2 // --- Please read help() below: ---
7 #include <opencv2/calib3d/calib3d.hpp>
8 #include <opencv2/calib3d/calib3d_c.h>
9 #include <opencv2/core/core.hpp>
10 #include <opencv2/highgui/highgui.hpp>
11 #include <opencv2/imgproc/imgproc.hpp>
12 #include <opencv2/legacy/compat.hpp>
15 #include <OpenGL/gl.h>
25 cout << "This demo demonstrates the use of the Qt enhanced version of the highgui GUI interface\n"
26 "and dang if it doesn't throw in the use of of the POSIT 3D tracking algorithm too\n"
27 "It works off of the video: cube4.avi\n"
28 "Using OpenCV version " << CV_VERSION << "\n\n"
30 " 1) This demo is mainly based on work from Javier Barandiaran Martirena\n"
31 " See this page http://code.opencv.org/projects/opencv/wiki/Posit.\n"
32 " 2) This is a demo to illustrate how to use **OpenGL Callback**.\n"
33 " 3) You need Qt binding to compile this sample with OpenGL support enabled.\n"
34 " 4) The features' detection is very basic and could highly be improved\n"
35 " (basic thresholding tuned for the specific video) but 2).\n"
36 " 5) Thanks to Google Summer of Code 2010 for supporting this work!\n" << endl;
39 #define FOCAL_LENGTH 600
42 static void renderCube(float size)
46 glNormal3f( 0.0f, 0.0f, 1.0f);
47 glVertex3f( 0.0f, 0.0f, 0.0f);
48 glVertex3f( size, 0.0f, 0.0f);
49 glVertex3f( size, size, 0.0f);
50 glVertex3f( 0.0f, size, 0.0f);
52 glNormal3f( 0.0f, 0.0f,-1.0f);
53 glVertex3f( 0.0f, 0.0f, size);
54 glVertex3f( 0.0f, size, size);
55 glVertex3f( size, size, size);
56 glVertex3f( size, 0.0f, size);
58 glNormal3f( 0.0f, 1.0f, 0.0f);
59 glVertex3f( 0.0f, size, 0.0f);
60 glVertex3f( size, size, 0.0f);
61 glVertex3f( size, size, size);
62 glVertex3f( 0.0f, size, size);
64 glNormal3f( 0.0f,-1.0f, 0.0f);
65 glVertex3f( 0.0f, 0.0f, 0.0f);
66 glVertex3f( 0.0f, 0.0f, size);
67 glVertex3f( size, 0.0f, size);
68 glVertex3f( size, 0.0f, 0.0f);
70 glNormal3f( 1.0f, 0.0f, 0.0f);
71 glVertex3f( size, 0.0f, 0.0f);
72 glVertex3f( size, 0.0f, size);
73 glVertex3f( size, size, size);
74 glVertex3f( size, size, 0.0f);
76 glNormal3f(-1.0f, 0.0f, 0.0f);
77 glVertex3f( 0.0f, 0.0f, 0.0f);
78 glVertex3f( 0.0f, size, 0.0f);
79 glVertex3f( 0.0f, size, size);
80 glVertex3f( 0.0f, 0.0f, size);
84 static void on_opengl(void* param)
86 //Draw the object with the estimated pose
88 glScalef( 1.0f, 1.0f, -1.0f);
89 glMultMatrixf( (float*)param );
90 glEnable( GL_LIGHTING );
91 glEnable( GL_LIGHT0 );
93 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
94 renderCube( CUBE_SIZE );
96 glDisable( GL_LIGHTING );
99 static void initPOSIT(std::vector<CvPoint3D32f> * modelPoints)
101 // Create the model pointss
102 modelPoints->push_back(cvPoint3D32f(0.0f, 0.0f, 0.0f)); // The first must be (0, 0, 0)
103 modelPoints->push_back(cvPoint3D32f(0.0f, 0.0f, CUBE_SIZE));
104 modelPoints->push_back(cvPoint3D32f(CUBE_SIZE, 0.0f, 0.0f));
105 modelPoints->push_back(cvPoint3D32f(0.0f, CUBE_SIZE, 0.0f));
108 static void foundCorners(vector<CvPoint2D32f> * srcImagePoints, const Mat & source, Mat & grayImage)
110 cvtColor(source, grayImage, COLOR_RGB2GRAY);
111 GaussianBlur(grayImage, grayImage, Size(11, 11), 0, 0);
112 normalize(grayImage, grayImage, 0, 255, NORM_MINMAX);
113 threshold(grayImage, grayImage, 26, 255, THRESH_BINARY_INV); //25
115 Mat MgrayImage = grayImage;
116 vector<vector<Point> > contours;
117 vector<Vec4i> hierarchy;
118 findContours(MgrayImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
121 vector<CvPoint2D32f> srcImagePoints_temp(4, cvPoint2D32f(0, 0));
123 if (contours.size() == srcImagePoints_temp.size())
125 for (size_t i = 0; i < contours.size(); i++ )
129 for (size_t j = 0 ; j < contours[i].size(); j++)
132 srcImagePoints_temp.at(i) = cvPoint2D32f(float(p.x) / contours[i].size(), float(p.y) / contours[i].size());
135 // Need to keep the same order
143 for (size_t i = 1 ; i<srcImagePoints_temp.size(); i++)
144 if (srcImagePoints_temp.at(i).y > srcImagePoints_temp.at(index).y)
146 srcImagePoints->at(0) = srcImagePoints_temp.at(index);
150 for (size_t i = 1 ; i<srcImagePoints_temp.size(); i++)
151 if (srcImagePoints_temp.at(i).x > srcImagePoints_temp.at(index).x)
153 srcImagePoints->at(1) = srcImagePoints_temp.at(index);
157 for (size_t i = 1 ; i<srcImagePoints_temp.size(); i++)
158 if (srcImagePoints_temp.at(i).x < srcImagePoints_temp.at(index).x)
160 srcImagePoints->at(2) = srcImagePoints_temp.at(index);
164 for (size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
165 if (srcImagePoints_temp.at(i).y < srcImagePoints_temp.at(index).y)
167 srcImagePoints->at(3) = srcImagePoints_temp.at(index);
169 Mat Msource = source;
171 for (size_t i = 0; i<srcImagePoints_temp.size(); i++ )
174 circle(Msource, srcImagePoints->at(i), 5, Scalar(0, 0, 255));
175 putText(Msource, ss.str(), srcImagePoints->at(i), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 255));
178 // new coordinate system in the middle of the frame and reversed (camera coordinate system)
179 srcImagePoints->at(i) = cvPoint2D32f(srcImagePoints_temp.at(i).x - source.cols / 2,
180 source.rows / 2 - srcImagePoints_temp.at(i).y);
185 static void createOpenGLMatrixFrom(float * posePOSIT, const CvMatr32f & rotationMatrix,
186 const CvVect32f & translationVector)
188 // coordinate system returned is relative to the first 3D input point
189 for (int f = 0; f < 3; f++)
190 for (int c = 0; c < 3; c++)
191 posePOSIT[c * 4 + f] = rotationMatrix[f * 3 + c]; // transposed
193 posePOSIT[3] = translationVector[0];
194 posePOSIT[7] = translationVector[1];
195 posePOSIT[11] = translationVector[2];
196 posePOSIT[12] = 0.0f;
197 posePOSIT[13] = 0.0f;
198 posePOSIT[14] = 0.0f;
199 posePOSIT[15] = 1.0f;
206 string fileName = "cube4.avi";
207 VideoCapture video(fileName);
208 if (!video.isOpened())
210 cerr << "Video file " << fileName << " could not be opened" << endl;
214 Mat source, grayImage;
217 namedWindow("Original", WINDOW_AUTOSIZE | WINDOW_FREERATIO);
218 namedWindow("POSIT", WINDOW_OPENGL | WINDOW_FREERATIO);
219 resizeWindow("POSIT", source.cols, source.rows);
221 displayOverlay("POSIT", "We lost the 4 corners' detection quite often (the red circles disappear).\n"
222 "This demo is only to illustrate how to use OpenGL callback.\n"
223 " -- Press ESC to exit.", 10000);
225 float OpenGLMatrix[] = { 0, 0, 0, 0,
229 setOpenGlContext("POSIT");
230 setOpenGlDrawCallback("POSIT", on_opengl, OpenGLMatrix);
232 vector<CvPoint3D32f> modelPoints;
233 initPOSIT(&modelPoints);
235 // Create the POSIT object with the model points
236 CvPOSITObject* positObject = cvCreatePOSITObject( &modelPoints[0], (int)modelPoints.size());
238 CvMatr32f rotation_matrix = new float[9];
239 CvVect32f translation_vector = new float[3];
240 CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 100, 1e-4f);
241 vector<CvPoint2D32f> srcImagePoints(4, cvPoint2D32f(0, 0));
243 while (waitKey(33) != 27)
249 imshow("Original", source);
251 foundCorners(&srcImagePoints, source, grayImage);
252 cvPOSIT(positObject, &srcImagePoints[0], FOCAL_LENGTH, criteria, rotation_matrix, translation_vector);
253 createOpenGLMatrixFrom(OpenGLMatrix, rotation_matrix, translation_vector);
255 updateWindow("POSIT");
257 if (video.get(CAP_PROP_POS_AVI_RATIO) > 0.99)
258 video.set(CAP_PROP_POS_AVI_RATIO, 0);
261 setOpenGlDrawCallback("POSIT", NULL, NULL);
263 cvReleasePOSITObject(&positObject);
265 delete[]rotation_matrix;
266 delete[]translation_vector;