4、双目标定原理:双目标定与单目标定的区别、立体校正(极线约束)、本征矩阵与基础矩阵、立体匹配与视差图
双目标定,说白了就是给相机装上一双「会算距离的眼睛」。单目标定我们只关心一个相机怎么拍清楚,双目标定则要解决两个相机怎么配合着看世界。我刚开始接触双目时,总觉得不就是两个单目标定加起来嘛?后来踩了坑才明白,这里面的门道深着呢。
4.1 双目标定与单目标定的区别
单目标定,我们只求两个东西:内参矩阵 K 和畸变系数。内参告诉你像素坐标和物理坐标怎么换算,畸变系数帮你把桶形或枕形失真拉回来。嗯,这些在单目里就够了。
但双目标定不一样。除了左右相机各自的内参和畸变,我们还需要一个关键量——两个相机之间的相对位姿。也就是右相机相对于左相机,到底旋转了多少、平移了多少。这个旋转矩阵 R 和平移向量 T,才是双目标定的核心产出。
单目标定 vs 双目标定
- 单目标定:内参 K₁、K₂ + 畸变系数 d₁、d₂
- 双目标定:内参 K₁、K₂ + 畸变系数 d₁、d₂ + 旋转矩阵 R + 平移向量 T
我在项目中遇到过一个问题:两个相机单独标定都很准,但拼在一起就是测不准距离。后来发现是双目标定时的 R 和 T 没优化好。你想想看,单目标定只优化单个相机的重投影误差,而双目标定要同时优化两个相机的重投影误差加上立体约束误差。这个约束就是——左右相机拍到同一个点,它们的投影线必须在空间中相交。
4.2 立体校正(极线约束)
为什么要做立体校正?说白了就是为了省计算量。未经校正的双目图像,你要在整张图上搜索匹配点,计算量巨大。校正之后,匹配点只出现在同一行上,搜索从二维降到了一维。
极线约束是立体校正的理论基础。它告诉我们:左图上的一个点,在右图上的匹配点一定位于一条直线上,这条线就叫极线。如果两个相机完全平行且共面,极线就变成了水平线。立体校正的目的,就是通过旋转和重投影,让左右图像达到这种理想状态。
我个人的习惯:在校正之前,先用棋盘格拍一组左右图像,肉眼看一下极线是否水平。如果偏差太大,说明标定参数有问题,这时候跑校正算法只会得到扭曲的图像。我曾经因为这个浪费了一整天。
立体校正的流程大致是这样的:
- 根据双目标定得到的 R 和 T,计算左右相机的校正旋转矩阵 R₁_rect 和 R₂_rect
- 将左图像按照 R₁_rect 进行重投影
- 将右图像按照 R₂_rect 进行重投影
- 此时左右图像的极线已经水平对齐
OpenCV 里提供了 stereoRectify 函数,直接传入标定参数就能得到校正映射表。我建议你把这个映射表保存下来,以后每次用的时候直接查表,不用每次都重新计算。
4.3 本征矩阵与基础矩阵
这两个矩阵是双目标定的数学灵魂。很多人分不清它们,其实很简单:
- 本征矩阵 E:描述的是两个相机在归一化坐标系下的几何关系。它只包含旋转 R 和平移 T,不包含内参。
- 基础矩阵 F:描述的是两个相机在像素坐标系下的几何关系。它包含了内参信息,是 E 的「像素版」。
它们的关系是:F = K₂⁻ᵀ · E · K₁⁻¹
为什么需要这两个矩阵?因为极线约束就是用它们来表达的。对于左图上的一个点 p₁,它在右图上的极线 l₂ 可以通过基础矩阵计算:l₂ = F · p₁。反过来也一样。
注意:基础矩阵的秩为 2,也就是说它的自由度是 7(而不是 9)。如果你用 8 点法求解 F,一定要确保数据点不共面,否则会退化。我曾经在标定一个平面场景时踩过这个坑,算出来的 F 完全不对。
在实际工程中,我们通常先通过特征点匹配(比如 SIFT、ORB)得到一组对应点,然后用这些点求解基础矩阵,再用基础矩阵分解出 R 和 T。不过要注意,分解出来的 R 和 T 有四种可能的组合,需要根据点在相机前方的约束来筛选。
4.4 立体匹配与视差图
立体匹配,就是找到左右图像中对应的像素点。校正之后,匹配变成了在一维水平线上搜索,大大简化了问题。
匹配的方法有很多种:
- 局部匹配:基于窗口的相似度计算,速度快但容易受噪声影响
- 全局匹配:构建能量函数,用图割或动态规划求解,精度高但慢
- 半全局匹配(SGM):折中方案,兼顾速度和精度,工业界用得最多
匹配完成后,每个像素点都有一个视差值 d = x_left - x_right。视差越大,说明物体离相机越近。视差图就是一张灰度图,每个像素的灰度值代表该点的视差大小。
有了视差图,深度就可以直接算出来:
Z = (f * B) / d
其中 f 是焦距(像素单位),B 是基线长度(两个相机光心的距离),d 是视差。
避坑指南:我曾经在室外场景做双目测距,发现远处的物体视差几乎为零,导致深度计算不稳定。后来我意识到,基线长度决定了测距范围。基线越长,远距离测距精度越高,但近距离会有盲区。选基线时一定要根据你的应用场景来权衡。
视差图的质量直接决定了深度图的精度。影响视差图质量的因素包括:纹理丰富度、光照一致性、遮挡区域处理等。对于弱纹理区域(比如白墙),匹配算法很容易出错,这时候可以结合结构光或投影纹理来辅助。
最后说一句,双目标定不是一次性的工作。温度变化、振动、镜头松动都会导致标定参数漂移。我建议在实际项目中定期做在线标定校正,或者设计自标定算法来实时更新参数。嗯,这部分内容我们后面会详细讲。