五、三维重建与
OpenGL
显示
.
在获取到视差数据后,利用
OpenCV
的
reProjectImageTo3D
函数结合
Bouquet
校正方法得到的
Q
矩阵就可以得到环境的三维坐标数据,然后利用
OpenGL
来实现三维重构。
OpenCV
与
OpenGL
的编程范例,我在
学习笔记(
15
)
中有详细的讨论,这里就不重复了,下面补充一些细节问题:
.
.
1.
reProjectImageTo3D
是怎样计算出三维坐标数据的?
图
22
.
相信看过
OpenCV
第
12
章的朋友对上图中的
Q
矩阵不会陌生,根据以上变换公式,按理说
OpenCV
应该也是通过矩阵运算的方式来计算出三维坐标数据的,但实际上仔细查看源代码,会发现
cvReprojectImageTo3D
用了比较奇怪的方法来实现,主要代码如下:
OpenCV
的这种计算方式比较令人费解,我的理解是可能这种方式的计算速度比较快。理论上,直接通过矩阵
Q
与向量
[x,y,d,1]’
的乘积就可以得到相同的结果,下面用
Matlab
来验证一下两种方式是异曲同工的,用
Matlab
按照
OpenCV
计算方式得到的结果称为“
OpenCV method
”,直接按公式计算得到的结果称为“
Equation method
”,用
OpenCV
本身算出的三维坐标作为参考,程序代码如下
:
图
23
.
.
2.
为什么利用修正了的
Q
矩阵所计算得到的三维数据中,
Y
坐标数据是正负颠倒的?
图
24
.
这个问题我觉得可以从图像坐标系与摄像机坐标系的关系这一角度来解释。如上图所示,一般图像坐标系和摄像机坐标系都是以从左至右为
X
轴正方向,从上至下为
Y
轴正方向
,摄像机坐标系的
Z
轴正方向则是从光心到成像平面的垂线方向。因此,我们得到的三维坐标数据中
Y
轴数据的正负与实际是相反的,在应用时要添加负号来修正。
.
.
3.
如何画出三维重建图像和景深图像?
.
利用
cvReprojectImageTo3D
计算出的三维坐标数据矩阵一般是三通道浮点型的,需要注意的是这个矩阵存储的是三维坐标数据,而不是
RGB
颜色值,所以是不能调用
cvShowImage()
或者
OpenCV2.1
版的
imshow()
等函数来显示这个矩阵,否则就会看到这种图像:
.
图
25
.
这里出现的明显的四个色块,其实应该是由三维坐标数据中的
X
轴和
Y
轴数据造成,不同象限的数据形成相应的色块。
要画出正确的三维重建图像,可以结合
OpenGL
(可参考我的
学习笔记(
15
)
)或者
Matlab
(例如保存三维数据到本地然后用
Matlab
的
mesh
函数画出,例程见本文问题
1
;也可以考虑在
OpenCV
中调用
Matlab
混合编程)来实现。
深度图像的显示相对比较简单,只要从三维坐标数据中分离出来(可用
cvSplit()
函数),经过适当的格式转换(例如转换为
CV_8U
格式),就可用
cvShowImage()
或者
OpenCV2.1
版的
imshow()
等函数来显示了,伪彩色的深度图
也可以参考我的
学习笔记(
18
)
问题
6
给出的例程
稍作修改即可实现。
.
.
4.
怎样把
OpenGL
窗口的图像复制到
OpenCV
中用
IplImage
格式显示和保存?
.
在
学习笔记(
15
)
中详细给出了将
OpenCV
生成的
IplImage
图像和三维坐标数据复制到
OpenGL
中显示的例程,而在应用中,我们有时候也需要把
OpenGL
实时显示的三维图像复制到
OpenCV
中,用
IplImage
格式保存,以便和其它图像组合起来显示或保存为视频文件。这里给出相应的例程以供参考:
首先在创建
OpenGL
窗口时,显示模式要如下设置:
在循环中的调用:
loadGLPixelToIplImage
函数定义:
显示效果如下:
图26
(待续)
.
.