4、多视图几何基础:对极几何、基础矩阵与本质矩阵、三角化原理
各位同学,欢迎来到第四章。这一章,咱们要啃一块硬骨头——多视图几何。
说实话,很多做嵌入式AI的朋友一听到「几何」两个字就头大。我当年刚接触BEV时也是这样,觉得这东西太数学了,跟嵌入式离得远。但后来在实际项目中踩过坑才发现——不懂多视图几何,你连相机怎么摆放、图像怎么对齐都搞不明白,更别提做BEV融合了。
这一章,我会尽量用「人话」把对极几何、基础矩阵、本质矩阵、三角化这几个概念讲清楚。你不需要成为数学家,但得理解它们为什么重要,以及怎么在BEV里用起来。
4.1 为什么多视图几何对BEV这么重要?
先问一个问题:BEV感知里,我们通常有多个相机,比如前视、后视、左视、右视。每个相机看到的都是2D图像,但我们要把它们融合成一个统一的鸟瞰视角。
这里有个核心矛盾:同一个3D点,在不同相机图像里的位置是不一样的。怎么知道它们对应的是同一个点?怎么从2D坐标反推3D位置?
这就是多视图几何要解决的问题。说白了,就是研究「多个相机看同一个场景时,图像之间有什么几何关系」。
我在项目中遇到过一种情况:两个相机拍同一个行人,一个在图像左边,一个在图像右边。如果不做几何校正,直接拼接,那人就「分身」了。嗯,这就是没理解对极几何的后果。
4.2 对极几何:两个相机之间的「约束」
对极几何,名字听着吓人,其实道理很简单。
想象一下:你有两个相机,同时拍同一个3D点P。P在左相机图像上是p1,在右相机图像上是p2。那么p1和p2之间有什么关系?
对极几何告诉我们:p2一定在一条特定的直线上,这条线叫「对极线」。
为什么会这样?因为P、左相机光心O1、右相机光心O2,这三个点构成了一个平面(叫对极平面)。这个平面与右相机图像的交线,就是p2所在的直线。
你想想看,这意味着什么?
- 搜索匹配点时,不用全图搜,只用在一条线上搜
- 计算量大大降低——这对嵌入式平台太重要了
- 还能剔除很多错误的匹配
我个人习惯把对极几何理解成「两个相机之间的约会规则」——你左眼看到的东西,右眼只能在特定位置看到,不能乱跑。
4.3 基础矩阵与本质矩阵:数学表达
对极几何的数学表达,就是基础矩阵F和本质矩阵E。
这两个矩阵,说白了就是描述「两个相机之间几何关系」的数学工具。
4.3.1 基础矩阵 F
基础矩阵F,描述的是两个相机在像素坐标系下的关系。它把左图像上的一个点p1,映射到右图像上的一条对极线l2。
数学表达式:
l2 = F * p1
其中p1是左图像上的齐次坐标,l2是右图像上的对极线。
反过来也成立:
p2^T * F * p1 = 0
这个公式的意思是:如果p1和p2是匹配点,那么它们满足这个约束。
F矩阵有7个自由度(因为尺度模糊和秩为2的约束),所以理论上只需要8对匹配点就能求解——这就是经典的「八点法」。
4.3.2 本质矩阵 E
本质矩阵E,跟F很像,但它是在归一化相机坐标系下的。说白了,E = K^T * F * K,其中K是相机内参矩阵。
E矩阵描述的是两个相机之间的相对位姿(旋转R和平移t)。
数学上:
E = [t]× * R
其中[t]×是平移向量的反对称矩阵。
E矩阵有5个自由度(3个旋转 + 3个平移,但尺度模糊去掉1个),所以理论上5对匹配点就能求解——这就是「五点法」。
| 矩阵 | 坐标系 | 自由度 | 最少匹配点数 | 输出 |
|---|---|---|---|---|
| 基础矩阵 F | 像素坐标系 | 7 | 8 | 对极线约束 |
| 本质矩阵 E | 归一化相机坐标系 | 5 | 5 | 相对位姿 (R, t) |
我个人习惯:在BEV系统中,优先用本质矩阵E。因为E直接给出相机之间的相对位姿,这对后续的BEV融合太关键了。F只能告诉你「像素怎么对应」,而E能告诉你「相机怎么摆放」。
4.4 三角化:从2D到3D的逆推
好了,现在我们知道两个相机之间的几何关系了。但还有一个问题:怎么从两个2D图像点,反推出3D点的位置?
这就是三角化要做的事。
原理其实很简单:从两个相机光心出发,分别经过p1和p2画两条射线。理论上,这两条射线应该交于3D点P。但实际中,由于噪声和误差,它们往往不相交。
所以,三角化的本质是:找一个点P,使得它到两条射线的距离之和最小。
常用的方法有两种:
- 线性三角化:用最小二乘法直接求解,速度快,但精度一般
- 迭代三角化:用非线性优化(比如高斯-牛顿法),精度高,但慢一些
代码实现(线性三角化):
// 伪代码:线性三角化
// 输入:两个相机投影矩阵 P1, P2,匹配点 p1, p2
// 输出:3D点 X
// 构建方程组
// p1 × (P1 * X) = 0
// p2 × (P2 * X) = 0
// 具体实现
Matrix4x4 A;
A.row(0) = p1.x * P1.row(2) - P1.row(0);
A.row(1) = p1.y * P1.row(2) - P1.row(1);
A.row(2) = p2.x * P2.row(2) - P2.row(0);
A.row(3) = p2.y * P2.row(2) - P2.row(1);
// 求解 AX = 0,用SVD分解
SVD svd(A);
Vector4f X = svd.V().col(3);
// 归一化
X = X / X(3);
4.5 在BEV融合中的实际应用
好了,理论讲完了。咱们说说这些东西在BEV里到底怎么用。
一个典型的BEV多相机融合流程是这样的:
- 相机标定:得到每个相机的内参K和外参(R, t)
- 特征提取与匹配:在不同相机图像中找到对应点
- 计算本质矩阵E:验证和优化相机之间的相对位姿
- 三角化:将匹配的2D点反投影到3D空间
- BEV投影:将3D点投影到鸟瞰视角的网格上
我在实际项目中发现一个坑:很多同学直接拿OpenCV的findFundamentalMat函数算F,然后就不管了。但OpenCV默认用的是八点法+RANSAC,参数没调好时,结果可能很差。
我的建议是:
- 先用标定板做精确的相机标定,得到准确的K和初始外参
- 然后用本质矩阵E做在线校验,检测相机是否发生了微小位移
- 最后用三角化生成稀疏的3D点云,作为BEV融合的锚点
4.6 本章小结
这一章的内容确实有点硬,但它是BEV感知的基石。我总结几个你必须记住的点:
- 对极几何:告诉你匹配点在哪条线上找,省算力
- 基础矩阵F:像素坐标系下的对极约束,用八点法求解
- 本质矩阵E:归一化坐标系下的对极约束,直接给出相对位姿
- 三角化:从2D匹配点到3D坐标的逆推,精度取决于匹配和标定
下一章,我们会把这些几何知识用到实际的BEV特征融合中。到时候你会发现,今天学的这些东西,全都会派上用场。
嗯,今天就到这里。有问题随时交流。