序:
记录学习过程中自己的理解以及遇到的问题,慢慢补充。
若有错误,还希望各位大佬不吝赐教。
0. 零零散散
0.1 公开数据集
Middlebury:https://vision.middlebury.edu/stereo/data/(室内)
KITTI:http://www.cvlibs.net/datasets/kitti/stereo(室外驾驶)
SceneFlow:https://lmb.informatik.uni-freiburg.de/resources/datasets
0.2 左、右手坐标系
左手、右手坐标系
伸出大拇指,食指和中指,自然摆成三指互相垂直的状态。
中指:X轴
大拇指:Y轴
食指:Z轴
左手建成的坐标系就是左手坐标系,右手建成的坐标系就是右手坐标系。
1. 四个经典的坐标系
1.1 世界坐标系
暂时不重要
1.2 相机坐标系
图中的(Oc-XcYcZc)。
1.3 图像坐标系
图中的(o-xy)
1.4 像素坐标系
图中的(ouv-uv)
2. 理想的单目成像模型
三维空间点P,在相机坐标系下的坐标为P(Xc, Yc, Zc),它在图像坐标系下的成像点为p(x, y)。
这里存在两组相似三角形:△ABOc ∽ △oCOc 和 △PBOc ∽ △pCOc
(1) 由△ABOc ∽ △oCOc,可知:
(2) 由△PBOc ∽ △pCOc,可知:
联立上边两个等式,可以得到:
根据点的坐标,可以将上式转换为:
变一下型可以得到:
写成矩阵的形式,并且用齐次坐标的话,就可以写成常见的那个矩阵关系:
3. 理想的双目成像模型
在上边的单目成像模型中,式子
可以变形为:
式中,x和y都是图像坐标系下的坐标,将x和y转成像素坐标系下的坐标,代入像素坐标转图像坐标公式可以得到:
至此,可以得到点P的Xc和Yc的表达式,式中除了Zc都是已知量。
此时,引入下图中的理想双目成像模型:
点P在两个平面上的投影点分别为$P_L$和$P_R$,b为基线长度,$X_L$和$X_R$分别是两个成像点距离各自所在成像平面左边的距离,两个成像平面的像主点在 X 方向上的坐标为X0L和X0R 则可以得到点P在左右相机中的视差:
两个成像点$P_L$和$P_R$之间的物理距离为:
上图中存在一组相似三角形:△PPLPR ∽ △POLOR。可以得到下式:
代入$P_LP_R$,可以得到:
变形,可以得到:
当$X_{0R} 与 X_{0L}相等时$,上式简化为:
至此,Zc也得到了,物点P的三维坐标都得到了:
式中的$f、b、d_x、d_y、u_0、v_0、X_{0L}、X_{0R}$都是可以通过标定得到的,$u$和$v$是该点在左图中的像素坐标,视差$d$可以通过立体匹配得到。所以,点P的相机坐标可以得到。
注:
opencv中使用函数
stereoRectify()
时,如果参数flags
设置为CV_CALIB_ZERO_DISPARITY
,则该函数会让两幅校正后的图像的主点有相同的像素坐标,也就是上边的$X_{0R}$ 与 $X_{0L}$相等,否则该函数会水平或垂直的移动图像,以使得其有用的范围最大。
上式当中焦距 f 的单位 mm,不便于后边计算,所有在双目视觉领域中,出现了“等效焦距",也就是经常见到的$f_x = \frac{f}{dx}和f_y = \frac{f}{dy}$。
其中,$d_x$表示一个像素在 x 方向有多少mm,$d_y$表示一个像素在 y 方向有多少mm。而且,在标定的结果当中,一般也是直接得到$f_x$和f$_y$。一般的工业相机会在详细的资料介绍中,会给出$d_x$和$d_y$的值,可以手动计算验证一下。
引入等效焦距后,物点P的三维坐标可以写成:
4. 非理想的双目成像模型
上边都是理想的情况,而现实的情况是,两个相机各自都存在畸变,并且在安装双目时,既做不到让两个相机的光轴完全平行,也做不到让两个相机的成像平面平行。
4.1 存在畸变,怎么办?
通过标定得到畸变系数,采集到双目图像后,通过畸变校正,在一定程度上消除畸变,得到较为理想的左图和右图。
4.2 无法做到共面行对准,怎么办?
在畸变校正之后,通过使用立体校正算法,将两幅非共面行对准的图像 校正成为 共面行对准的左右图像。
5. 为什么距离越远,误差越大?
深度的公式:
可以的得出两个结论:
- 视差与深度成反比
- 同样的视差间隔,距离越远,两个视差所对应的深度间隔越大。
对于第二点,可以举例:
假定,$bf=1000$,
1和2,79和80,两组数,都是间隔1个像素的视差,但是第一组的深度相差了500,第二组的深度差了0.1582。目标物离相机越远时,视差越小,对应第一组数据的情形,所以说,同样的视差间隔,距离越远,两个视差所对应的深度间隔越大。所以在距离较远时,视差引起的误差更大。
OpenCV中的一些操作
1. 基本数据
首先由双目标定,可以得到左相机的内参M1和畸变系数D1,可以得到右相机的内参M2和畸变系数D2,以及两个相机之间的旋转矩阵R和平移矩阵T。
2.立体校正
使用stereoRectify函数主要包含两个步骤:畸变校正、立体矫正,还有一些方便后续计算的矩阵R1、R2、P1、P2、Q。
CV_EXPORTS_W void stereoRectify( InputArray cameraMatrix1, InputArray distCoeffs1,
InputArray cameraMatrix2, InputArray distCoeffs2,
Size imageSize, InputArray R, InputArray T,
OutputArray R1, OutputArray R2,
OutputArray P1, OutputArray P2,
OutputArray Q, int flags = CALIB_ZERO_DISPARITY,
double alpha = -1, Size newImageSize = Size(),
CV_OUT Rect* validPixROI1 = 0, CV_OUT Rect* validPixROI2 = 0 );
cameraMatrix1、distCoeffs1为相机1的内参数M1和畸变系数D1。
cameraMatrix2、distCoeffs2为相机2的内参数M2和畸变系数D2。
imageSize为用于校正的图像尺寸。
R1、R2为两个相机进行共面行对准时所用的旋转矩阵(使用这两个旋转矩阵,相当于把两个实际的相机坐标系转换到理想的两个坐标系了),换一种说法:R1和R2分别为左右相机消除畸变后的像平面投影到公共像平面的旋转矩阵。
P1,P2为两个相机的理想投影矩阵,可以将相机坐标系(O-XcYcZc)投影到像素坐标系(O-uv),这两个坐标系都是校正后的,理想的。
P1,P2分别为左右相机的投影矩阵,其作用是将世界坐标系的点转换到像素坐标系下(左相机光心为世界坐标系原点,所以,这里可以直接认为是完成相机坐标系转像素坐标系):
Q为重投影矩阵,可以把像素坐标系重投影为世界坐标系(相机坐标系,因为此时,世界坐标系与相机坐标系重合),这两个坐标系都是校正后的,理想的。
。。。。 P1和P2的验证
(挖坑, 待填)
。。。 。 Q矩阵的用法
(挖坑, 待填)
P1和P2在理想状态下,其实内部只差一个数字,P2比P1多了一个$-b·f$,
其他一些注意点
MATLAB标定结果中。