文档介绍:OpenCV学(16)双目测距与三维重建的OpenCV实现问题集锦(一)图像获取与单目定标
假设目标点在左视图中的坐标为(x,y),在左右视图上形成的视差为d,目标点在以左摄像头光心为原点的世界坐标系中的坐标为(X,Y,Z),则存在上图所示的变换矩阵Q,使得 Q*[x y d 1]’= [X Y Z W]’。
“***@scyscyao :为了精确地求得某个点在三维空间里的距离Z,我们需要获得的参数有焦距f、视差d、摄像头中心距Tx。如果还需要获得X坐标和Y坐标的话,那么还需要额外知道左右像平面的坐标系与立体坐标系中原点的偏移cx和cy。其中f, Tx, cx和cy可以通过立体标定获得初始值,并通过立体校准优化,使得两个摄像头在数学上完全平行放置,并且左右摄像头的cx, cy和f相同(也就是实现图2中左右视图完全平行对准的理想形式)。而立体匹配所做的工作,就是在之前的基础上,求取最后一个变量:视差d(这个d一般需要达到亚像素精度)。从而最终完成求一个点三维坐标所需要的准备工作。在清楚了上述原理之后,我们也就知道了,所有的这几步:标定、校准和匹配,都是围绕着如何更精确地获得 f, d, Tx, cx 和cy 而设计的。”
一、图像的获取
1. 如何打开两个或多个摄像头?
可以通过OpenCV的capture类函数或者结合DirectShow来实现双摄像头的捕获,具体可见我的读书笔记《OpenCV学(6)基于 VC+OpenCV+DirectShow 的多个摄像头同步工作》。文中曾提及不能用
cvCreateCameraCapture 同时读取两个摄像头,不过后来一位研友来信讨论说只要把摄像头指针的创建代码按照摄像头序号降序执行,就可以顺利打开多个摄像头,例如:
[c-sharp] view plaincopyprint?
1.
2. CvCapture* capture2 = cvCreateCameraCapture( 1 ); CvCapture* capture1 = cvCreateCameraCapture( 0 );
1.
2. (1, false, 640,480); (0, false, 640,480);
取出来,它还保存在OpenCV的内部缓存中,下一次读取操作就会被覆盖掉。所以一般我们要另外定义一个IplImage来复制所抓取的帧数据,然后对这个新IplImage进行操作。由上面的解释也可以看出,cvGrabFrame的作用就是尽可能快的将摄像头画面数据复制到计算机缓存,这个功能就方便我们实现对多个摄像头的同步抓取,即首先用cvGrabFrame依次抓取各个CvCapture*,然后再用cvRetrieveFrame把帧数据取出来。例如:
[c-sharp] view plaincopyprint?
1.
2.
3.
4.
5.
6.
7. cvGrabFrame( lfCam ); cvGrabFrame( riCam ); frame1 = cvRetrieveFrame( lfCam ); frame2 = cvRetrieveFrame( riCam ); if( !f