机器视觉 增强现实分享 http://blog.sciencenet.cn/u/wanglin193

博文

实验:OpenGL的增强现实

已有 11041 次阅读 2011-8-28 15:24 |个人分类:增强现实|系统分类:科研笔记| OpenGL, OpenCV, 增强现实

 
如果知道了物体相对于摄像机的三维姿态,就可以把3D图形渲染并叠加到图像中了。这里用的函数是一句OpenGL函数glutWireTeapot(),当然之前还有很多铺垫。首先,为了让它看起来是坐在那本书上的,它所在的坐标系要挪动到合适的位置,作用的矩阵M是由书的姿态R,T表达的4×4齐次矩阵。R,T的求法可参考去年的博客文章。也就是说,只要把R,T告诉OpenGL,它会调用glLoadMatrix或glMultMatrixf把图形渲染到合适的位置上。
 
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//要画在x,y,-z平面上,因为图像沿着Z轴推远了,能看到的物体z值是负数
glRotatef(180, 1.0, 0.0, 0.0 ); 
//M矩阵是以连乘的形式使用,M是列优先矩阵象Matlab里一样
glMultMatrixf(M); 
//画坐标轴
DrawAxis(0.0f,0.0f,0.0f,base_length);

 
其次,摄像机内部参数K要和定义视角的glFrustum或gluPerspective函数联系起来,当摄像机的焦距和光心位置确定以后,它观察世界的视野FOV就确定了,也就是说只要不换摄像机,这个函数调用是一劳永逸的。假设光心在图像中心,焦距fx=fy=fol,就是说K里只有一个变量焦距的时候,视野可以这样确定:
 
//因为焦距是在320×240图像上得到的
fov = 2 * atan(240/2/fol)*180/3.14159265; 
gluPerspective(fov, 4.0/3.0, znear, 100.0f);

更靠谱的方法是用glFrustum分别根据x方向的fx,光心位置横坐标u0,和y方向的fy,光心位置纵坐标v0,确定可见区域的椎体的6个面,它可以看作是gluPerspective的升级版,而gluPerspective是glFrustum的特例。根据K确定glFrustum六个参数的方法可参考下图。六个参数对应图中蓝色的六面体,图中只显示y方向的投影,left,right,znear和可利用fx和图像平面所在的三角形的相似性求得。同样,参数bottom,up可以在x方向投影图中用fy和图像平面所在的三角形的相似性求得。
 

 
还有,上面这些图形是叠加在原始图像上的,原始图像用OpenCV读进来,用纹理映射的方法贴到背景上。
 
 glDisable(GL_DEPTH_TEST); //这句很重要    
 glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();
 glOrtho(0,wid,hei,0,-1,1);//glOrtho(0,wid,0,hei,-1,1);用那个取决于输入图像是否颠倒
 glMatrixMode(GL_MODELVIEW);glPushMatrix();glLoadIdentity();
 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 glBindTexture(GL_TEXTURE_2D, texName);
 gluBuild2DMipmaps( GL_TEXTURE_2D,GL_RGB, wid,hei,GL_BGR_EXT, GL_UNSIGNED_BYTE,camInput->imageData);
 glBegin(GL_QUADS); //贴图
  glTexCoord2f(0.0, 0.0); glVertex3f(0,0,0.0);
  glTexCoord2f(0.0, 1.0); glVertex3f(0, hei, 0.0);
  glTexCoord2f(1.0, 1.0); glVertex3f(wid,hei,0.0);
  glTexCoord2f(1.0, 0.0); glVertex3f(wid,0,0.0);
 glEnd();
 glMatrixMode(GL_PROJECTION); glPopMatrix();
 glMatrixMode(GL_MODELVIEW); glPopMatrix();

 
可以看出背景是用正交投影方式(glOrtho)贴图的,原来的图形的投影方式要用glPushMatrix和glPopMatrix保护起来。先贴背景再画其他的图形。
 
以上是以读入图像为例,真正的AR系统要实时读取Webcam数据,获取视频的函数要放在标准回调函数idel()的定义里。
void idle()
{
  if(IsVideo)      //得到当前帧
     camInput = cvQueryFrame(capture);
  cvShowImage("OpenCV Webcam Input", camInput);
  glutPostRedisplay(); //强制调用显示回调函数 display()
}
也就是说主程序应该是下面这种形式的:


void main()
 InitGL();
 InitCV();
 glutDisplayFunc(display);
 glutReshapeFunc(reshape);
 glutKeyboardFunc(keyboard);
 glutIdleFunc(idle);
 glutMainLoop(); //取代了OpenCV里的for(;;)
}
 

增强视觉应用的难点还是在于利用机器视觉分析场景结构和姿态的部分,简单地说就是如何跟踪那本书,如何计算K,R和T等

 



https://blog.sciencenet.cn/blog-465130-480474.html

上一篇:ASM/AAM形状训练
下一篇:Region growing
收藏 IP: 58.247.12.*| 热度|

2 陈筝 dsk75

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-11-25 11:42

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部