3 //--- Please read help() below: ---
7 #include <opencv2/highgui/highgui.hpp>
9 #if defined WIN32 || defined _WIN32 || defined WINCE
18 #include <OpenGL/gl.h>
23 #include <opencv2/core/core.hpp>
30 cout << "\nThis demo demonstrates the use of the Qt enhanced version of the highgui GUI interface\n"
31 " and dang if it doesn't throw in the use of of the POSIT 3D tracking algorithm too\n"
32 "It works off of the video: cube4.avi\n"
33 "Using OpenCV version %s\n" << CV_VERSION << "\n\n"
34 " 1). This demo is mainly based on work from Javier Barandiaran Martirena\n"
35 " See this page http://code.opencv.org/projects/opencv/wiki/Posit.\n"
36 " 2). This is a demo to illustrate how to use **OpenGL Callback**.\n"
37 " 3). You need Qt binding to compile this sample with OpenGL support enabled.\n"
38 " 4). The features' detection is very basic and could highly be improved \n"
39 " (basic thresholding tuned for the specific video) but 2).\n"
40 " 5) THANKS TO Google Summer of Code 2010 for supporting this work!\n" << endl;
43 #define FOCAL_LENGTH 600
46 static void renderCube(float size)
50 glNormal3f( 0.0f, 0.0f, 1.0f);
51 glVertex3f( 0.0f, 0.0f, 0.0f);
52 glVertex3f( size, 0.0f, 0.0f);
53 glVertex3f( size, size, 0.0f);
54 glVertex3f( 0.0f, size, 0.0f);
56 glNormal3f( 0.0f, 0.0f,-1.0f);
57 glVertex3f( 0.0f, 0.0f, size);
58 glVertex3f( 0.0f, size, size);
59 glVertex3f( size, size, size);
60 glVertex3f( size, 0.0f, size);
62 glNormal3f( 0.0f, 1.0f, 0.0f);
63 glVertex3f( 0.0f, size, 0.0f);
64 glVertex3f( size, size, 0.0f);
65 glVertex3f( size, size, size);
66 glVertex3f( 0.0f, size, size);
68 glNormal3f( 0.0f,-1.0f, 0.0f);
69 glVertex3f( 0.0f, 0.0f, 0.0f);
70 glVertex3f( 0.0f, 0.0f, size);
71 glVertex3f( size, 0.0f, size);
72 glVertex3f( size, 0.0f, 0.0f);
74 glNormal3f( 1.0f, 0.0f, 0.0f);
75 glVertex3f( size, 0.0f, 0.0f);
76 glVertex3f( size, 0.0f, size);
77 glVertex3f( size, size, size);
78 glVertex3f( size, size, 0.0f);
80 glNormal3f(-1.0f, 0.0f, 0.0f);
81 glVertex3f( 0.0f, 0.0f, 0.0f);
82 glVertex3f( 0.0f, size, 0.0f);
83 glVertex3f( 0.0f, size, size);
84 glVertex3f( 0.0f, 0.0f, size);
89 static void on_opengl(void* param)
91 //Draw the object with the estimated pose
93 glScalef( 1.0f, 1.0f, -1.0f);
94 glMultMatrixf( (float*)param );
95 glEnable( GL_LIGHTING );
96 glEnable( GL_LIGHT0 );
98 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
99 renderCube( CUBE_SIZE );
101 glDisable( GL_LIGHTING );
104 static void initPOSIT(std::vector<CvPoint3D32f> *modelPoints)
106 //Create the model pointss
107 modelPoints->push_back(cvPoint3D32f(0.0f, 0.0f, 0.0f)); //The first must be (0,0,0)
108 modelPoints->push_back(cvPoint3D32f(0.0f, 0.0f, CUBE_SIZE));
109 modelPoints->push_back(cvPoint3D32f(CUBE_SIZE, 0.0f, 0.0f));
110 modelPoints->push_back(cvPoint3D32f(0.0f, CUBE_SIZE, 0.0f));
113 static void foundCorners(vector<CvPoint2D32f> *srcImagePoints, const Mat& source, Mat& grayImage)
115 cvtColor(source, grayImage, COLOR_RGB2GRAY);
116 GaussianBlur(grayImage, grayImage, Size(11,11), 0, 0);
117 normalize(grayImage, grayImage, 0, 255, NORM_MINMAX);
118 threshold(grayImage, grayImage, 26, 255, THRESH_BINARY_INV); //25
120 Mat MgrayImage = grayImage;
122 //MgrayImage = MgrayImage.clone();//deep copy
123 vector<vector<Point> > contours;
124 vector<Vec4i> hierarchy;
125 findContours(MgrayImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
128 vector<CvPoint2D32f> srcImagePoints_temp(4,cvPoint2D32f(0,0));
130 if (contours.size() == srcImagePoints_temp.size())
133 for(size_t i = 0 ; i<contours.size(); i++ )
138 for(size_t j = 0 ; j<contours[i].size(); j++ )
141 srcImagePoints_temp.at(i)=cvPoint2D32f(float(p.x)/contours[i].size(),float(p.y)/contours[i].size());
144 //Need to keep the same order
152 for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
154 if (srcImagePoints_temp.at(i).y > srcImagePoints_temp.at(index).y)
157 srcImagePoints->at(0) = srcImagePoints_temp.at(index);
161 for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
163 if (srcImagePoints_temp.at(i).x > srcImagePoints_temp.at(index).x)
166 srcImagePoints->at(1) = srcImagePoints_temp.at(index);
170 for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
172 if (srcImagePoints_temp.at(i).x < srcImagePoints_temp.at(index).x)
175 srcImagePoints->at(2) = srcImagePoints_temp.at(index);
179 for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
181 if (srcImagePoints_temp.at(i).y < srcImagePoints_temp.at(index).y)
184 srcImagePoints->at(3) = srcImagePoints_temp.at(index);
186 Mat Msource = source;
188 for(size_t i = 0 ; i<srcImagePoints_temp.size(); i++ )
191 circle(Msource,srcImagePoints->at(i),5,Scalar(0,0,255));
192 putText(Msource,ss.str(),srcImagePoints->at(i),FONT_HERSHEY_SIMPLEX,1,Scalar(0,0,255));
195 //new coordinate system in the middle of the frame and reversed (camera coordinate system)
196 srcImagePoints->at(i) = cvPoint2D32f(srcImagePoints_temp.at(i).x-source->width/2,source->height/2-srcImagePoints_temp.at(i).y);
202 static void createOpenGLMatrixFrom(float *posePOSIT,const CvMatr32f &rotationMatrix, const CvVect32f &translationVector)
206 //coordinate system returned is relative to the first 3D input point
207 for (int f=0; f<3; f++)
209 for (int c=0; c<3; c++)
211 posePOSIT[c*4+f] = rotationMatrix[f*3+c]; //transposed
217 posePOSIT[12] = translationVector[0];
218 posePOSIT[13] = translationVector[1];
219 posePOSIT[14] = translationVector[2];
226 VideoCapture video("cube4.avi");
227 CV_Assert(video.isOpened());
229 Mat source, grayImage;
233 namedWindow("original", WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
234 namedWindow("POSIT", WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
235 displayOverlay("POSIT", "We lost the 4 corners' detection quite often (the red circles disappear). This demo is only to illustrate how to use OpenGL callback.\n -- Press ESC to exit.", 10000);
237 float OpenGLMatrix[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
238 setOpenGlDrawCallback("POSIT",on_opengl,OpenGLMatrix);
240 vector<CvPoint3D32f> modelPoints;
241 initPOSIT(&modelPoints);
243 //Create the POSIT object with the model points
244 CvPOSITObject* positObject = cvCreatePOSITObject( &modelPoints[0], (int)modelPoints.size() );
246 CvMatr32f rotation_matrix = new float[9];
247 CvVect32f translation_vector = new float[3];
248 CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 100, 1.0e-4f);
250 vector<CvPoint2D32f> srcImagePoints(4,cvPoint2D32f(0,0));
253 while(waitKey(33) != 27)
256 imshow("original",source);
258 foundCorners(&srcImagePoints,source,grayImage);
259 cvPOSIT( positObject, &srcImagePoints[0], FOCAL_LENGTH, criteria, rotation_matrix, translation_vector );
260 createOpenGLMatrixFrom(OpenGLMatrix,rotation_matrix,translation_vector);
262 imshow("POSIT",source);
264 if (VideoCapture::get(video,CV_CAP_PROP_POS_AVI_RATIO)>0.99)
265 VideoCapture::get(video,CV_CAP_PROP_POS_AVI_RATIO,0);
269 cvReleasePOSITObject(&positObject);