全文参考:http://blog.csdn.net/sky_freebird/article/details/6695059
运用OpenGL实现二维图像的三维点云图显示。
#include
#include
#include
#include
#include
//#include
//#include
#include
using namespace std;
float imgdata[480][640]; //注意维度,第一维表示高度,第二维表示宽度
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);
gluLookAt (0.0, 0.0, 7.0, -0.5, 0.5, 0.0, 0.0, 1.0, 0.0);
//该函数定义一个视图矩阵,并与当前矩阵相乘。
//第一组eyex, eyey,eyez 相机(观察者眼睛)在世界坐标的位置
//第二组centerx,centery,centerz 相机镜头对准的物体在世界坐标的位置(观察者观察的方向)
//第三组upx,upy,upz 相机向上的方向在世界坐标中的方向
//http://www.cnblogs.com/chengmin/archive/2011/09/12/2174004.html
//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;iwidth;
h=imgGrey->height;
displayDisparity(imgGrey);
cvNamedWindow("3D disparity image", CV_WINDOW_AUTOSIZE );
cvShowImage( "3D disparity image", imgGrey );
//------------------OpenGL-------------------------
glutInit(&argc, argv);//initialize the GLUT library
glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); //设置初始化显示模式
//GLUT_RGBA颜色模式;GLUT_SINGLE单缓存模式,GLUT_DEPTH深度缓存模式
//单缓冲,实际上就是将所有的绘图指令在窗口上执行,就是直接在窗口上绘图,这样的绘图效率是比较慢的,如果使用单缓冲,而电脑比较慢,你会看到屏幕的闪烁。
//双缓冲,实际上的绘图指令是在一个缓冲区完成,这里的绘图非常的快,在绘图指令完成之后,再通过交换指令把完成的图形立即显示在屏幕上,这就避免了出现绘图的不完整,同时效率很高。
//一般用OpenGL绘图都是用双缓冲,单缓冲一般只用于显示单独的一副非动态的图像。
//深度缓冲:http://zh.wikipedia.org/wiki/%E6%B7%B1%E5%BA%A6%E7%BC%93%E5%86%B2
glutInitWindowPosition(600,200); //设置初始化窗口位置
glutInitWindowSize(640,480); //设置初始化窗口大小
glutCreateWindow("3D disparity image"); //创建窗口
glutDisplayFunc(renderScene);
//glutDisplayFunc函数用于注册一个绘图函数, 这样操作系统在必要时刻就会对窗体进行重新绘制操作。类似于windows程序设计中处理WM_PAINT消息。
glutReshapeFunc (reshape);
//glutReshapeFunc了解:http://zhidao.baidu.com/link?url=K_GPs7mXbe6H1M_OA-YibtC7-1GNqv8efOKC_jMDxiK7kRSHt_zBzH5eIQaao0tK9RQGegwX2r_CH2N5nSsufK
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutSpecialFunc(special);
glutMainLoop(); //glutMainLoop进入GLUT事件处理循环,让所有的与“事件”有关的函数调用无限循环。
//glutMainLoopEvent();
//cvWaitKey(0);
//release opencv stuff.
//system("pause");
cvReleaseImage(&imgGrey);
cvDestroyWindow("3D disparity image");
return 0;
}
要实现二维图像的三维显示,需要把相关的地方改一下。
RGB图像,需要将数组定义为3维数组。
float imgdata[480][640][3];
相关函数需要改一下:
void displayDisparity(IplImage* disparity){
//double xyscale=100;
int j=0;
int i=0;
CvScalar s;
//accessing the image pixels
for (i=0;i
glColor3f(imgdata[i][j][0]/255, imgdata[i][j][1]/255, imgdata[i][j][2]/255);//red,green,blue
glBegin(GL_POINTS);//GL_POINTS
for (int i=0;i如果有扫描到的物体表面高度信息,可以在此处赋高度信息;此处以blue分量作为z坐标
/*z=(imgdata[i][j])/scalar;*/
glVertex3f(x,y,z); //坐标视角函数
}
}
glEnd();
下图旋转了一定角度,可以看出blue分量值越大,Z坐标值越大,blue的位置越靠前(右手坐标系,Z正方向为从电脑向人的指向)。