2D-2D对极几何:从对极约束到单应矩阵
各位同学,今天我们来聊聊视觉里程计里最基础、也最核心的一块——2D-2D对极几何。
说实话,我刚入行那会儿,对极几何这玩意儿看得我头大。什么本质矩阵、基础矩阵,一堆数学公式。后来做项目踩了坑才明白,这些东西说白了就是解决一个问题:两张图片之间,相机到底动了多少?
嗯,咱们今天就把这块彻底讲透。
1. 对极约束:两张图之间的几何关系
想象一下,你拿着相机拍了两张照片。第一张里有个点P,第二张里也有个点P'。这两个点之间有什么几何关系?
我习惯这么理解:对极约束就是告诉你,P'一定在一条特定的直线上。这条线叫对极线。
为什么会这样?
你看啊,第一张图的相机中心O₁,第二张图的相机中心O₂,加上空间点P,这三个点构成了一个平面——对极平面。这个平面与第二张图的成像平面相交,那条交线就是对极线。
所以,P'一定在这条线上。这就是对极约束的核心思想。
核心公式:
x₂ᵀ · F · x₁ = 0
其中x₁、x₂是归一化平面上的点,F是基础矩阵。
我在项目中遇到过一个问题:如果两张图的匹配点太少,对极约束就不好使了。所以,匹配点数量至少得8对以上,这是八点法的基本要求。
2. 本质矩阵E与基础矩阵F
这两个矩阵,很多初学者容易搞混。我简单说说我的理解。
本质矩阵E:它只包含相机的旋转R和平移t的信息。说白了,就是相机在三维空间里怎么动的。
基础矩阵F:它除了包含R和t,还包含了相机的内参K。所以F = K⁻ᵀ · E · K⁻¹。
你想想看,如果相机内参已知,我们直接用E就够了。如果内参未知,那就得用F。
| 矩阵 | 包含信息 | 自由度 | 适用场景 |
|---|---|---|---|
| 本质矩阵E | R, t | 5 | 内参已知 |
| 基础矩阵F | R, t, K | 7 | 内参未知 |
我的小技巧:实际工程中,我一般先用E,因为它的自由度少,求解更稳定。除非相机内参真的不确定,才用F。
3. 八点法求解:从匹配点到矩阵
好了,理论讲完了,咱们来点实际的。怎么从一堆匹配点里算出E或F?
最经典的方法就是八点法。名字很直白,至少需要8对匹配点。
步骤是这样的:
- 收集8对以上的匹配点 (x₁, x₂)
- 构建线性方程组 A·f = 0
- 用SVD分解求解f
- 将f重构成3×3矩阵
- 强制满足奇异值约束(对E来说,两个奇异值相等,第三个为0)
代码实现其实不复杂:
def eight_point_algorithm(points1, points2):
# 构建A矩阵
A = np.zeros((len(points1), 9))
for i in range(len(points1)):
x1, y1 = points1[i]
x2, y2 = points2[i]
A[i] = [x2*x1, x2*y1, x2, y2*x1, y2*y1, y2, x1, y1, 1]
# SVD求解
U, S, Vt = np.linalg.svd(A)
F = Vt[-1].reshape(3, 3)
# 强制秩为2
U, S, Vt = np.linalg.svd(F)
S[2] = 0
F = U @ np.diag(S) @ Vt
return F
注意:八点法对噪声非常敏感。我曾经在室外场景测试,匹配点稍微有点偏差,算出来的E就完全不对了。所以,一定要先做归一化,把点的坐标缩放到[-1, 1]之间。
4. 单应矩阵H:平面场景的利器
聊完E和F,咱们再来说说单应矩阵H。
H和E/F最大的区别是什么?H假设场景中的点都在同一个平面上。
你想想看,如果拍的是墙面、地面、桌面,这些平面场景,用H就特别合适。H描述的是两个平面之间的投影变换。
H的求解只需要4对匹配点(不共线),比八点法少一半。而且H的鲁棒性更好,对噪声不那么敏感。
我个人的经验是:如果场景近似平面,优先用H。比如无人机拍地面、机器人拍天花板,H的效果远好于E/F。
H的公式也很直观:
x₂ = H · x₁
求解方法类似,也是构建线性方程组,然后用SVD或直接线性变换(DLT)求解。
什么时候用E/F,什么时候用H?
- 场景有深度变化(比如有近景有远景)→ 用E/F
- 场景近似平面(比如墙面、地面)→ 用H
- 相机纯旋转 → 只能用H,因为E/F在纯旋转时退化了
5. 知识体系总览
说了这么多,我画了一张图,帮你把今天的内容串起来:
6. 避坑指南
最后,分享几个我踩过的坑:
- 匹配点质量比数量重要:我曾经用100对匹配点算E,结果不如20对高质量点。所以,先做RANSAC剔除误匹配。
- 纯旋转场景别用E/F:相机只旋转不平移时,E/F会退化,算出来的t是错的。这时候只能用H。
- 别忘了归一化:八点法不归一化,结果基本不能用。这是很多初学者容易忽略的。
- 三角化验证:算出来的R和t对不对?把点三角化到三维空间,看看重投影误差。这是最直接的验证方法。
好了,2D-2D对极几何的核心内容就这些。记住,理论是基础,实践出真知。多写代码、多跑数据,才能真正理解这些矩阵背后的几何意义。