参考资料:《Learning OpenCV》,Stanford University CS 131 Computer Vision Foundations and Applications 2016 - lecture10
假设两个相机:
这样的相机布置称为frontal parallel,这样的假设实际在物理上很难达到,而校正的过程则是在数学上实现上述假设。
基于上述假设,利用三角形相似:
�−(��−��)�−�=��⇒�=��(��−���)−(��−���)=����−��−(���−���)
�=��−��或�=��−��−(���−���)称为视差
同理,可得:
�=���−��−(���−���)(��−��)�=���−��−(���−���)(��−��)
当���=���时,有:
�=����−��
此时,无穷远处的视差为0,也就是说两个相机的光轴平行且在无限远处相交;否则,有限远处的视差为0,等价于两个相机的光轴在有限远处相交,也就是说这种情况下,两个相机坐标系没有共面,即相机处于横向汇聚模式,不能用上述公式求解距离。也就是说,对于两个相机坐标系共面的情况或者立体校正过程中,必然要求���=���
当x采用像素坐标时,f应该也是像素坐标的��,��=�/��;��,���是在左相机图像坐标系下,��,���是在右相机图像坐标系下;
由公式可知距离与视差成反比,当视差大小的范围固定时,减小f,T,能对更近的物体进行测量,增大测距范围。
对上述公式求微分,有:
�=�2���
视差计算的分辨率对测量分辨率的影响:
��/��=1/�1/�=��=���2
当视差计算分辨率固定时,测量分辨率与距离的平方成反比,与f,T成正比
单位视差计算误差对测量误差的影响:
��=�2��
该公式反映了视差计算的误差造成的测量误差与距离平方成正比,与f, T成反比,即与测量分辨率相反
好像这部分的原理在实际立体视觉应用过程中没有用到
应该是由于进行了立体校正,不需要用到基础矩阵去求解物体位置
根据单目标定,可以得到左右相机的外参��,��,��,��,令P为物体坐标,则其对应的左右相机坐标��,��为:
��=���+����=���+��
联立并消去P可得:
�=��−1(��−��)��=����−1(��−��)+��=���−���+��=���+�
其中,�=����−1,�=��−���, 代表从右相机到左相机坐标系的几何关系
实际求解过程中,对于多对棋盘图像,先用单目标定算法标定左右相机的外参,再根据上面的公式计算左右相机间的R,T,然后以多对棋盘图像计算到的R、T的中值为初始值,使用Levenberg-Marquardt 迭代算法求解使重投影误差(局部)最小的解,这个解包括左右相机的参数和两者之间的R、T,立体标定通常可以获得比单目标定更准确的相机参数。
立体校正是为了使得左右相机的图像坐标系行对准,主要分两个步骤:
Bouguet's算法实现立体校正:
总体的立体校正为:
������=�������������=�������
本质上是对图像进行了3维旋转,由于校正前后的内参矩阵已知,则对于归一化成像坐标系中的一点,可以由校正前后的内参矩阵得到校正前后的像素坐标。
完整的从原图得到校正图像的过程示意图如下,该图取自《Learning OpenCV》,图中的公式含义不清且可能有误,可以忽略;
Stereo rectification: for the left and right camera, the raw image (a) is undistorted (b) and rectified (c) and finally cropped (d) to focus on overlapping areas between the two cameras; the rectification computation actually works backward from (c) to (a)
校正过程如下:
实际实现整个立体校正的时候,可以将undistort, rectify, crop合成一步,直接用一个map进行映射。
令投影矩阵为P(也就是单应性矩阵),投影矩阵使齐次的3D世界坐标(或相机坐标)投影到2D图像坐标:
�[���1]=[���]
其中投影后的图像坐标为(�/�,�/�)
由于对图像坐标系进行了旋转,所以相机的主距和主点像素坐标都发生了变化,令左相机校正前的投影矩阵为��,则由
��������[���1]=������[���]
可得,校正后的投影矩阵������=��������
当3D点为左相机的相机坐标时,
������=��������′������=��������′
其中,������,������分别为左右相机校正后的相机矩阵,注意,这里的变量名与《Learning OpenCV》中不太一致
��′=[1000010000100000]��′=[100��010000100000]
2D点也能反投影到3D相机坐标
�[���1]=[����]
其中,反投影后的3D坐标为(�/�,�/�,�/�)
反投影矩阵Q为
�=[100−��010−��000�001/��(��−��′)/��]
其中的相机参数除��′为右相机参数外,其余均为左相机参数,另外,这里的f应该是fx,相应的,反投影方程中的x,y也是做相机中的坐标。注意,《Learning OpenCV》中,这里的1/Tx取了负号,感觉应该是书本出错了。
将矩阵乘法展开可得:
[����]=[�−���−���(�+��−��′)/��]
3D坐标为:
1/�[���]=��(�+��−��′)[�−���−���]
与 三角测量中一致
OpenCV提供了reprojectTo3DImage()和perspectiveTransform(),分别对视差图和离散的视差数据进行反投影。
匹配图像缩小时的反投影
如果为了减少立体匹配的计算量和计算时间,将图像缩小后再进行立体匹配得到视差图,反投影需要做调整;
假设匹配图像行列缩放因子为p,得到视差数据为[x’ y’ d’],其对应的原图匹配得到的视差数据为[x y d],则有对应公式
[���]=1/�[�′�′�′]
则有两种方法进行反投影:
当然,也可以考虑在双目立体标定、立体校正、立体匹配和反投影全过程中使用缩放后的图像
步骤:
视差搜索范围:
从minDisparity到MaxDisparity范围内搜索,MaxDisparity=minDisparity+NumDisparities,均为像素坐标
视差搜索范围 注意,实际搜索的过程中,是以亚像素精度的视差搜索的,精度为1/16像素
视差搜索范围形成了一个双目视界(horopter),也就是确定了可能的测量范围,超过这个测量范围的物体,其深度是未知的,减小f,T,增大视差查找范围或增加像素宽度可扩大双目视界
顺序约束:点在左右视图中的顺序保持一致,计时有部分点确实(遮挡或噪声)
注意,OpenCV中,StereoMatcher::compute()函数计算得到的视差图要除以16,因为视差搜索使用亚像素精度,精度为1/16像素,而视差图输出为整形数据,所以对亚像素精度视差乘以16再取整保存为整形数据。
参见《视觉测量技术基础》- 白福忠
双目横向汇聚模式(相机光轴在有限远处相交)应该是为了对远处物体有更大的重合视野,同时应该有利于减少视差计算误差造成的测量误差
《Learning OpenCV3》的Calibrated stereo rectification: Bouguet’s algorithm部分指出,stereoRectify()的flags参数设置为0,即对应为汇聚模式,设置为CALIB_ZERO_DISPARITY,即对应平行模式,且指出,汇聚模式可以在接近汇聚点位置获得更好的深度分辨率,也就是能减小重建误差
《Learning OpenCV3》的Depth Maps from Three-Dimensional Reprojection部分指出,OpenCV的stereoRectify()得到的反投影矩阵Q,是可以应用于汇聚模式的,可以用reprojectImageTo3D()进行三维重建