AI Hero Club

视觉与三维场景 · 第 5 章

已自行标记完成0 / 8

仅保存在当前浏览器;完成标记不代表通过项目验收。

本章提纲 4 个小节
全课目录 8 章
完整课程计划 ↗
视觉与三维场景 / 课程计划 ↗

CHAPTER 05 / 8建议学习 120 分钟

三角化、深度敏感性与几何精化

两条像素观测怎样给出三维位置,为什么重投影误差很小也可能深度极不稳定?

本章要解决的 3 个问题
  • 从一般相机的像素方程建立三角化
  • 区分代数解、重投影与真实几何误差
  • 计算视差误差到深度误差的传播
课程项目 ZIP ↓

像素约束、三角化与深度不确定性

现在已经有两张图的候选对应与各自相机矩阵,本章求未知世界位置。输入只有像素、相机和匹配记录,不含珠子三维真值。理想情况下两条世界射线相交于同一点;检测噪声下通常不严格相交,需要一个明确的近似目标。我们先求线性齐次三角化,再检查正深度和像素残差,最后讲怎样用几何误差精化。不存在“给两个点便必定有可信深度”的无条件定理。

令未知齐次三维点为四维向量,左相机三行记为 P 的行向量,右相机记为 Q。与 DLT 相同,左像素横坐标乘第三行减第一行、纵坐标乘第三行减第二行,各与未知点点积等于零;右图再贡献两行。四行堆成四乘四矩阵 A,寻找单位长度的近似零空间向量,再用第四分量除前三分量,得到欧氏位置。若第四分量接近零,点可能趋于无穷远或几何退化,不能直接除出巨大数字冒称成功。

A=[uP3−P1vP3−P2u′Q3−Q1v′Q3−Q2],AX~≈0,X=X~1:3/X~4A=\begin{bmatrix}uP_3-P_1\\vP_3-P_2\\u^{\prime} Q_3-Q_1\\v^{\prime} Q_3-Q_2\end{bmatrix},\quad A\tilde X\approx0,\quad X=\tilde X_{1:3}/\tilde X_4
u、v 与带撇号的坐标分别来自左右图;撇号不是求导。

奇异值分解给最小代数残差方向,作用与上一章相机 DLT 相似,但这次未知是一个点而不是相机。对每个点求出位置后,重新投影到左右相机,计算两个二维像素残差平方和的一半再开根号,作为每视角二维 RMS。项目门槛是一像素。门槛是固定规则,不是后验地调到所有输出都通过;超过门槛的候选被明确记录为拒绝。

正深度检查独立于残差。某个三维点可以在数学上投影到两个像素,却位于一台相机背后,不能解释正常针孔可见观测。项目投影函数遇到非正深度直接拒绝。因此正常轨迹须同时满足描述子、极线、有限齐次位置、正深度与重投影。即便这些条件全过,也仍可能是一个外观重复、几何自洽的错物体,所以输出保留原始观测与匹配距离,不把门槛提升为身份证明。

算例一:平行双目的米制深度

先看容易手算的特殊情况,两相机同姿态、内参相同、右相机中心横移基线 B。左归一化横坐标是 X 除 Z,右边是 X 减 B 后除 Z;相减得到 B 除 Z。乘像素焦距 f,视差 d 等于 fB 除 Z,所以 Z 等于 fB 除 d。设焦距一百像素、基线零点二米、视差十像素,深度为二米。若左横像素距主点十五,则 X 为十五乘二除一百,即零点三米。

d=uL−uR=fBZ,Z=fBd,∂Z∂d=−fBd2d=u_L-u_R=\frac{fB}{Z},\qquad Z=\frac{fB}{d},\qquad \frac{\partial Z}{\partial d}=-\frac{fB}{d^2}
此式仅对同姿态或已校正双目使用;一般旋转由矩阵三角化处理。

在同一设置下,视差误差零点二像素的一阶深度误差幅度是二十除一百乘零点二,即零点零四米。若真实深度改为十米,视差只有二像素,同样零点二像素对应约一米误差。图像测量看起来同样精细,远处深度却明显更不稳定。减小基线也会降低视差。误差公式揭示采集几何限制,不能靠在结果表中增加小数位修复。

独立左右横坐标误差若各有方差 s 平方,视差误差方差是二 s 平方;若二者相关,还要减去两倍协方差。深度局部方差近似为深度导数平方乘视差方差。这是小噪声一阶传播,不是所有噪声分布下的精确后验;视差接近零时函数非线性强,可能出现偏斜长尾甚至无效深度。此时更适合报告区间、拒绝或保留射线,而不是把线性标准差当完整可信范围。

算例二:低重投影误差与错误绝对尺度

假设两个相机中心和所有真实点共同放大十倍,旋转与内参保持原值。每个相机中的相对位置也放大十倍,透视除法全部抵消,因此重投影误差可以仍为零;但输出单位若继续声称米,真实尺寸错十倍。这一失败不靠更多图像残差就能发现,需要已知标靶尺寸、基线或独立长度检查。项目用米制非共面靶给相机尺度,因此三维 RMS 才具有米单位含义。

项目从前两张训练图片提取十二条匹配,按一般旋转相机矩阵重建。评价阶段才读取真值,对颜色身份建立参照,三角化位置 RMS 实测约零点零零二九零八米。该数值使用有限受控场景,没有遮挡与真实镜头畸变,不能外推为自然场景毫米级能力。逐点误差也保存,最大点与平均不同,任何看似精确的整体均值都不能替代逐点检查。

若要几何精化,可以直接最小化各视角像素残差平方和。设位置增量为三维向量,投影在当前点附近以雅可比 J 线性化,残差变成 r 加 J 乘增量。展开平方并对增量求导,正规方程为转置 J 乘 J 再乘增量,等于负转置 J 乘 r。求解后更新位置并重新检查真实目标;过大步长可能离开局部线性范围,需要阻尼或回溯,不能假定一次线性解就是最优。

(J⊤J+λI)δ=−J⊤r,Xnew=X+δ(J^\top J+\lambda I)\delta=-J^\top r,\qquad X_{new}=X+\delta
lambda 是非负阻尼;设零时为局部 Gauss–Newton 方程。

若同时优化相机与所有点,就得到束调整问题。它的目标来自同一重投影残差,但引入共同坐标变换与尺度自由度,必须固定一个参考相机和尺度或其他约束。相机旋转还要用合法参数更新,不能把九个矩阵元素当自由数而任其失去正交。当前项目不运行完整束调整,而在固定标定相机下拟合小型发光 Gaussian 场景;这两种优化目标和参数范围必须区分。

残差通过后再问:哪些方向仍没有足够信息

将基线改为0.0001米、焦距95像素,真点(0.1,0.1,4)在平行双目中的视差只有.002375像素。若右图横坐标增加.002像素,剩余视差为.000375,重算深度95×.0001/.000375=25.3333米。两个射线仍能精确相交,因此重投影RMS可接近零。这是“找到一个几何自洽点”与“精确知道深度”的区别,不应被成功布尔值抹掉。

一般旋转时不依赖平行视差公式,直接对四个像素预测关于三维位置求雅可比J。它为4×3矩阵,第i个相机的某一坐标导数是(P行前三项−该像素坐标×P第三行前三项)/深度。若局部像素误差独立、同方差s²,并暂把相机当已知,线性化最小二乘的协方差近似为s²(JᵀJ)逆。J的最小奇异值越小,最弱三维方向越难确定;最大位置标准差为s除最小奇异值。

Cov⁡(δX)≈s2(J⊤J)−1,σX,max⁡=sσmin⁡(J)\operatorname{Cov}(\delta X)\approx s^2(J^\top J)^{-1},\qquad \sigma_{X,\max}=\frac{s}{\sigma_{\min}(J)}
只在局部线性、固定相机与该像素噪声假设下成立;若J退化,不能取普通逆宣称有限可信区间。

现在主重建报告中每条轨迹包含geometry_diagnostics:基线、两条射线夹角、基线/距离比、J的奇异值、假设像素噪声及最大位置标准差。默认假设s=.1像素,并把最大位置标准差/到相机中点距离超过.25的轨迹标为weak_geometry;否则只称locally_constrained,不称真值可信。阈值与噪声均作为参数显式记录。弱几何仍可作为待补观测点保留,但不能与充分约束轨迹同等无条件解读;有实际应用容差时,应由容差制定拒绝策略。

这个诊断没有加入相机标定误差、非高斯离群点和身份错配,也没有在强非线性小视差处把线性近似升级为精确后验。它提供可检查的局部信息量,不是安全保证。当前主场景无需重训即可重新输出诊断;旧180步拟合报告和检查点作为原冻结实验保留,新增诊断与回归另存,避免把新源码散列冒充旧实验原始来源。

在课程项目目录运行用真实三角化与新诊断展示“残差几乎为零但深度不可靠”。
import numpy as np
from vision3d.core import triangulate
K=np.array([[95.,0,48],[0,95,40],[0,0,1]])
P=K@np.c_[np.eye(3),np.zeros(3)]
Q=K@np.c_[np.eye(3),np.array([-.0001,0,0])]
x=np.array([.1,.1,4.,1.])
def pixel(M):
    y=M@x
    return y[:2]/y[2]
u,v=pixel(P),pixel(Q);v[0]+=.002
point,error,_,diagnostic=triangulate(u,v,P,Q,return_diagnostics=True)
assert abs(point[2]-25.3333333333)<1e-6 and error<1e-9
assert diagnostic['geometry_status']=='weak_geometry'
print('depth',point[2],'rms',error,'uncertainty',diagnostic)

噪声、错配和弱基线需要不同处理。噪声可通过重复观测和合理权重减少,错配适合鲁棒损失或离群拒绝,弱基线需要增加视点几何信息。把所有残差统一乘很小的权重会让报告看似好看,却不会恢复缺失信息。鲁棒损失也可能忽略真正复杂区域,因此需保留被降权的观测与理由。当前一像素门槛只作教学可检查版本,不宣称统计最优。

输出点云还必须说明哪些东西没有重建。这里只有能在至少两图中被检测和正确匹配的亮斑中心,不包含珠子背面纹理、场景表面、隐藏物体和任意实心体积。点之间连线不自动成为网格边,点的凸包也不自动代表真实物体外壳。下一章讨论表示时会将这种几何中心信息与渲染假设分开,避免从稀疏点凭空推断连续表面。

可以用已知精确投影建立独立的算法正向控制:任取一般旋转的两个相机与一个前方点,用前向函数生成无噪声像素,再三角化检查位置。这个测试只证明数值公式与投影约定匹配。另一个删除真值文件仍能重建的测试证明信息边界;真实 PNG 的几何 RMS 则测整个观测链。三种证据回答不同问题,不能把最容易的精确投影测试包装成实际图像管线质量。

对多于两视角的点,可把每视角两行约束继续堆叠,求同一个近似零空间向量。多观测可能改善抗噪声,但新增错配也会拖偏全部结果。合理方案先检查每视角残差,保留可见性与匹配置信信息,再进行鲁棒重估;不能因为方程数量增加就保证质量提升。当前项目三角化明确只用前两图,因此第三图的光度拟合是新的约束,而非把未使用的多视角线性重建写成既成事实。

独立运行视差扰动的一阶预测与直接重算对照。
f,B,d=100.,.2,10.
Z=f*B/d
linear=-(f*B/d**2)*.2
exact=f*B/(d+.2)-Z
assert Z==2.0
print({'depth_m':Z,'linear_delta_m':linear,'exact_delta_m':exact})

TRY IT YOURSELF

练习一:基线改变

焦距一百像素、深度五米,基线从零点二米变成零点零二米。视差各多少?同为零点一像素误差时深度一阶误差各多少?

提示 1
先算视差d=fB/Z,再对Z=fB/d求视差导数。
提示 2
两种基线分别代入并乘像素误差;当相对误差变大时别忘核对线性近似范围。
对照参考解答
视差分别是一百乘零点二除五等于四像素,以及零点四像素。深度导数幅度为 fB 除 d 平方,前者二十除十六等于一点二五米每像素,后者二除零点一六等于十二点五。乘零点一得到零点一二五米与一点二五米。弱基线让深度敏感性放大十倍,后一误差已经不很小,线性近似的可靠性也要另外检查。

TRY IT YOURSELF

练习二:几何残差单位

左右二维像素残差长度分别三与四。项目定义的每视角 RMS 是多少?若按四个坐标平均再开根号又是多少,为什么不能混用?

提示 1
先写每视角RMS的分子与分母,分母是视角数还是坐标数?
提示 2
两种约定共享平方残差总和但除数不同,检查单位与阈值必须同一口径。
对照参考解答
两个视角的平方长度和是九加十六等于二十五,除二再开根号得根号十二点五,约三点五三六像素。若按四个坐标平均则为根号六点二五等于二点五像素。两者相差根号二,都是可定义的统计,但报告与门槛必须匹配。项目定义前者,所以不能拿另一软件的每坐标 RMS 直接比较而不转换。

TRY IT YOURSELF

练习三:纯旋转

两个相机中心相同、姿态不同,为什么通常不能靠两个观测恢复射线上的深度?低重投影误差能否解决?

提示 1
中心相同的两相机是否形成两条不同起点的交会射线?
提示 2
沿同一世界射线改深度再投影,观察图像位置是否变化;若不变,残差无法挑出唯一深度。
对照参考解答
相机旋转只改变同一射线的坐标表达;沿该世界射线选择任意正距离点,两张图的投影都保持对应。没有中心间基线就没有三角交会的距离信息,因此深度不可识别。重投影目标在这方向上不能提供约束,残差为零也无法选唯一深度。需要平移视点、已知尺寸或其他深度信息,程序应拒绝退化或明确输出未定射线。

CHECK YOUR UNDERSTANDING

检验理解

先作答,再决定是否展开解析。选择题用于发现理解缺口;独立实现与迁移任务仍需另行检验。

1. 线性三角化最后一个齐次分量接近零意味着什么?

查看解析不能未经判断直接除出巨大欧氏坐标。
2. 固定像素噪声下远点的深度误差通常怎样?

查看解析深度对视差的导数幅度正比于视差倒数平方。
3. 低重投影是否独立证明米制尺度?

查看解析共同尺度变换可保持像素,标定靶等额外信息固定尺度。
4. 束调整与当前Gaussian拟合是否相同?

查看解析一个优化几何重投影,可联合相机;另一个在固定相机下拟合像素强度。

自行标记用于记录学习进度,不代表通过项目验收。