1 /*******************************************************************************
2 *   Copyright 2013-2014 EPFL                                                   *
3 *   Copyright 2013-2014 Quentin Bonnard                                        *
4 *                                                                              *
5 *   This file is part of chilitags.                                            *
6 *                                                                              *
7 *   Chilitags is free software: you can redistribute it and/or modify          *
8 *   it under the terms of the Lesser GNU General Public License as             *
9 *   published by the Free Software Foundation, either version 3 of the         *
10 *   License, or (at your option) any later version.                            *
11 *                                                                              *
12 *   Chilitags is distributed in the hope that it will be useful,               *
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
15 *   GNU Lesser General Public License for more details.                        *
16 *                                                                              *
17 *   You should have received a copy of the GNU Lesser General Public License   *
18 *   along with Chilitags.  If not, see <http://www.gnu.org/licenses/>.         *
19 *******************************************************************************/
20 
21 // This file serves as an illustration of how to use Chilitags
22 
23 
24 // The Chilitags header
25 #include <chilitags.hpp>
26 
27 #ifdef OPENCV3
28 #include <opencv2/core/utility.hpp> // getTickCount...
29 #include <opencv2/imgproc/imgproc.hpp>
30 #endif
31 
32 #include <opencv2/core/core_c.h> // CV_AA
33 #include <opencv2/core/core.hpp>
34 
35 // OpenCV goodness for I/O
36 #include <opencv2/highgui/highgui.hpp>
37 
38 #include <iostream>
39 #include <csignal>
40 
41 
42 bool sRunning = true;
43 cv::VideoCapture capture;
44 
quitFunction(int sig)45 void quitFunction(int sig) {
46     std::cout << "Caught interrupt. Closing" << std::endl;
47     capture.release();
48     sRunning = false;
49 }
50 
main(int argc,char * argv[])51 int main(int argc, char* argv[])
52 {
53     signal(SIGINT, quitFunction);
54 
55     // Simple parsing of the parameters related to the image acquisition
56     int xRes = 640;
57     int yRes = 480;
58     int cameraIndex = 0;
59     if (argc > 2) {
60         xRes = std::atoi(argv[1]);
61         yRes = std::atoi(argv[2]);
62     }
63     if (argc > 3) {
64         cameraIndex = std::atoi(argv[3]);
65     }
66 
67     // The source of input images
68     capture.open(cameraIndex);
69     if (!capture.isOpened())
70     {
71         std::cerr << "Unable to initialise video capture." << std::endl;
72         return 1;
73     }
74 #ifdef OPENCV3
75     capture.set(cv::CAP_PROP_FRAME_WIDTH, xRes);
76     capture.set(cv::CAP_PROP_FRAME_HEIGHT, yRes);
77 #else
78     capture.set(CV_CAP_PROP_FRAME_WIDTH, xRes);
79     capture.set(CV_CAP_PROP_FRAME_HEIGHT, yRes);
80 #endif
81     cv::Mat inputImage;
82 
83     // The tag detection happens in the Chilitags class.
84     chilitags::Chilitags chilitags;
85 
86     // The detection is not perfect, so if a tag is not detected during one frame,
87     // the tag will shortly disappears, which results in flickering.
88     // To address this, Chilitags "cheats" by keeping tags for n frames
89     // at the same position. When tags disappear for more than 5 frames,
90     // Chilitags actually removes it.
91     // Here, we cancel this to show the raw detection results.
92     chilitags.setFilter(0, 0.0f);
93 
94     cv::namedWindow("DisplayChilitags");
95     // Main loop, exiting when 'q is pressed'
96     for (; 'q' != (char) cv::waitKey(1) && sRunning; ) {
97 
98         // Capture a new image.
99         capture.read(inputImage);
100 
101         // Start measuring the time needed for the detection
102         int64 startTime = cv::getTickCount();
103 
104         // Detect tags on the current image (and time the detection);
105         // The resulting map associates tag ids (between 0 and 1023)
106         // to four 2D points corresponding to the corners positions
107         // in the picture.
108         chilitags::TagCornerMap tags = chilitags.find(inputImage);
109 
110         // Measure the processing time needed for the detection
111         int64 endTime = cv::getTickCount();
112         float processingTime = 1000.0f*((float) endTime - startTime)/cv::getTickFrequency();
113 
114 
115         // Now we start using the result of the detection.
116 
117         // First, we set up some constants related to the information overlaid
118         // on the captured image
119         const static cv::Scalar COLOR(255, 0, 255);
120         // OpenCv can draw with sub-pixel precision with fixed point coordinates
121         static const int SHIFT = 16;
122         static const float PRECISION = 1<<SHIFT;
123 
124         // We dont want to draw directly on the input image, so we clone it
125         cv::Mat outputImage = inputImage.clone();
126 
127         for (const std::pair<int, chilitags::Quad> & tag : tags) {
128 
129             int id = tag.first;
130             // We wrap the corner matrix into a datastructure that allows an
131             // easy access to the coordinates
132             const cv::Mat_<cv::Point2f> corners(tag.second);
133 
134             // We start by drawing the borders of the tag
135             for (size_t i = 0; i < 4; ++i) {
136                 cv::line(
137                     outputImage,
138                     PRECISION*corners(i),
139                     PRECISION*corners((i+1)%4),
140 #ifdef OPENCV3
141                     COLOR, 1, cv::LINE_AA, SHIFT);
142 #else
143                     COLOR, 1, CV_AA, SHIFT);
144 #endif
145             }
146 
147             // Other points can be computed from the four corners of the Quad.
148             // Chilitags are oriented. It means that the points 0,1,2,3 of
149             // the Quad coordinates are consistently the top-left, top-right,
150             // bottom-right and bottom-left corners.
151             // (i.e. clockwise, starting from top-left)
152             // Using this, we can compute (an approximation of) the center of
153             // tag.
154             cv::Point2f center = 0.5f*(corners(0) + corners(2));
155             cv::putText(outputImage, cv::format("%d", id), center,
156                         cv::FONT_HERSHEY_SIMPLEX, 0.5f, COLOR);
157         }
158 
159         // Some stats on the current frame (resolution and processing time)
160         cv::putText(outputImage,
161                     cv::format("%dx%d %4.0f ms (press q to quit)",
162                                outputImage.cols, outputImage.rows,
163                                processingTime),
164                     cv::Point(32,32),
165                     cv::FONT_HERSHEY_SIMPLEX, 0.5f, COLOR);
166 
167         // Finally...
168         cv::imshow("DisplayChilitags", outputImage);
169     }
170 
171     cv::destroyWindow("DisplayChilitags");
172     capture.release();
173 
174     return 0;
175 }
176