Contents — find the section you need

通过三角测量和 PnP 方法从运动结构重建 (Structure from Motion) 和视觉 SLAM (Visual-SLAM) 中获取的相机位姿和 3D 点,充其量只是基于线性近似和顺序处理的粗略初始值。图像噪声、对应点的量化误差以及顺序估计的传播误差都会累积,导致重建结果本身存在内部不一致。光束法平差 (Bundle Adjustment, BA) 是一种最终的优化方法,它通过同时调整每个相机参数和每个 3D 点,最小化所有观测点的重投影误差之和,从而解决这种不一致性。“光束法平差”的名称来源于它同时调整从每个 3D 点到每个相机的光束,使其与观测位置一致。

0. 30 秒概要

  • 光束法平差是一个非线性最小二乘问题,其未知量为相机的内参/外参和三维点坐标,目标是最小化所有观测值上的重投影误差平方和。

  • 它使用高斯-牛顿法或莱文伯格-马夸特 (LM) 算法迭代求解。LM 算法通过参数 \lambda 在不稳定但快速的高斯-牛顿法和缓慢但稳定的最速下降法之间平滑插值。

  • 由于单个相机仅与其实际观测到的点相关联,因此雅可比矩阵和黑塞矩阵近似值呈现稀疏的块结构形式,并按相机 × 点进行组织。这种稀疏性是解决大规模问题的关键。

  • Schur 补引理技巧利用了 3D 点块相互独立(块对角)的特性,首先消除点,从而求解一个仅包含摄像头的小型“简化摄像头系统”。这使得在合理的时间内解决包含数万个点和数千个摄像头的规模问题成为可能。

  • 捆绑调整与 SLAM 的位姿图优化密切相关,区别在于其未知量包含 3D 点本身。它是一项共享的基础技术,既用于完善 SfM,也用于 SLAM 的局部/全局优化。

1. 它需要什么输入,以及它求解什么?

输入包含以下三个初始估计值,它们是从 SfM 或 Visual-SLAM 获得的中间结果:

  • 相机位姿的初始值 \{K_i, R_i, \mathbf{t}_i\}(i=1,\dots,m;在许多情况下,相机内部参数 K_i 是已知或固定的)

  • 3D 点的初始值 \{\mathbf{X}_j\}(j=1,\dots,n;通过三角测量获得的粗略坐标)

  • 相机观测到的点的对应关系——即每次观测的图像坐标 \mathbf{u}_{ij}(相机 i 观测到点 j 的像素位置)

输出是相机位姿和 3D 点,所有数据都经过精细调整,使得每次观测之间的内部一致性更高。捆绑调整并非从零开始构建解决方案,而是一种局部优化,用于对已“大致正确”的初始值进行精细调整,这一点对于下文关于收敛性的讨论至关重要。

2. 代价函数:重投影误差

三维点 \mathbf{X}_j 在相机 i 中的投影位置与实际观测到的图像坐标 \mathbf{u}_{ij} 之间的偏差称为重投影误差。将相机 i 的位姿记为 R_i, \mathbf{t}_i,投影函数记为 \pi(\cdot)(将齐次坐标转换为像素坐标的非线性映射),则单次观测的残差为:

r_{ij} = \pi\big(K_i(R_i\mathbf{X}_j + \mathbf{t}_i)\big) - \mathbf{u}_{ij}

捆绑调整旨在最小化所有观测点对 \mathcal{O}=\{(i,j)\} 的残差平方和。

\min_{\{K_i,R_i,\mathbf{t}_i,\mathbf{X}_j\}}\sum_{(i,j)\in\mathcal{O}}\rho\left(\|r_{ij}\|^2\right)

\rho 是一个鲁棒的损失函数,例如 Huber 损失,它可以防止单个大的异常值(例如不匹配)扭曲整个优化过程。该方程与 SfM 入门 中出现的形式完全相同——捆绑调整处理了实际解决此最小化问题的计算核心。

3. 非线性最小二乘法求解:从高斯-牛顿法到 Levenberg-Marquardt 法

将所有未知量收集到一个向量 \mathbf{x} 中(所有相机位姿和所有 3D 点的集合),并将所有残差写成 \mathbf{r}(\mathbf{x}),则最小化目标为 \|\mathbf{r}(\mathbf{x})\|^2。由于 \mathbf{r} 是非线性的,我们使用围绕当前估计值 \mathbf{x}_k 的一阶泰勒展开式:\mathbf{r}(\mathbf{x}_k+\Delta\mathbf{x})\approx \mathbf{r}(\mathbf{x}_k)+J\Delta\mathbf{x}。J=\partial \mathbf{r}/\partial \mathbf{x} 是雅可比矩阵。将其代入并求解 \Delta\mathbf{x},即可得到高斯-牛顿法的正规方程:

(J^\mathsf{T}J)\,\Delta\mathbf{x} = -J^\mathsf{T}\mathbf{r}

H=J^\mathsf{T}J 是 Hessian 矩阵近似(即高斯-牛顿近似,忽略二阶项)。求解该方程得到 \Delta\mathbf{x},更新 \mathbf{x}_{k+1}=\mathbf{x}_k+\Delta\mathbf{x},并重复此操作直至残差收敛,即为整个过程。

当初始值接近解时,高斯-牛顿法收敛速度很快;但当初始值较差时,该方法容易发散。 Levenberg-Marquardt (LM) 算法由 Levenberg (1944) 和 Marquardt (1963) 分别独立提出,通过在正规方程中添加阻尼项来简化这一问题。

(J^\mathsf{T}J + \lambda D)\,\Delta\mathbf{x} = -J^\mathsf{T}\mathbf{r}

D 通常是 J^\mathsf{T}J(或等效的缩放矩阵)的对角元素,而 \lambda 是阻尼系数。当 \lambda 较小时,该算法的行为接近高斯-牛顿法,收敛速度很快;当 \lambda 较大时,该算法会采取小而稳妥的步长,更接近最速下降法。通过自适应控制方案——在每次迭代中成本降低时缩小\lambda以加速,在成本增加时增大\lambda以拒绝并缩短步长——LM算法兼具高斯-牛顿法的速度和最速下降法的稳定性。几乎所有实际的光束法平差实现(例如下文讨论的Ceres Solver、g2o、SBA等)都采用了LM算法或其密切相关的信赖域方法。

4. 为什么雅可比矩阵是稀疏的?

光束法平差的未知量包括相机位姿(6个自由度——3个旋转自由度加3个平移自由度,如果相机内参固定)×m个相机,以及3D点(3个自由度)×n个点,总维度可达6m+3n维。在实际的SfM问题中,如果观测次数达到数万甚至更多,简单地将J^\mathsf{T}J视为稠密矩阵,则计算成本将达到O((6m+3n)^3)——这在实际时间内是无法解决的。

关键在于重投影误差r_{ij}的结构,它“仅取决于相机i的参数和点j的参数”。对于任何其他相机k\neq i或点l\neq j的偏导数都恒等于零。

\frac{\partial r_{ij}}{\partial \mathbf{x}_{\text{camera }k}} = 0 \ (k\neq i), \qquad \frac{\partial r_{ij}}{\partial \mathbf{X}_l} = 0 \ (l\neq j)

换句话说,由单个观测生成的雅可比矩阵的行仅在对应相机的块和对应点的块中具有非零元素。行数与观测次数成正比增长,但每行非零元素的数量保持不变(相机 6 + 点 3,如果包含内部参数,则略多一些)。这种稀疏性在观察 J^\mathsf{T}J 时表现为以下块结构。

J^\mathsf{T}J = \begin{pmatrix} B & E \\ E^\mathsf{T} & C \end{pmatrix}
  • B:相机参数之间的交互作用。除非相机 i 和 k 观测到同一个点,否则该值为零,因此它具有稀疏块结构。

  • C:3D 点参数之间的交互作用。由于点 j 的 3 个自由度永远不会与其他任何点耦合,因此这是一个块对角矩阵——这是下一节中 Schur 补码技巧的前提。

  • E:摄像机与点之间的交互(每次观测都会出现一个非零块 (i,j))。

5. 基本流程

Diagram 1 · Use the button to switch views
捆绑调整通过重复生成重投影残差和稀疏雅可比矩阵、利用舒尔补求解以及应用 LM 步骤来联合细化相机位姿和 3D 点

Diagram 2 · Use the button to switch views
r_{ij} Sparse Jacobiancamera × pointblock structure Eliminate points viaSchur complement,reduced camera system Adjust \lambda viaLM method,update \Delta\mathbf{x} Checkconvergence

每次迭代都会重新计算重新投影误差,组装稀疏雅可比矩阵,通过舒尔补求解仅包含相机信息的简化系统,并通过LM的步长控制进行更新。此过程重复进行,直到成本变化低于阈值,或达到最大迭代次数。

6. 舒尔补技巧:将稀疏性转化为简化的计算

利用上一节中的块结构,我们可以将法方程(J^\mathsf{T}J+\lambda D)\Delta\mathbf{x}=-J^\mathsf{T}\mathbf{r}拆分为相机更新\Delta\mathbf{c}和点更新\Delta\mathbf{p},如下所示:

\begin{pmatrix} B' & E \\ E^\mathsf{T} & C' \end{pmatrix} \begin{pmatrix} \Delta\mathbf{c} \\ \Delta\mathbf{p} \end{pmatrix} = \begin{pmatrix} v \\ w \end{pmatrix}

(其中B', C'是添加阻尼项后的块)。由于 C' 是一个分块对角矩阵,每个 3D 点都是独立的,因此每个 3×3 块都可以单独求逆,其成本大致与点的数量 n 成正比。利用此 C'^{-1} 消除 \Delta\mathbf{p},即可得到仅包含以下相机的简化相机系统:

\left(B' - E C'^{-1}E^\mathsf{T}\right)\Delta\mathbf{c} = v - E C'^{-1}w

左侧的 B'-EC'^{-1}E^\mathsf{T} 称为舒尔补。该矩阵的大小为6m\times 6m(仅取决于相机数量,与点数n无关),一旦\Delta\mathbf{c}被求解,每个点的更新都可以通过以下方式快速恢复:

\Delta\mathbf{p} = C'^{-1}\left(w - E^\mathsf{T}\Delta\mathbf{c}\right)

在典型的SfM问题中,点数n可能是相机数量m的数十倍,因此,与其简单地求解一个具有6m+3n维的系统,不如只处理维度为6m的舒尔补。这正是即使在数万个点的规模下,捆绑调整也能实际求解的核心思想。理论上,该算法由 Triggs 等人在《捆绑调整——现代综合》(2000)一文中提出,并且是 Ceres Solver 和 g2o 等现有库的标准内部实现。

Ceres Solver 提供了多种求解该简化系统的选项:DENSE_SCHUR,它将其作为稠密矩阵求解(最多可处理几百个相机);SPARSE_SCHUR,它利用重排序来提高稀疏性(可处理数千个相机);以及 ITERATIVE_SCHUR,它将共轭梯度应用于 Schur 补(适用于更大规模的问题)。根据问题规模选择合适的选项是一个实用的经验法则。

7. 规整自由度:解并非唯一确定的方向

捆绑调整保留了一个自由度,允许在不改变代价函数值的情况下移动整个参数集。将所有相机和所有 3D 点同时进行相同的旋转、平移和缩放,重投影误差完全不变(对于仅使用单目的情况,绝对比例同样不确定)。这种自由度称为标度自由度。如果不加以处理,它会导致 J^\mathsf{T}J 奇异(秩亏),从而使正规方程无解或数值不稳定。

在实践中,可以通过固定前两个相机的位姿或一个基线长度来解决这个问题,或者利用 LM 自身的阻尼项 \lambda D 隐式地正则化这个奇异方向。当可以获得绝对比例或绝对位姿信息时——例如来自 GPS 或 IMU 的信息——很自然地会将其用作额外的约束来固定标度。

8. 与姿态图优化的区别

姿态图优化(在回环闭合入门中有所介绍)与捆绑调整属于同一数学框架,因为它们都使用鲁棒损失函数来最小化基于\mathrm{Log}映射构建的非线性最小二乘残差。区别在于未知量的具体内容。

姿态 捆绑调整 姿态图优化
未知量 每个相机的姿态 + 每个三维点的坐标 每个相机(节点)的姿态
残差 三维点重投影误差(图像空间) 与相对姿态观测值的差异(SE(3)空间)
稀疏性来源 哪个相机观测到了哪个点 哪些节点对之间存在约束
计算成本 点数多时成本高,可通过舒尔补码降低 本身成本较低,随节点(关键帧)数量增加而降低
主要用途 SfM 的最终优化,细化局部/全局地图 SLAM 中的全局漂移校正(回环检测后)

在实际的视觉 SLAM 系统中,通常会采用分工:局部光束法平差(局部 BA),包含 3D 点,逐帧地细化关键帧周围的区域;而轻量级的姿态图优化(不显式使用 3D 点)则在检测到回环时快速校正全局轨迹。包含 3D 点的完整光束法平差(全局 BA)精度更高,但计算成本也更高,因此在需要实时性能的场景中无法频繁运行。

9. 代表性实现

  • Ceres Solver:由谷歌开发的通用非线性最小二乘库,自 2010 年起投入生产使用。它内置了基于 Schur 补的求解器,并被用作许多 SfM/SLAM 实现(包括 COLMAP)的捆绑调整后端。

  • g2o:由 Kümmerle 等人在 2011 年 ICRA 会议上发表的图优化框架,能够在同一框架内处理 SLAM 的位姿图优化和捆绑调整。它已被广泛用作 ORB-SLAM 系列的后端。

  • SBA(稀疏捆绑调整):由 Lourakis 和 Argyros 于 2009 年在 ACM Transactions on Mathematical Software 上发表的早期公开可用的稀疏捆绑调整专用实现。它常被引用为显式实现 Schur 补技巧的代表性示例。

  • COLMAP 内置的 BA:内部使用 Ceres Solver,在增量 SfM 的每一步中自动切换局部和全局光束法平差。

10. 困难情况和常见失败案例

  • 初始值差:光束法平差是一种局部优化——如果初始值与真实解相差甚远,则可能收敛到错误的局部解,甚至根本无法收敛。从三角剖分或 PnP 获得的初始值的质量决定了最终精度。

  • 观测点少或视差小:仅从极少图像观测到的点,或视差很小的点,往往具有病态的雅可比矩阵,并可能留下较大的残差,且该残差主要集中在深度方向上。

  • 严重的异常值污染:混杂了大量不匹配点,即使使用鲁棒损失函数也无法完全吸收它们,正确的相邻点也可能被拖拽和扭曲。 超大规模问题:对于观测数量高达数百万的城市尺度重建,即使使用舒尔补集,计算和内存成本也不可忽略,因此需要将问题拆分并并行化,或结合近似技术(例如粗化LM的信赖域)。

  • 未处理的规范自由度:如上所述,忘记固定规范会导致数值不稳定,进而导致无法收敛或偏离物理实际解。

11. 实际选择

  • 如果您需要在SfM的最后阶段获得高密度精度,那么无论使用增量策略还是全局策略,在最后运行一次完整的光束法平差都是标准做法。遵循现有实现(例如COLMAP)的默认设置不太可能导致错误。

  • 对于实时SLAM,对每一帧都进行完整的光束法平差计算成本过高。一种实用的设计方案结合了仅基于最新关键帧的局部光束法平差,以及仅在闭环时触发的姿态图优化。

  • 如果您要从头开始构建自己的流程,那么基于 Ceres Solver 或 g2o 等库进行构建是合理的。从零开始编写 Schur 补的实现,相对于验证其正确性的成本而言,学习收益甚微。

  • 对于大规模、城市尺度的重建,与其依赖单一的光束法平差,不如考虑按区域划分问题并进行分层集成的方法(这通常也作为多视图立体视觉的预处理阶段,下文将对此进行讨论)。

12. 总结

光束法平差是一个非线性最小二乘问题,它同时最小化每个相机和每个 3D 点的重投影误差,并通过 Levenberg-Marquardt 方法迭代求解。舒尔补引理技巧利用了相机-点观测关系的稀疏性,使得即使在数万个点的规模下,该优化问题也能在合理的时间内解决。虽然它与姿态图优化共享数学框架,但二者之间的选择取决于是否显式地保存了3D点,而这正是支撑SfM和SLAM精度的共同基础技术。

检查你的理解
低重投影误差能否确定尺度?

仅凭单目重投影无法确定全局尺度。

区分修正量规和添加物理尺寸测量值。

参考文献

What to read next

Review the background运动结构重建入门——从无序照片集中同时恢复3D结构和相机位置Continue the series多视图立体建模入门——将稀疏点云填充为密集三维形状Explore another aspect of this field图像亮度 Lab — 曝光、伽马与裁剪