4. 多视图几何:对极几何、基础矩阵、单应性矩阵,如何关联多个相机
好,咱们进入第四章。这一章我打算聊聊多视图几何。
说实话,在BEV感知里,多相机融合是个绕不开的坎。你想想看,车上装了6个、8个甚至12个摄像头,每个摄像头看到的都是局部画面。怎么把这些局部画面拼成一个完整的鸟瞰图?靠的就是多视图几何。
我个人习惯把这一章分成三块:对极几何、基础矩阵、单应性矩阵。这三兄弟,一个比一个实用。
4.1 对极几何:两个相机之间的“约束关系”
先说说对极几何。说白了,它就是描述两个相机之间成像关系的几何学。
假设你有一个点P在三维空间里。它在左相机成像为p_l,在右相机成像为p_r。那么p_l和p_r之间有什么关系?
嗯,这里有个关键概念:极线约束。
什么意思呢?就是左图上的一个点p_l,它在右图上的对应点p_r,一定落在一条特定的直线上。这条线就叫极线。
我在项目中遇到过一个问题:做双目立体匹配时,如果极线找不准,匹配出来的深度图全是噪点。后来发现是相机标定没做好,极线歪了。
所以,对极几何的核心就是:已知左图点,在右图上搜索对应点时,不用全图搜,只沿着极线搜就行。这能省下大量计算。
核心公式:
p_r^T · F · p_l = 0
其中F就是基础矩阵。这个公式表达的就是极线约束。
4.2 基础矩阵:连接两个相机的“数学桥梁”
基础矩阵F,说白了就是一个3x3的矩阵,秩为2。它把左图上的点映射到右图上的极线。
怎么求F?经典方法是八点法。你需要至少8对匹配点。
// 伪代码:八点法求基础矩阵
// 输入:8对匹配点 (x1,y1) -> (x2,y2)
// 输出:基础矩阵 F (3x3)
// 1. 构建系数矩阵 A (8x9)
for each match (p1, p2):
x1, y1 = p1
x2, y2 = p2
A[i] = [x1*x2, x1*y2, x1, y1*x2, y1*y2, y1, x2, y2, 1]
// 2. 对A做SVD分解
[U, S, V] = svd(A)
// 3. F是V的最后一列,reshape成3x3
F = reshape(V[:, 8], 3, 3)
// 4. 强制秩为2(再次SVD,把最小奇异值置0)
[U_f, S_f, V_f] = svd(F)
S_f[2,2] = 0
F = U_f * S_f * V_f^T
我曾经踩过一个坑:直接用原始像素坐标算F,结果数值不稳定。后来我意识到,必须先做归一化。把坐标缩放到[-1, 1]之间,再算F,最后再反归一化。这一步不做,你的F矩阵基本是废的。
避坑指南:
我曾经在实车测试时发现,基础矩阵在车辆高速转弯时失效了。原因是匹配点太少,而且分布不均匀。后来我强制要求匹配点必须覆盖整个图像,不能只集中在某个区域。
4.3 单应性矩阵:平面到平面的“投影变换”
单应性矩阵H,跟基础矩阵不一样。它描述的是同一个平面在两个相机之间的投影关系。
你想想看,如果场景中所有点都在同一个平面上(比如地面),那么两个相机之间的变换就是单应性变换。
H矩阵也是3x3的,但秩为3。它比F矩阵更强——它直接给出了点的对应关系,而不是极线。
// 伪代码:四点法求单应性矩阵
// 输入:4对匹配点 (x1,y1) -> (x2,y2)
// 输出:单应性矩阵 H (3x3)
// 1. 构建系数矩阵 A (8x9)
for each match (p1, p2):
x1, y1 = p1
x2, y2 = p2
A[2*i] = [-x1, -y1, -1, 0, 0, 0, x1*x2, y1*x2, x2]
A[2*i+1] = [0, 0, 0, -x1, -y1, -1, x1*y2, y1*y2, y2]
// 2. SVD分解
[U, S, V] = svd(A)
// 3. H是V的最后一列,reshape成3x3
H = reshape(V[:, 8], 3, 3)
个人经验:
在BEV项目中,我通常用单应性矩阵来做IPM(逆透视映射)。把前视相机图像投影到地面,再拼成鸟瞰图。但要注意:单应性矩阵只适用于地面平面。如果场景中有立杆、车辆等高出地面的物体,投影后会有重影。
4.4 如何关联多个相机?
好了,现在我们有F矩阵和H矩阵。怎么用它们关联多个相机?
我建议分两步走:
- 两两标定:对每一对相机,计算它们之间的F矩阵或H矩阵。比如6个相机,就有15对组合。
- 全局优化:把所有两两关系放到一个图里,做全局优化(Bundle Adjustment)。
具体到BEV场景,我常用的做法是:
- 相邻相机用单应性矩阵:因为相邻相机视野重叠区域主要在地面,用H矩阵直接做图像拼接。
- 非相邻相机用基础矩阵:它们之间没有直接重叠,但可以通过极线约束做特征匹配,辅助全局位姿优化。
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 相邻相机(前-前侧) | 单应性矩阵H | 地面平面假设成立,直接像素映射 |
| 非相邻相机(前-后) | 基础矩阵F | 无直接重叠,极线约束辅助匹配 |
| 环视全景拼接 | 多单应性矩阵融合 | 每个相机投影到统一地面坐标系 |
核心要点:
多相机关联的本质,就是把每个相机的局部坐标系,统一到同一个全局坐标系下。对极几何和单应性矩阵,就是完成这个统一的数学工具。
最后说一句:别被这些矩阵吓到。在实际工程中,OpenCV已经封装好了cv::findFundamentalMat()和cv::findHomography()。你真正需要理解的是:什么时候用F,什么时候用H,以及为什么。
下一章,我会讲怎么把这些几何关系用到BEV特征融合里。到时候你会发现,这些矩阵就是连接不同相机视角的“翻译官”。