opencv/samples/cpp/Qt_sample/qt_opengl.cpp

277 lines
8.7 KiB
C++
Raw Normal View History

2012-10-17 07:18:30 +08:00
//Yannick Verdie 2010
//--- Please read help() below: ---
#include <iostream>
#include <vector>
2013-11-20 18:57:21 +08:00
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
2013-11-20 18:57:21 +08:00
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/legacy/compat.hpp>
#if defined WIN32 || defined _WIN32 || defined WINCE
#include <windows.h>
#undef small
#undef min
#undef max
#undef abs
#endif
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
2012-10-17 07:18:30 +08:00
using namespace std;
using namespace cv;
static void help()
2012-10-17 07:18:30 +08:00
{
cout << "\nThis demo demonstrates the use of the Qt enhanced version of the highgui GUI interface\n"
" and dang if it doesn't throw in the use of of the POSIT 3D tracking algorithm too\n"
"It works off of the video: cube4.avi\n"
2014-02-13 04:17:15 +08:00
"Using OpenCV version " << CV_VERSION << "\n\n"
" 1). This demo is mainly based on work from Javier Barandiaran Martirena\n"
" See this page http://code.opencv.org/projects/opencv/wiki/Posit.\n"
" 2). This is a demo to illustrate how to use **OpenGL Callback**.\n"
" 3). You need Qt binding to compile this sample with OpenGL support enabled.\n"
" 4). The features' detection is very basic and could highly be improved \n"
" (basic thresholding tuned for the specific video) but 2).\n"
" 5) THANKS TO Google Summer of Code 2010 for supporting this work!\n" << endl;
2012-10-17 07:18:30 +08:00
}
#define FOCAL_LENGTH 600
#define CUBE_SIZE 10
static void renderCube(float size)
2012-10-17 07:18:30 +08:00
{
glBegin(GL_QUADS);
// Front Face
glNormal3f( 0.0f, 0.0f, 1.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( size, 0.0f, 0.0f);
glVertex3f( size, size, 0.0f);
glVertex3f( 0.0f, size, 0.0f);
// Back Face
glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f( 0.0f, 0.0f, size);
glVertex3f( 0.0f, size, size);
glVertex3f( size, size, size);
glVertex3f( size, 0.0f, size);
// Top Face
glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 0.0f, size, 0.0f);
glVertex3f( size, size, 0.0f);
glVertex3f( size, size, size);
glVertex3f( 0.0f, size, size);
// Bottom Face
glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 0.0f, size);
glVertex3f( size, 0.0f, size);
glVertex3f( size, 0.0f, 0.0f);
// Right face
glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( size, 0.0f, 0.0f);
glVertex3f( size, 0.0f, size);
glVertex3f( size, size, size);
glVertex3f( size, size, 0.0f);
// Left Face
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, size, 0.0f);
glVertex3f( 0.0f, size, size);
glVertex3f( 0.0f, 0.0f, size);
glEnd();
}
static void on_opengl(void* param)
2012-10-17 07:18:30 +08:00
{
//Draw the object with the estimated pose
glLoadIdentity();
glScalef( 1.0f, 1.0f, -1.0f);
glMultMatrixf( (float*)param );
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glEnable( GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
renderCube( CUBE_SIZE );
glDisable(GL_BLEND);
glDisable( GL_LIGHTING );
}
static void initPOSIT(std::vector<CvPoint3D32f> *modelPoints)
2012-10-17 07:18:30 +08:00
{
//Create the model pointss
modelPoints->push_back(cvPoint3D32f(0.0f, 0.0f, 0.0f)); //The first must be (0,0,0)
modelPoints->push_back(cvPoint3D32f(0.0f, 0.0f, CUBE_SIZE));
modelPoints->push_back(cvPoint3D32f(CUBE_SIZE, 0.0f, 0.0f));
modelPoints->push_back(cvPoint3D32f(0.0f, CUBE_SIZE, 0.0f));
}
static void foundCorners(vector<CvPoint2D32f> *srcImagePoints, const Mat& source, Mat& grayImage)
2012-10-17 07:18:30 +08:00
{
cvtColor(source, grayImage, COLOR_RGB2GRAY);
GaussianBlur(grayImage, grayImage, Size(11,11), 0, 0);
normalize(grayImage, grayImage, 0, 255, NORM_MINMAX);
threshold(grayImage, grayImage, 26, 255, THRESH_BINARY_INV); //25
2012-10-17 07:18:30 +08:00
Mat MgrayImage = grayImage;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(MgrayImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
Point p;
vector<CvPoint2D32f> srcImagePoints_temp(4,cvPoint2D32f(0,0));
if (contours.size() == srcImagePoints_temp.size())
{
for(size_t i = 0 ; i<contours.size(); i++ )
2012-10-17 07:18:30 +08:00
{
p.x = p.y = 0;
for(size_t j = 0 ; j<contours[i].size(); j++ )
2012-10-17 07:18:30 +08:00
p+=contours[i][j];
srcImagePoints_temp.at(i)=cvPoint2D32f(float(p.x)/contours[i].size(),float(p.y)/contours[i].size());
}
//Need to keep the same order
//> y = 0
//> x = 1
//< x = 2
//< y = 3
//get point 0;
size_t index = 0;
for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
2012-10-17 07:18:30 +08:00
{
if (srcImagePoints_temp.at(i).y > srcImagePoints_temp.at(index).y)
index = i;
}
srcImagePoints->at(0) = srcImagePoints_temp.at(index);
//get point 1;
index = 0;
for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
2012-10-17 07:18:30 +08:00
{
if (srcImagePoints_temp.at(i).x > srcImagePoints_temp.at(index).x)
index = i;
}
srcImagePoints->at(1) = srcImagePoints_temp.at(index);
//get point 2;
index = 0;
for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
2012-10-17 07:18:30 +08:00
{
if (srcImagePoints_temp.at(i).x < srcImagePoints_temp.at(index).x)
index = i;
}
srcImagePoints->at(2) = srcImagePoints_temp.at(index);
//get point 3;
index = 0;
for(size_t i = 1 ; i<srcImagePoints_temp.size(); i++ )
2012-10-17 07:18:30 +08:00
{
if (srcImagePoints_temp.at(i).y < srcImagePoints_temp.at(index).y)
index = i;
}
srcImagePoints->at(3) = srcImagePoints_temp.at(index);
Mat Msource = source;
stringstream ss;
for(size_t i = 0 ; i<srcImagePoints_temp.size(); i++ )
2012-10-17 07:18:30 +08:00
{
ss<<i;
circle(Msource,srcImagePoints->at(i),5,Scalar(0,0,255));
putText(Msource,ss.str(),srcImagePoints->at(i),FONT_HERSHEY_SIMPLEX,1,Scalar(0,0,255));
2012-10-17 07:18:30 +08:00
ss.str("");
//new coordinate system in the middle of the frame and reversed (camera coordinate system)
2013-11-20 18:57:21 +08:00
srcImagePoints->at(i) = cvPoint2D32f(srcImagePoints_temp.at(i).x-source.cols/2,source.rows/2-srcImagePoints_temp.at(i).y);
2012-10-17 07:18:30 +08:00
}
}
}
static void createOpenGLMatrixFrom(float *posePOSIT,const CvMatr32f &rotationMatrix, const CvVect32f &translationVector)
2012-10-17 07:18:30 +08:00
{
//coordinate system returned is relative to the first 3D input point
for (int f=0; f<3; f++)
for (int c=0; c<3; c++)
posePOSIT[c*4+f] = rotationMatrix[f*3+c]; //transposed
2014-02-13 04:17:15 +08:00
2012-10-17 07:18:30 +08:00
posePOSIT[3] = 0.0;
posePOSIT[7] = 0.0;
posePOSIT[11] = 0.0;
posePOSIT[12] = translationVector[0];
posePOSIT[13] = translationVector[1];
posePOSIT[14] = translationVector[2];
posePOSIT[15] = 1.0;
}
int main(void)
2012-10-17 07:18:30 +08:00
{
help();
2012-10-17 07:18:30 +08:00
2014-02-13 04:17:15 +08:00
string fileName = "cube4.avi";
VideoCapture video(fileName);
if (!video.isOpened())
{
cerr << "Video file " << fileName << " could not be opened" << endl;
return EXIT_FAILURE;
}
2012-10-17 07:18:30 +08:00
2014-02-13 04:17:15 +08:00
Mat source, grayImage;
video >> source;
namedWindow("original", WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
2014-02-13 04:17:15 +08:00
namedWindow("POSIT", WINDOW_OPENGL | CV_WINDOW_FREERATIO);
resizeWindow("POSIT", source.cols, source.rows);
2014-02-13 04:17:15 +08:00
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);
float OpenGLMatrix[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
setOpenGlDrawCallback("POSIT", on_opengl, OpenGLMatrix);
2012-10-17 07:18:30 +08:00
vector<CvPoint3D32f> modelPoints;
initPOSIT(&modelPoints);
//Create the POSIT object with the model points
CvPOSITObject* positObject = cvCreatePOSITObject( &modelPoints[0], (int)modelPoints.size() );
CvMatr32f rotation_matrix = new float[9];
CvVect32f translation_vector = new float[3];
2014-02-13 04:17:15 +08:00
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 100, 1e-4f);
vector<CvPoint2D32f> srcImagePoints(4, cvPoint2D32f(0, 0));
2012-10-17 07:18:30 +08:00
2014-02-13 04:17:15 +08:00
while (waitKey(33) != 27)
2012-10-17 07:18:30 +08:00
{
video >> source;
2014-02-13 04:17:15 +08:00
if (source.empty())
break;
imshow("original", source);
2012-10-17 07:18:30 +08:00
foundCorners(&srcImagePoints,source,grayImage);
cvPOSIT( positObject, &srcImagePoints[0], FOCAL_LENGTH, criteria, rotation_matrix, translation_vector );
2014-02-13 04:17:15 +08:00
createOpenGLMatrixFrom(OpenGLMatrix, rotation_matrix, translation_vector);
2012-10-17 07:18:30 +08:00
imshow("POSIT",source);
2012-10-17 07:18:30 +08:00
2013-11-20 18:57:21 +08:00
if (video.get(CV_CAP_PROP_POS_AVI_RATIO) > 0.99)
video.set(CV_CAP_PROP_POS_AVI_RATIO, 0);
2012-10-17 07:18:30 +08:00
}
2014-02-13 04:17:15 +08:00
setOpenGlDrawCallback("POSIT", 0, 0);
destroyAllWindows();
2012-10-17 07:18:30 +08:00
cvReleasePOSITObject(&positObject);
return 0;
}