关于OpenNI2和OpenCV2的那些事——获取三维点云数据并用OpenGL表示

上一节呢,我们利用openni2获得了彩色图像和深度图像,这一节我们用openni2的转换函数将深度数据转换为三维点云,然后用彩色数据作为纹理将点云用opengl画出来。


首先介绍CoordinateConverter::convertDepthToWorld(const VideoStream& depthStream, int depthX, int depthY, DepthPixel depthZ, float* pWorldX, float* pWorldY, float* pWorldZ)函数:depthStream表示深度数据流,depthX,depthY表示深度图像某一行,某一列,depthZ表示该行该列的值(即深度值)。pWorldX, pWorldY, pWorldZ是转换好的世界坐标系下的三维坐标。


建立三维数组xyzdata[480][640][3]存储点云数据:

pdepth = (DepthPixel*)frameDepth.getData();
for (int i = 0; i < frameDepth.getHeight(); i++)
{
	for (int j = 0; j < frameDepth.getWidth(); j++)
	{
		depthv = pdepth[i*frameDepth.getWidth() + j];
		CoordinateConverter::convertDepthToWorld(streamDepth, i, j, depthv, &x, &y, &z);
		xyzdata[i][j][0] = x ;
		xyzdata[i][j][1] = y ;
		xyzdata[i][j][2] = z ;
	}
}

接下来利用彩色数据获得纹理,存储在三维数组texture[480][640][3]中(注意opengl中着色是RGB,根据opencv中图像的不同作相应转换):

for (int i = 0; i < cImageBGR.rows; i++)
{
	Vec3b *p = cImageBGR.ptr<Vec3b>(i);
	for (int j = 0; j < cImageBGR.cols; j++)
	{
		texture[i][j][0] = p[j][2];  //red
		texture[i][j][1] = p[j][1];  //green
		texture[i][j][2] = p[j][0];  //blue
	}
}

最后在opengl中画出来即可(注意绕Z轴逆时针旋转90°):

void display(void)
{
	// clear screen and depth buffer  
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// Reset the coordinate system before modifying   
	glLoadIdentity();
	// set the camera position  
	gluLookAt(0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 	glRotatef(-90.0, 0.0, 0.0, 1.0); //绕Z轴逆时针旋转90°
 
	float x,y,z;
	// 绘制图像点云
	glBegin(GL_POINTS);
	for (int i=0;i<480;i++){
		for (int j=0;j<640;j++){
			// color interpolation
			glColor3f(texture[i][j][0]/255, texture[i][j][1]/255, texture[i][j][2]/255);
			x= xyzdata[i][j][0];
			y= xyzdata[i][j][1];
			z= xyzdata[i][j][2];
			glVertex3f(x,y,z);
		}
	}
	glEnd();
	glutSwapBuffers();
}

效果如下:

6500.bmp为了显示的更加清楚,我们加入了鼠标和键盘控制旋转和缩放:

void mouse(int button, int state, int x, int y)
{
	if (state == GLUT_DOWN)
	{
		mousedown = GL_TRUE;
	}
	mousex = x, mousey = y;
}
 
void motion(int x, int y)
{
	if (mousedown == GL_TRUE)
	{       /// 所除以的数字是调整旋转速度的,随便设置,达到自己想要速度即可
		xrotate -= (x - mousex) / 10.0f;
		yrotate -= (y - mousey) / 10.0f;
	}
	mousex = x, mousey = y;
	glutPostRedisplay();
}
void keyboard(unsigned char c, int x, int y)
{
	switch (c)
	{
	case 'w':
		eye[2] += 20.0f;
		break;
	case 's':
		eye[2] -= 20.0f;
		break;
	case 'a':
		eye[0] += 20.0f;
		break;
	case 'd':
		eye[0] -= 20.0f;
		break;
	case 'r':
		eye[0] = 0.0f;
		eye[2] = 0.0f;
		xrotate = 0;
		yrotate = 0;
		break;
	case 27:
		exit(0);
	default:
		break;
	}
	glutPostRedisplay();
}

改良后的显示函数:

void display(void)
{
	// clear screen and depth buffer  
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// Reset the coordinate system before modifying   
	glLoadIdentity();
	// set the camera position  
//	gluLookAt(0.0, 0.0, -0.1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	gluLookAt(eye[0], eye[1], eye[2],
		center[0], center[1], center[2],
		0, 1, 0);
	glPushMatrix();
  	glRotatef(-90.0, 0.0, 0.0, 1.0);
	glTranslatef(-350.0, -300.0, 5000.0);
	glRotatef(xrotate, 1.0, 0.0, 0.0);
	glRotatef(yrotate, 0.0, 1.0, 0.0);
	glTranslatef(350.0, 300.0, -5000.0);
 
	float x,y,z;
	// 绘制图像点云
	glBegin(GL_POINTS);
	for (int i=0;i<480;i++){
		for (int j=0;j<640;j++){
			// color interpolation
			glColor3f(texture[i][j][0]/255, texture[i][j][1]/255, texture[i][j][2]/255);
			x= xyzdata[i][j][0];
			y= xyzdata[i][j][1];
			z= xyzdata[i][j][2];
			glVertex3f(x,y,z);
		}
	}
	glEnd();
 
	glPopMatrix();
	glutSwapBuffers();
}

控制鼠标和键盘效果如下:

缩放

4532.bmp

旋转1

2175.bmp

旋转2

5939.bmp


旋转3

2893.bmp

详细代码与工程点此下载

这一节就到这,自认为效果还不错,欢迎大家讨论。接下来开始研究实时三维重建的相关论文,立体匹配,滤波等等,可能要一段时间之后才能写出相关博客。


————————————————

版权声明:本文为CSDN博主「cc_sunny」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/aptx704610875/article/details/49798543



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年3月    »
123
45678910
11121314151617
18192021222324
25262728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864