4、多视图几何基础:对极几何、基础矩阵与本质矩阵、三角化原理

各位同学,欢迎来到第四章。这一章,咱们要啃一块硬骨头——多视图几何。

说实话,很多做嵌入式AI的朋友一听到「几何」两个字就头大。我当年刚接触BEV时也是这样,觉得这东西太数学了,跟嵌入式离得远。但后来在实际项目中踩过坑才发现——不懂多视图几何,你连相机怎么摆放、图像怎么对齐都搞不明白,更别提做BEV融合了。

这一章,我会尽量用「人话」把对极几何、基础矩阵、本质矩阵、三角化这几个概念讲清楚。你不需要成为数学家,但得理解它们为什么重要,以及怎么在BEV里用起来。

4.1 为什么多视图几何对BEV这么重要?

先问一个问题:BEV感知里,我们通常有多个相机,比如前视、后视、左视、右视。每个相机看到的都是2D图像,但我们要把它们融合成一个统一的鸟瞰视角。

这里有个核心矛盾:同一个3D点,在不同相机图像里的位置是不一样的。怎么知道它们对应的是同一个点?怎么从2D坐标反推3D位置?

这就是多视图几何要解决的问题。说白了,就是研究「多个相机看同一个场景时,图像之间有什么几何关系」。

我在项目中遇到过一种情况:两个相机拍同一个行人,一个在图像左边,一个在图像右边。如果不做几何校正,直接拼接,那人就「分身」了。嗯,这就是没理解对极几何的后果。

核心思想:多视图几何就是建立「不同视角图像之间的像素对应关系」,为后续的3D重建和BEV融合提供数学基础。

4.2 对极几何:两个相机之间的「约束」

对极几何,名字听着吓人,其实道理很简单。

想象一下:你有两个相机,同时拍同一个3D点P。P在左相机图像上是p1,在右相机图像上是p2。那么p1和p2之间有什么关系?

对极几何告诉我们:p2一定在一条特定的直线上,这条线叫「对极线」。

为什么会这样?因为P、左相机光心O1、右相机光心O2,这三个点构成了一个平面(叫对极平面)。这个平面与右相机图像的交线,就是p2所在的直线。

你想想看,这意味着什么?

  • 搜索匹配点时,不用全图搜,只用在一条线上搜
  • 计算量大大降低——这对嵌入式平台太重要了
  • 还能剔除很多错误的匹配

我个人习惯把对极几何理解成「两个相机之间的约会规则」——你左眼看到的东西,右眼只能在特定位置看到,不能乱跑。

嵌入式优化小技巧:在BEV系统中,如果你提前计算好对极线,匹配时就可以用查表法代替实时计算,能省不少算力。我在一个Jetson Orin项目里就是这么干的,帧率提升了15%。

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对匹配点就能求解——这就是经典的「八点法」。

注意:八点法对噪声非常敏感。我曾经在项目中直接用原始匹配点算F,结果出来的对极线歪得离谱。后来加了RANSAC(随机抽样一致性算法)做鲁棒估计,才稳定下来。所以,千万别裸用八点法,一定要加鲁棒估计。

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,使得它到两条射线的距离之和最小

常用的方法有两种:

  1. 线性三角化:用最小二乘法直接求解,速度快,但精度一般
  2. 迭代三角化:用非线性优化(比如高斯-牛顿法),精度高,但慢一些

代码实现(线性三角化):

// 伪代码:线性三角化
// 输入:两个相机投影矩阵 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);
关键点:三角化的精度高度依赖于匹配点的精度和相机位姿的准确性。如果匹配点偏差1个像素,3D点可能偏差几米。这就是为什么BEV系统里,特征匹配和相机标定是重中之重

4.5 在BEV融合中的实际应用

好了,理论讲完了。咱们说说这些东西在BEV里到底怎么用。

一个典型的BEV多相机融合流程是这样的:

  1. 相机标定:得到每个相机的内参K和外参(R, t)
  2. 特征提取与匹配:在不同相机图像中找到对应点
  3. 计算本质矩阵E:验证和优化相机之间的相对位姿
  4. 三角化:将匹配的2D点反投影到3D空间
  5. BEV投影:将3D点投影到鸟瞰视角的网格上

我在实际项目中发现一个坑:很多同学直接拿OpenCV的findFundamentalMat函数算F,然后就不管了。但OpenCV默认用的是八点法+RANSAC,参数没调好时,结果可能很差。

我的建议是:

  • 先用标定板做精确的相机标定,得到准确的K和初始外参
  • 然后用本质矩阵E做在线校验,检测相机是否发生了微小位移
  • 最后用三角化生成稀疏的3D点云,作为BEV融合的锚点
嵌入式部署建议:在嵌入式平台上,三角化可以用查表法加速。预先计算好每个像素对应的3D射线方向,运行时只需要做插值。我在一个RK3588项目里用这个方法,把三角化从5ms降到了0.3ms。

4.6 本章小结

这一章的内容确实有点硬,但它是BEV感知的基石。我总结几个你必须记住的点:

  • 对极几何:告诉你匹配点在哪条线上找,省算力
  • 基础矩阵F:像素坐标系下的对极约束,用八点法求解
  • 本质矩阵E:归一化坐标系下的对极约束,直接给出相对位姿
  • 三角化:从2D匹配点到3D坐标的逆推,精度取决于匹配和标定

下一章,我们会把这些几何知识用到实际的BEV特征融合中。到时候你会发现,今天学的这些东西,全都会派上用场。

嗯,今天就到这里。有问题随时交流。