Part III · 第 11 章 多视图几何 · 11.3

三角化

相机已标定,同一个点在两张(或更多)图里的像素也匹配上了,那么这个点在三维空间的哪里?这一步叫三角化,它把特征匹配变成三维路标,是双目测距、SfM 和视觉 SLAM 的共同核心。难处在于:像素有噪声,两条视线几乎永远不相交,所以"交点"必须重新定义;而答案有多准,几乎完全取决于相机之间隔了多远。本节把三种估计方法(中点、线性 DLT、最小化重投影误差)放到同一组数据上比较,再用不确定性椭球看清深度误差为什么与 Z² 成正比,为什么直行的机器人看不准前方,以及 SLAM 为什么要等"足够的视差"再初始化路标。

约 35 分钟 前置:1.12 SVD · 1.13 最小二乘 · 4.5 不确定性传播 · 6.9 非线性最小二乘 · 10.3 内参与外参 · 11.2 立体视觉 5 个交互

    1为什么机器人需要它

    一张图只告诉你一个三维点在哪个方向上;深度在投影时丢掉了(10.1)。要把像素变回三维,至少要从两个不同的位置看同一个点:每个视角给出一条穿过光心和像素的射线,点就在射线的交会处。这就是三角化(triangulation),机器人里到处在用它:

    • 双目 / 多目深度:每个匹配像素的深度。11.2 的 \(Z=fB/d\) 就是共面(校正过的)双目的特例。
    • SfM 与视觉 SLAM:把关键帧之间的特征匹配变成三维路标,供 PnP(11.4)定位、供光束法平差(11.6)联合优化。
    • 多相机系统:动捕的反光点、AprilTag 的角点、遥操作采集数据时的人手 / 人体关键点,都是先在每台相机里检测二维点,再三角化成三维。

    但真实的射线从来不相交:像素有噪声,空间中两条直线通常是异面的。于是出现三个问题:没有交点时"交点"指什么?这个答案可信到什么程度?相机该怎么放才好?本节依次回答。

    2直觉:两条几乎相交的射线

    从相机 \(i\) 的光心 \(\mathbf o_i\) 出发,穿过观测到的像素,得到射线 \(\mathbf o_i + s\,\mathbf d_i\)(\(s>0\),\(\mathbf d_i\) 为单位方向;像素 → 方向见 10.3)。没有噪声时,两条射线恰好交于真实点 \(\mathbf X\)。一旦像素偏了几个像素,两条射线就擦肩而过。我们取两条射线最短的连线(公垂线)的中点作为估计:

    $$ \hat{\mathbf X} \;=\; \hl{mid}{\tfrac12\big(\mathbf o_1 + s^{*}\mathbf d_1 + \mathbf o_2 + t^{*}\mathbf d_2\big)},\qquad (s^{*},t^{*}) = \arg\min_{s,t}\ \big\|\mathbf o_1 + s\mathbf d_1 - \mathbf o_2 - t\mathbf d_2\big\|,\qquad \hl{gap}{d_{\min}} = \big\|\mathbf o_1 + s^{*}\mathbf d_1 - \mathbf o_2 - t^{*}\mathbf d_2\big\|. $$

    下图左边是俯视图(可以拖动两台相机 \(C_1,C_2\) 和真实点 \(X\)),右边是同一场景的三维视图(可以旋转,也可以切到"放大"看公垂线)。相机始终朝向场景中心。噪声被刻意放大了(默认 6 像素,真实角点检测通常在 1 像素以内),否则公垂线短得看不见。两条射线夹的角 \(\alpha\) 叫三角化角(视差角)。

    滑块的第二个功能是模拟一次误匹配:把相机 2 里的像素沿(或垂直于)对极线平移。猜一猜:哪一种误匹配更容易被发现?

    FIG 1两条几乎相交的射线
    俯视图 (x–y)
    三维(拖动旋转)
    青色:两台相机及其视线;紫色:真实点 \(X\);琥珀色:公垂线与中点 \(\hat X\)。"沿对极线"移动相机 2 的像素等价于让点沿相机 1 的射线滑动,所以两条射线仍然相交,只是交在错误的位置;"垂直于对极线"移动则让射线变成异面。一致性检验:\(\hat X\) 在两张图里的重投影误差合起来不超过 \(3\sigma\)。
    试一试
    • 把像素噪声调到 0:公垂线缩成一个点(\(d_{\min}<1\) mm),射线恰好相交。这是它们唯一相交的时候。
    • 把两台相机拖近,使 \(\alpha<10^\circ\),并让估计误差 \(\|\hat X-X\|\) 超过 0.5 m。同样的像素噪声,为什么误差变大了?
    • 选"沿对极线",把误匹配平移至少 40 像素,使一致性检验仍然通过、而点已偏离真值 0.4 m 以上。
    • 选"垂直于对极线",平移至少 40 像素,让检验失败。
    核心洞见

    三角化 = 求一组本来不相交的射线的"交点"。所以每个算法都是对"最接近"的一种选择(什么度量?在哪个空间?),再加上一份说明:这个答案有多不确定。沿对极线的误匹配会给出一个完美自洽却错误的三维点,单靠两个视角的几何检验抓不到它,需要第三个视角或先验。

    3动手玩:三种估计与更多视角

    "最接近"有不止一种答案。本节在同一批带噪声的像素上运行三个真正的算法(它们都在这个页面里实时运行):

    • 中点:使三维空间中到各条射线的距离平方和最小(\(N=2\) 时就是上一节的公垂线中点)。
    • 线性 DLT:把每个视角写成两个线性方程,堆成 \(A\tilde{\mathbf X}=0\),取 SVD 最小奇异值的右奇异向量(1.12)。
    • 最优(重投影):最小化 \(\sum_i\|\mathbf x_i-\pi(P_i\mathbf X)\|^2\),即像素空间中的平方误差,用 DLT 作初值做 Gauss–Newton(6.6)。

    左图是几何(相机沿一条路径排开,第一个最近、最后一个最远),右图把真值附近放大:小点是 150 次独立噪声实验各自的结果,大点是第 1 次实验。右侧表格给出 150 次实验的统计。

    FIG 2三种估计器
    几何(俯视)
    真值附近放大
    紫色十字:真值;紫色虚线椭圆:理论协方差(Cramér–Rao 界)的 95% 椭圆(见第 5 节)。"重投影 RMS"是每个视角的像素残差的均方根;最优估计的期望值是 \(\sigma\sqrt{(2N-3)/N}\)(\(2N\) 个测量,3 个自由度)。读数里的最后一项:把世界原点平移 3 m 后重新做一次 DLT,结果移动了多少(真正的几何方法不应该移动)。
    • 用 \(N=2\) 并把最远相机拉远("远端距离"约 8 m 以上),使 DLT 的重投影 RMS 达到最优估计的 2 倍以上,但两者的三维误差只差几个百分点。

    三个观察。(1)中点和 DLT 几乎重合:DLT 每个方程都等于"点到射线的距离"乘一个常数,它其实是中点法的代数版本(第 5 节推导)。(2)最优估计的三维误差只比它们小几个到几十个百分点,但重投影误差却小得多,因为前两种方法"不在乎"像素:近处相机的 1 像素对应的米数少,远处相机的多,而它们对两者一视同仁。(3)视角越多越好,误差大致按 \(1/\sqrt N\) 下降,并且最优估计逼近理论界。

    一个问题,三种看法

    几何的:找离所有射线最近的点(中点)。代数的:找 \(A\tilde{\mathbf X}=0\) 的近似零空间向量(DLT,1.12)。统计的:假设像素噪声是高斯的,则最大似然估计就是最小化重投影误差(4.6、6.9),并且噪声传播给出答案的协方差(4.5)。三者在无噪声时给出同一个点;有噪声时它们的区别,正是"在哪个空间里度量误差"。

    4第二个视角:不确定性椭球

    只看一次估计的好坏意义不大。更有用的是问:同样的相机、同样的噪声,重复很多次,估计点会散成什么形状?答案是一个细长的椭球:它沿着观测方向很长,垂直于观测方向很短。原因很直观:一个像素误差只让射线在横向偏几毫米(\(\approx Z\sigma/f\)),而两条射线夹角很小时,横向的小偏移会让交点沿射线方向滑出很远。

    下图用蒙特卡洛实验(500 次,种子固定)画出这个云团,并叠加由重投影雅可比算出的理论协方差 \(\Sigma_X=\sigma^2(\sum_i J_i^\top J_i)^{-1}\)(推导见第 5 节,用到 4.5 与 6.9)。两台相机平行朝前(+y 方向),点在前方 \(Z\) 处。

    FIG 3不确定性椭球实验室
    真实比例的场景(俯视)
    估计点云(放大,等比例)
    琥珀色小点:500 次噪声实验的三角化结果(x–y 投影,每次用 DLT 初始化再做 Gauss–Newton);青色实线椭圆:理论协方差的 x–y 边缘 95% 椭圆;蓝色虚线:样本协方差的同一椭圆。左图虚线方框是右图的取景范围。基线沿"运动方向"放置:横向时两台相机左右并排,向前时一台在另一台正后方。
    • 点"设为参考",然后把基线 \(B\) 加倍(其他不变):沿视线方向的误差 \(\sigma_1\) 变成原来的多少?
    • 重新设参考,把深度 \(Z\) 加倍:\(\sigma_1\) 变成原来的多少倍?
    • 把运动方向换成"向前":同样的 \(B\),\(\sigma_1\) 比横向时大 5 倍以上。这就是直行的机器人看不准正前方的原因。

    注意读数里两处对照:理论值与蒙特卡洛值在横向运动时吻合到百分之几(样本只有 500 个,本身就有约 3% 的抽样误差);而在"向前"或很小基线时,云团变成弯曲的、有长尾的"香蕉",线性化的协方差低估了真实的散布,而且估计还带有偏差。这提醒我们:协方差只是一阶近似。

    同一个椭球,三句话

    (1)深度精度:\(\Delta Z\approx Z^2\Delta d/(fB)\),基线加倍误差减半,深度加倍误差变四倍(11.2 的结果,这里是它的一般形式)。(2)椭球的长宽比约为 \(2/\alpha\)(\(\alpha\) 为三角化角,弧度):夹角 6.8° 时约 17:1。(3)向前运动:\(\alpha\to0\),椭球沿视线无限拉长;点正好在光轴上时深度完全不可观测。

    5再看数学

    提示:把鼠标悬停在公式中带底色的符号上,FIG 1、3、4、5 中对应的元素会被高亮。

    每个视角给出什么

    相机 \(i\) 的外参 \({}^{c}T_{w}=(R_i,\mathbf t_i)\)(世界 → 相机,OpenCV 的 \([R|t]\)),投影矩阵 \(P_i=K_i[R_i\,|\,\mathbf t_i]\)(10.3)。点 \(\tilde{\mathbf X}=(\mathbf X,1)\) 的像素满足 \(\lambda_i\tilde{\mathbf x}_i=P_i\tilde{\mathbf X}\),其中 \(\lambda_i\) 恰是点在相机 \(i\) 里的深度 \(z_i\)。反过来,光心是 \(\mathbf o_i=-R_i^\top\mathbf t_i\)(相机位姿 \({}^{w}T_{c}\) 的平移),像素 \(\mathbf x_i\) 的射线方向是 \(\mathbf d_i\propto R_i^\top K_i^{-1}\tilde{\mathbf x}_i\)。

    中点:二次函数的极小

    令 \(\mathbf w=\mathbf o_1-\mathbf o_2\),\(b=\mathbf d_1\!\cdot\!\mathbf d_2=\cos\hl{alpha}{\alpha}\),\(c_1=\mathbf d_1\!\cdot\!\mathbf w\),\(c_2=\mathbf d_2\!\cdot\!\mathbf w\)。对 \(\|\mathbf w+s\mathbf d_1-t\mathbf d_2\|^2\) 分别对 \(s,t\) 求导并令其为零,得到 \(s-bt=-c_1\),\(-bs+t=c_2\),因此

    $$ s^{*}=\frac{b\,c_2-c_1}{1-b^{2}},\qquad t^{*}=\frac{c_2-b\,c_1}{1-b^{2}},\qquad 1-b^2=\sin^2\alpha,\qquad d_{\min}=\frac{|\mathbf w\cdot(\mathbf d_1\times\mathbf d_2)|}{\|\mathbf d_1\times\mathbf d_2\|}. $$

    分母 \(\sin^2\alpha\):射线平行(\(\alpha\to0\))时公式失效,这是第一次遇到"小基线灾难"。\(N\) 条射线的推广是 \(\hat{\mathbf X}=\big(\sum_i(I-\mathbf d_i\mathbf d_i^\top)\big)^{-1}\sum_i(I-\mathbf d_i\mathbf d_i^\top)\mathbf o_i\),其中 \(I-\mathbf d_i\mathbf d_i^\top\) 把向量投影到与射线垂直的平面;它是线性最小二乘(1.13)。注意它最小化的是米,不是像素。

    线性 DLT 与代数误差

    \(\lambda\tilde{\mathbf x}=P\tilde{\mathbf X}\) 里未知的 \(\lambda\) 可以用叉积消去:\(\tilde{\mathbf x}\times(P\tilde{\mathbf X})=\mathbf 0\)。记 \(\mathbf p_k^{\top}\) 为 \(P\) 的第 \(k\) 行,其中两个独立方程是 \((u\,\mathbf p_3^\top-\mathbf p_1^\top)\tilde{\mathbf X}=0\) 和 \((v\,\mathbf p_3^\top-\mathbf p_2^\top)\tilde{\mathbf X}=0\)(第三个是它们的线性组合)。\(N\) 个视角堆成 \(2N\times4\) 的矩阵:

    $$ A\tilde{\mathbf X}=\begin{bmatrix} u_1\,\mathbf p_3^{(1)\top}-\mathbf p_1^{(1)\top}\\ v_1\,\mathbf p_3^{(1)\top}-\mathbf p_2^{(1)\top}\\ \vdots\\ u_N\,\mathbf p_3^{(N)\top}-\mathbf p_1^{(N)\top}\\ v_N\,\mathbf p_3^{(N)\top}-\mathbf p_2^{(N)\top}\end{bmatrix}\tilde{\mathbf X}=\mathbf 0,\qquad \tilde{\mathbf X}^{*}=\arg\min_{\|\tilde{\mathbf X}\|=1}\|A\tilde{\mathbf X}\|=\mathbf v_{4},\qquad \mathbf X=\tfrac{\tilde X_{1:3}}{\tilde X_4}. $$

    \(\mathbf v_4\) 是 \(A\) 的 SVD(1.12)中最小奇异值对应的右奇异向量。看看它在最小化什么:每一行等于 \((\mathbf p_3^\top\tilde{\mathbf X})(u-\hat u)=z_i\,(u_i-\hat u_i)\),即深度乘像素残差。它与点到射线的距离也有关系:这两行恰是叉积 \(\mathbf X_c\times\mathbf m\) 的两个分量(再乘以焦距;\(\mathbf X_c\) 是点在相机坐标系里的坐标,\(\mathbf m=K^{-1}\tilde{\mathbf x}\) 是射线方向),而这个叉积的模等于 \(\|\mathbf m\|\) 乘以点到射线的距离,所以 DLT 是中点法的代数版本(FIG 2 里两者几乎重合)。因此 DLT 最小化的不是像素误差,它让远处的相机占更大的权重;并且条件 \(\|\tilde{\mathbf X}\|=1\) 依赖于坐标系的选择,把世界原点平移一下答案就会变(FIG 2 的最后一项)。实现时应先对像素做归一化(用 \(K^{-1}\) 变成归一化坐标)并把世界坐标平移缩放到原点附近。

    最优:最小化重投影误差

    $$ \hat{\mathbf X}=\arg\min_{\mathbf X}\sum_{i=1}^{N}\big\|\mathbf x_i-\pi(P_i\tilde{\mathbf X})\big\|^2,\qquad \Delta\mathbf X=\Big(\sum_i J_i^\top J_i\Big)^{-1}\sum_i J_i^\top\mathbf r_i,\qquad J_i=\frac{\partial\pi}{\partial\mathbf X}=\begin{bmatrix}\tfrac{f_x}{z} & 0 & -\tfrac{f_x x_c}{z^2}\\ 0 & \tfrac{f_y}{z} & -\tfrac{f_y y_c}{z^2}\end{bmatrix}R_i. $$

    其中 \((x_c,y_c,z)=R_i\mathbf X+\mathbf t_i\) 是点在相机 \(i\) 坐标系里的坐标,\(\mathbf r_i=\mathbf x_i-\pi(\cdot)\) 是残差(3.3 的雅可比,6.6 的 Gauss–Newton)。像素噪声是独立同方差的高斯时,这就是最大似然估计(4.6)。问题只有 3 个未知数,用 DLT 作初值,3 到 5 次迭代就收敛;页面里的实现还加了步长折半以保证代价不上升。两个视角时还有闭式的全局最优解:Hartley–Sturm 把问题化为一个 6 次多项式求根;Lindstrom 给出更快的近似。

    协方差与椭球的形状

    把像素噪声 \(\mathrm{cov}(\mathbf x_i)=\sigma^2I\) 通过 Gauss–Newton 的解传播(4.5):线性化后 \(\delta\mathbf X=(\sum J_i^\top J_i)^{-1}\sum J_i^\top\delta\mathbf x_i\),所以

    $$ \hl{cov}{\Sigma_{X}}=\sigma^2\Big(\sum_{i=1}^{N}J_i^\top J_i\Big)^{-1}. $$

    这是 6.9 里"高斯–牛顿的 Hessian 的逆",也是 Cramér–Rao 界,信息 \(\sum J_i^\top J_i\) 在视角之间相加。每个 \(J_i^\top J_i\approx(f/r_i)^2(I-\mathbf u_i\mathbf u_i^\top)\)(\(\mathbf u_i\) 是单位视线,\(r_i\) 是点到相机的距离):一个视角只在垂直于视线的两个方向上提供信息,沿视线的方向一点也没有。取两个等距(\(r_1=r_2=r\))的相机,三角化角为 \(\alpha\),三个主轴上的标准差为

    $$ \sigma_{\text{range}}\approx\frac{r\sigma}{\sqrt2\,f\,\sin(\alpha/2)},\qquad \sigma_{\perp}\approx\frac{r\sigma}{\sqrt2\,f\,\cos(\alpha/2)},\qquad \sigma_{\text{vert}}\approx\frac{r\sigma}{\sqrt2\,f},\qquad \frac{\sigma_{\text{range}}}{\sigma_\perp}=\cot\frac\alpha2\approx\frac2\alpha. $$

    范围方向(沿角平分线)的信息只有 \(2\sin^2(\alpha/2)\,(f/r)^2\),随 \(\alpha\) 平方消失。对校正过的双目,\(\sin(\alpha/2)\approx B/(2Z)\),代入得 \(\sigma_Z=\sqrt2\,\sigma Z^2/(fB)\),恰是 11.2 里 \(\Delta Z=Z^2\Delta d/(fB)\) 配上视差噪声 \(\sigma_d=\sqrt2\sigma\)(两张图各有独立噪声)。一般地,\(\alpha\approx B\sin\gamma/r\),其中 \(\gamma\) 是基线与视线的夹角:基线与视线平行(\(\gamma=0\),向前运动)时没有视差。

    逆深度

    校正过的双目里 \(Z=fB/d\),所以 \(\rho=1/Z=d/(fB)\) 是视差的线性函数。视差噪声是高斯的,\(\rho\) 就是高斯的,且 \(\sigma_\rho=\sqrt2\sigma/(fB)\) 与深度无关;而 \(Z=1/\rho\) 的分布是歪的、有长尾,当 \(\rho\) 的误差棒跨过 0 时,\(Z\) 甚至会变成负的或无穷大(FIG 5)。一般的单目情形把路标写成"锚点相机光心 \(\mathbf c\) + 方向 \(\mathbf m(\theta,\phi)\) + 逆深度 \(\rho\)":\(\mathbf X=\mathbf c+\mathbf m/\rho\)。另一台相机 \(j\) 看到它的像素是 \(\pi\big(R_j(\rho(\mathbf c-\mathbf o_j)+\mathbf m)\big)\)(投影对整体缩放不变,乘以 \(\rho\)),\(\rho=0\) 时依然有定义:无穷远的点只约束相机的旋转(Civera–Davison–Montiel)。

    6机器人中的它:SLAM 里的视差门槛

    单目 SLAM 的机器人在路上走,每个新特征第一次被看到时只有一条射线,深度未知。随着机器人移动,同一特征在后续帧里被再次观测,才有可能三角化。这时就要回答一个很实际的问题:什么时候可以把它当作路标放进地图?太早(视差不足),深度几乎是猜的,坏路标会拖垮位姿估计;太晚,又浪费了观测。

    FIG 4 把这件事做成实验。机器人沿 x 轴直线行驶,距离首帧 \(b\);路标在 8 m 远,相对行驶方向的方位角 \(\gamma\) 可选:"侧视"(90°)、"斜前方"(30°)、"正前方"(8°)。右图是路标沿视线方向的相对不确定性 \(\sigma_r/r\)(用首帧与当前帧的两视角协方差计算,对数坐标)与行驶距离的关系。常见的两种准入规则分别画成阈值:不确定性小于 \(\varepsilon\),或者三角化角大于 \(\alpha_{\min}\)。

    FIG 4SLAM 里的视差门槛
    场景(俯视,真实比例)
    σᵣ/r(对数)随行驶距离
    左图:青色为首帧相机,琥珀色为当前相机,紫点是路标真值,琥珀色椭圆是两视角估计的 95% 椭圆(x–y 边缘,真实比例)。右图:三条曲线分别对应三个方位角(当前选中的最粗),横向虚线是 \(\varepsilon\),竖向实线是当前的 \(b\);琥珀 / 紫色三角分别标出满足"不确定性"和"视差角"规则所需的最小行驶距离。
    • 先在"侧视"下找到满足不确定性规则(\(\sigma_r/r<\varepsilon\))的最小 \(b\);再选"正前方",把 \(b\) 拖到同样满足规则。需要多行驶几倍?

    读图的要点:\(\sigma_r/r\approx\sqrt2\,(\sigma/f)\,r/(b\sin\gamma)\),与 \(b\sin\gamma\)(垂直于视线的位移,即有效基线)成反比。侧视时 \(b\) 就是有效基线;正前方时 \(\sin\gamma\) 很小,必须多走约七倍(\(1/\sin8^\circ\))才能达到同样的精度。这正是视觉 SLAM 在"直行靠近一面墙"时尺度和深度容易漂的原因。

    下面的 FIG 5 再看另一件事:就算已经过了门槛,深度的分布也不是高斯的。

    FIG 5深度 Z 与逆深度 ρ 的分布
    深度 Z(米)的直方图
    逆深度 ρ = 1/Z(1/米)的直方图
    1200 次独立噪声实验,每次对一对平行双目相机做真正的 DLT 三角化。青色曲线是高斯分布:左图是"在 Z 里线性化"的高斯 \(\mathcal N(Z,\ \sigma_\rho Z^2)\),右图是 \(\mathcal N(\rho,\ \sigma_\rho)\);虚线标出真值。直方图是对全部样本归一化的密度;左图只画 \(0\) 到 \(2.5Z\) 的范围,范围外的样本不显示,所以它的面积小于 1,缺的部分就是长尾。
    • 拖动深度或基线,让 \(Z\) 的偏度超过 2,而 \(\rho\) 的偏度仍在 \(\pm0.3\) 以内。
    真实系统里

    ORB-SLAM 系列:新地图点由共视关键帧之间的匹配三角化,并且拒绝视差角过小(量级约 1°)、重投影误差过大或深度为负的点;VINS-Mono 等视觉惯性系统在滑窗里用逆深度表示特征,并按平均视差挑选关键帧;DSO 等直接法同样使用逆深度。COLMAP(SfM)在增量重建时对每个轨迹做多视图三角化,有最小三角化角(默认约 1.5°)和最大重投影误差的过滤,并用 RANSAC 抵抗误匹配。双目 / RGB-D 与立体相机:校正后每个像素就是一个共面三角化,即 \(Z=fB/d\)。动捕系统(如 Vicon、OptiTrack)把标定好的多台相机看到的反光球三角化成三维点;多相机 AprilTag 与人体 / 手部关键点(遥操作数据采集)则是在每台相机里检测二维点,再加权三角化。(具体阈值与默认值随版本不同,使用前请查阅文档。)

    7常见误区

    误区 1:基线太小也照样三角化

    代码不会报错:DLT 总会给你一个点,只不过它的深度误差可能是几十米。机器人原地转动(纯旋转)时基线为 0,根本没有深度信息,此时两帧之间的关系是单应(10.5),不是对极几何。工程上要检查三角化角(或基线 / 深度比),并把"深度未定"的点保留为只有方向的特征。FIG 3 的"向前"挡直接展示了这一点。

    误区 2:把远处的深度误差当作对称高斯

    "Z = 20 ± 5 m"听起来对称,真实分布却是歪的:偏近的一侧很窄,偏远的一侧拖着长尾,甚至包含无穷远(FIG 5)。把 \(Z\) 当作卡尔曼滤波的状态,线性化会在视差小的时候失效;用逆深度,噪声的分布就接近高斯,滤波和优化都稳得多。

    误区 3:以为"几何自洽"就是"对了"

    好的三角化管线要做三个检验:(a)手性(cheirality):点在每台相机前面(\(z_i>0\),并且射线参数 \(s,t>0\)),否则射线是发散的;(b)重投影误差在每张图里都小于阈值;(c)视差角足够大。但 FIG 1 说明,沿对极线的误匹配通过 (a)(b),因为它恰好对应射线 1 上的另一个点;只有第三个视角、描述子距离或深度先验才能抓住它。因此 SfM 和 SLAM 才依赖多视图轨迹和 RANSAC,而不是两两检验。

    误区 4:用 DLT 的结果直接当"最优解"

    DLT 最小化的是代数误差 \(\|A\tilde{\mathbf X}\|\)(深度 × 像素残差),既不是像素误差,也不具有射影不变性。三维误差也许只差几个百分点,但它的重投影残差明显更大,会误导后面的外点检验。DLT 只适合作为初值,之后做几步 Gauss–Newton。如果不归一化(像素除以 \(K\),世界坐标靠近原点),数值条件也会变差。

    误区 5:相机模型、单位或位姿方向搞错

    最常见的 bug:把相机位姿 \({}^{w}T_{c}\) 当作外参 \({}^{c}T_{w}\) 塞进 \(P=K[R|t]\)(二者互逆);用带畸变的像素直接三角化而忘了先去畸变(10.3);基线用厘米、焦距用像素、深度用米混着算;左右图的顺序反了。每一种都会得到"看起来合理"的点云,只是位置或尺度错了。最可靠的自检:把得到的三维点用原相机重投影,看误差是否在噪声量级。

    8小练习

    1. 相机的投影矩阵第 \(k\) 行为 \(\mathbf p_k^\top\),观测像素是 \((u,v)\)。它给 DLT 矩阵 \(A\) 贡献的两行是?
    \(\lambda(u,v,1)^\top=P\tilde{\mathbf X}\) 给出 \(u=\mathbf p_1^\top\tilde{\mathbf X}/\mathbf p_3^\top\tilde{\mathbf X}\) 与 \(v=\mathbf p_2^\top\tilde{\mathbf X}/\mathbf p_3^\top\tilde{\mathbf X}\),交叉相乘得 \((u\mathbf p_3^\top-\mathbf p_1^\top)\tilde{\mathbf X}=0\) 和 \((v\mathbf p_3^\top-\mathbf p_2^\top)\tilde{\mathbf X}=0\)。选项 B 把 \(\mathbf p_3\) 与 \(\mathbf p_1\) 的位置弄反了;C 混淆了齐次与非齐次;D 的那一行线性相关于前两行,一个视角实际上提供 2 个独立方程,3 个未知数要求至少两个视角。
    2. 校正后的双目:\(f=600\) 像素,基线 \(B=0.12\) m,目标距离 \(Z=3\) m,视差噪声 \(0.5\) 像素。深度误差约为?
    \(\Delta Z\approx Z^2\Delta d/(fB)=9\times0.5/(600\times0.12)=4.5/72=0.0625\) m。2.1 cm 是漏掉一个 \(Z\) 的结果(\(Z\Delta d/(fB)\));0.7 cm 是忘了乘 \(Z^2\);25 cm 则相当于基线只有 3 cm(小了四倍)。深度误差与 \(Z^2\) 成正比,这就是 3 m 时厘米级、30 m 时就是几米的原因。
    3. DLT 三角化的"代数误差"\((u\,\mathbf p_3^\top-\mathbf p_1^\top)\tilde{\mathbf X}\) 等于?
    \(u\,\mathbf p_3^\top\tilde{\mathbf X}-\mathbf p_1^\top\tilde{\mathbf X}=(\mathbf p_3^\top\tilde{\mathbf X})(u-\hat u)\),而 \(\mathbf p_3^\top\tilde{\mathbf X}=z\)。所以远处的相机残差被放大,DLT 与"所有像素等权"的最大似然不同。它与点到射线的距离只差一个近似常数因子(焦距与视场相关),所以选项 C 不精确;有噪声时 \(\tilde{\mathbf X}\) 只在近似零空间里,残差不为零。
    4. 机器人沿光轴直线前进,用前后两帧三角化正前方光轴上的一个点。结果是?
    基线与视线平行,\(\sin\gamma=0\),三角化角 \(\alpha=0\):两帧里该点都落在主点,像素完全相同,没有视差,信息矩阵沿视线方向为零,深度的方差无穷大。基线长不等于视差大,有效基线是垂直于视线的那一部分 \(b\sin\gamma\)。稍微偏离光轴的点会有一点点视差,但很小(FIG 3、FIG 4)。
    5. 校正双目、视差噪声为高斯。对一个很远的点,哪个量的估计分布最接近高斯?
    \(\rho=d/(fB)\) 是视差 \(d\) 的线性函数,高斯噪声经过线性映射仍是高斯;\(Z=fB/d\) 是 \(d\) 的倒数,当 \(d\) 的标准差与 \(d\) 本身可比时,\(Z\) 的分布严重偏斜并有长尾,甚至 \(d\le0\) 时 \(Z\) 为负或无穷。\(\log Z=-\log\rho+\text{常数}\) 也不是高斯,尽管比 \(Z\) 好一些。

    9延伸阅读

    • R. Hartley & A. Zisserman, Multiple View Geometry in Computer Vision, 2nd ed., Cambridge University Press, 2004, Ch. 12 — 结构计算:线性与几何(重投影)三角化,最优解,以及估计点的概率分布
    • R. I. Hartley & P. Sturm, Triangulation, Computer Vision and Image Understanding 68(2), 1997, 146–157 — 两视图的最优三角化:化为 6 次多项式
    • P. Lindstrom, Triangulation Made Easy, CVPR 2010 — 快速、非迭代、接近最优的两视图三角化
    • R. Szeliski, Computer Vision: Algorithms and Applications (1st ed., 2010, §7.1; in the 2nd ed., 2022, the chapter on structure from motion and SLAM) — 三角化与 SfM 的整体流程
    • J. Civera, A. J. Davison & J. M. M. Montiel, Inverse Depth Parametrization for Monocular SLAM, IEEE Transactions on Robotics 24(5), 2008 — 逆深度:为什么它能让无穷远的路标进入滤波器
    • J. L. Schönberger & J.-M. Frahm, Structure-from-Motion Revisited, CVPR 2016 — COLMAP 的增量重建,包含多视图三角化与过滤的工程细节