基于OpenGL和OpenCV的三维显示
最近想用OpenCV+OpenGL+QT实现三维显示,但是一直都么有弄出来,今天看了一篇博客,感觉很不错,拿来分享下。
简而言之,这段代码是如何从disparity image获得点云数据(Point cloud)并利用OpenGL显示出来。 如果想使用代码,请确认OpenGL和OpenCV都安装在电脑中。我使用的是Visual Studio 2008...(关于如何安装OPENGL 请参考http://techhouse.brown.edu/~dmorris/cs148_summer_2005/handouts/OpenGL-Install-Guide.pdf)
//
//Huang,Haiqiao coded on Dec.2009
#include 'stdafx.h'
#include <iostream>
#include <stdlib.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;
float imgdata[500][500];
int w=0;
int h=0;
float scalar=50;//scalar of converting pixel color to float coordinates
void renderScene(void) {
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();// Reset the coordinate system before modifying
gluLookAt (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
//glRotatef(-30, 0.0, 1.0, 0.0); //rotate about the x axis
glRotatef(-180, 0.0, 0.0, 1.0); //rotate about the z axis
glRotatef(-180, 0.0, 1.0, 0.0); //rotate about the y axis
float imageCenterX=w*.5;
float imageCenterY=h*.5;
float x,y,z;
glPointSize(1.0);
glBegin(GL_POINTS);//GL_POINTS
for (int i=0;i<h;i++){
for (int j=0;j<w;j++){
// color interpolation
glColor3f(1-imgdata[i][j]/255, imgdata[i][j]/255, imgdata[i][j]/255);
x=((float)j-imageCenterX)/scalar;
y=((float)i-imageCenterY)/scalar;
z=imgdata[i][j]/scalar;
glVertex3f(x,y,z);
}
}
glEnd();
glFlush();
}
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
}
void displayDisparity(IplImage* disparity){
double xyscale=100;
int j=0;
int i=0;
CvScalar s;
//accessing the image pixels
for (i=0;i<h;i++){
for (j=0;j<w;j++){
s=cvGet2D(disparity,i,j);
imgdata[i][j]=s.val[0];//for disparity is a grey image.
}
}
}
int main(int argc, char *argv[])
{
cout << 'OpenCV and OpenGL working together!'<<endl;
char* filename='D:\\OpenCV_stuff\\SampleImages\\tsuDisparity.bmp';
IplImage* imgGrey = cvLoadImage(filename,0); //read image as a grey one
if (imgGrey==NULL){
cout << 'No valid image input.'<<endl;
char c=getchar();
return 1;
}
w=imgGrey->width;
h=imgGrey->height;
displayDisparity(imgGrey);
cvNamedWindow('original', CV_WINDOW_AUTOSIZE );
cvShowImage( 'original', imgGrey );
//------------------OpenGL-------------------------
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow('3D disparity image');
glutDisplayFunc(renderScene);
glutReshapeFunc (reshape);
glutMainLoop();
cvWaitKey(0);
//release opencv stuff.
cvReleaseImage(&imgGrey);
cvDestroyWindow('Original');
return 0;
}
在此基础上,我又综合了一小段代码,随着鼠标移动,可以从多个视角观看生成的三维点云图(VS中还要加上预编译头):)
#include <iostream>
#include <stdlib.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <math.h>
#include <gl/glut.h>
using namespace std;
float imgdata[500][500];
int w=0;
int h=0;
float scalar=50;//scalar of converting pixel color to float coordinates
#define pi 3.1415926
bool mouseisdown=false;
bool loopr=false;
int mx,my;
int ry=10;
int rx=10;
void timer(int p)
{
ry-=5;
//marks the current window as needing to be redisplayed.
glutPostRedisplay();
if (loopr)
glutTimerFunc(200,timer,0);
}
void mouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON)
{
if(state == GLUT_DOWN)
{
mouseisdown=true;
loopr=false;
}
else
{
mouseisdown=false;
}
}
if (button== GLUT_RIGHT_BUTTON)
if(state == GLUT_DOWN)
{
loopr=true; glutTimerFunc(200,timer,0);
}
}
void motion(int x, int y)
{
if(mouseisdown==true)
{
ry+=x-mx;
rx+=y-my;
mx=x;
my=y;
glutPostRedisplay();
}
}
void special(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_LEFT:
ry-=5;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT:
ry+=5;
glutPostRedisplay();
break;
case GLUT_KEY_UP:
rx+=5;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
rx-=5;
glutPostRedisplay();
break;
}
}
void renderScene(void) {
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();// Reset the coordinate system before modifying
gluLookAt (0.0, 0.0, 7.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0);
//to invert the image
glRotatef(ry,0,1,0);
glRotatef(rx-180,1,0,0);
float imageCenterX=w*.5;
float imageCenterY=h*.5;
float x,y,z;
glPointSize(1.0);
glBegin(GL_POINTS);//GL_POINTS
for (int i=0;i<h;i++){
for (int j=0;j<w;j++){
// color interpolation
glColor3f(1-imgdata[i][j]/255, imgdata[i][j]/255, imgdata[i][j]/255);//red,green,blue
x=((float)j-imageCenterX)/scalar;
y=((float)i-imageCenterY)/scalar;
z=(255-imgdata[i][j])/scalar;
glVertex3f(x,y,z);
}
}
glEnd();
glFlush();
}
void reshape (int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h);//set viewpoint
glMatrixMode (GL_PROJECTION);//specify which matrix is the current matrix
glLoadIdentity ();//replace the current matrix with the identity matrix
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
}
void displayDisparity(IplImage* disparity){
//double xyscale=100;
int j=0;
int i=0;
CvScalar s;
//accessing the image pixels
for (i=0;i<h;i++){
for (j=0;j<w;j++){
s=cvGet2D(disparity,i,j);
imgdata[i][j]=s.val[0];//for disparity is a grey image.
//cout << imgdata[i][j]<<endl;
}
}
}
int main(int argc, char *argv[])
{
cout << 'OpenCV and OpenGL works together!'<<endl;
char* filename=argv[1];
IplImage* imgGrey = cvLoadImage(filename,0); //read image as a grey one
if (imgGrey==NULL){
cout << 'No valid image input.'<<endl;
return 1;
}
w=imgGrey->width;
h=imgGrey->height;
displayDisparity(imgGrey);
cvNamedWindow('original', CV_WINDOW_AUTOSIZE );
cvShowImage( 'original', imgGrey );
//------------------OpenGL-------------------------
glutInit(&argc, argv);//initialize the GLUT library
glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);//sets the initial display mode
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow('3D disparity image');
glutDisplayFunc(renderScene);
glutReshapeFunc (reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutSpecialFunc(special);
glutMainLoop();
cvWaitKey(0);
//release opencv stuff.
cvReleaseImage(&imgGrey);
cvDestroyWindow('Original');
return 0;
}
赞 (0)