DUSt3R:让几何 3D 视觉变简单
论文:DUSt3R: Geometric 3D Vision Made Easy
作者:Shuzhe Wang, Vincent Leroy, Yohann Cabon, Boris Chidlovskii, Jerome Revaud
arXiv:2312.14132v3
本地文件:/root/other/paper/2312.14132v3.pdf
官方页面:arXiv 2312.14132
项目页面:DUSt3R
这篇论文解决什么问题
传统多视角重建通常需要先求一堆中间量:
图像匹配
-> essential / fundamental matrix
-> camera intrinsics / extrinsics
-> SfM sparse reconstruction
-> MVS dense reconstruction
-> fusion
这个流程很强,但工程链条长,而且每一步都会把误差传给下一步。尤其是在野外图片集合里,经常没有相机内参、没有外参,也不一定有稳定的视角覆盖。
DUSt3R 的目标是反过来做:
不先显式估计相机参数,而是直接从图像对回归 dense pointmap。
也就是说,给两张图像:
网络直接输出两个 dense 3D pointmap:
它们分别对应图像 1 和图像 2 的每个像素,但关键是二者都表达在图像 1 的坐标系中。
图源说明:根据 Wang et al., DUSt3R 的网络结构描述重绘,非论文原图。
一句话版本
DUSt3R 把多视角几何问题改写成一个 pointmap regression 问题:
two RGB images
-> transformer with cross-attention
-> two aligned pointmaps + confidence maps
-> depth / matching / camera pose / 3D reconstruction
它最不寻常的地方是:输出不是传统的 depth map + camera pose,而是直接输出像素对齐的 3D 点。
Pointmap 是什么
论文把 dense 2D field of 3D points 称为 pointmap:
对于每个像素:
都有一个三维点:
所以 pointmap 建立了:
也就是:
一个像素 <-> 一个 3D 场景点
如果已知相机内参 和 depth map ,普通几何里可以由反投影得到 pointmap:
这和前面 point-map 实验路线中的:
pixel -> camera ray -> depth -> camera-space 3D point
是同一件事。
DUSt3R 的区别是:它不要求你先给定 、pose 或 depth,而是让网络直接预测 pointmap。
⭐ 为什么 pointmap 比单纯 depth map 更适合 DUSt3R?
Depth map 只告诉你每个像素沿相机射线有多远。要把 depth 变成 3D 点,还需要相机内参:
以及不同相机之间的外参:
但 DUSt3R 面对的是 unconstrained image collection:可能没有内参,也没有外参。
如果直接预测 pointmap:
网络输出本身就已经是 3D 几何。它不必先显式经过:
depth + K + pose -> 3D
这让 DUSt3R 可以绕开传统 pipeline 中最脆弱的相机参数估计环节。
代价是:预测出来的 pointmap 不一定严格满足某个真实针孔相机模型。论文也明确指出,这种 generic architecture 在推理时没有显式强加几何约束,而是依靠训练数据学到几何一致性。
模型架构:输入与输出
DUSt3R 的核心网络记为:
输入两张 RGB 图像:
输出:
其中:
- :图像 1 每个像素对应的 3D 点,表达在图像 1 坐标系。
- :图像 2 每个像素对应的 3D 点,也表达在图像 1 坐标系。
- :对应 confidence map。
图源说明:根据 Wang et al., DUSt3R 的 pointmap 表达方式重绘,非论文原图。
网络流程
DUSt3R 使用 CroCo 风格的 Transformer 架构:
I1, I2
-> shared ViT encoder
-> two token features F1, F2
-> transformer decoders with cross-attention
-> regression heads
-> pointmaps + confidence maps
编码阶段:
解码阶段不断做信息交换。每个 decoder block 不只是看自己这张图的 tokens,也通过 cross-attention 看另一张图的 tokens:
最后 regression head 输出:
为什么两个 pointmap 都放在图像 1 坐标系
这是 DUSt3R 的关键设计。
如果按照常规方式,图像 1 预测:
图像 2 预测:
那么两个 pointmap 分别在各自相机坐标系中。要比较二者,必须先知道相机 1 到相机 2 的相对位姿:
但 DUSt3R 正是想在没有相机参数的情况下工作。
所以它直接让网络输出:
即:图像 2 的点也被表达在图像 1 坐标系中。
这样就可以直接在 3D 空间比较:
它把一部分“相机位姿估计 + 三角化”的工作隐式塞进了 pointmap regression 里。
训练目标
DUSt3R 使用 fully-supervised 的 3D regression loss。设 ground-truth pointmap 为:
对 view 的有效像素 ,基础回归误差是:
这里 和 是尺度归一化项,用来处理预测和真值之间的尺度歧义。论文定义:
也就是所有有效 3D 点到原点距离的平均值。
Confidence-aware loss
真实图像里有些区域很难定义可靠 3D 点,例如:
- sky
- translucent surface
- reflective surface
- textureless area
- 单视角可见但另一视角不可见的位置
因此 DUSt3R 同时预测 confidence:
最终 loss 为:
其中 越大,表示网络越相信这个像素的 3D 预测。
⭐ 为什么 loss 里有 - α log C?
如果只有:
模型可能把所有 confidence 都预测得很小,让损失也变小。
加入:
以后,当 太小时, 会变大,模型会受到惩罚。
所以这个 loss 同时鼓励两件事:
难的点:可以给低一点 confidence,避免错误监督过强。
容易的点:不能随便把 confidence 压低,否则 -log C 会惩罚。
直觉上,confidence 不是让模型逃避预测,而是让它区分“我有把握”和“这里确实不稳定”。
输出可以用来干什么
DUSt3R 的输出不只是 3D 点云。由于 pointmap 同时保留了像素索引和 3D 坐标,它可以顺手导出很多传统几何任务需要的中间量。
| 输出 | 可以做什么 | 说明 |
|---|---|---|
| 3D reconstruction | 每个像素直接对应一个 3D 点 | |
| confidence maps | 过滤低质量区域 | 降低 sky、遮挡、反光区域影响 |
| pointmap nearest neighbor | pixel matching | 在 3D pointmap 空间做互为最近邻 |
| recover intrinsics | 因为它在图像 1 坐标系,可拟合 focal | |
| relative pose | 可用 Procrustes / RANSAC + PnP | |
| 多图 pairwise pointmaps | global 3D model | 通过 global alignment 融合成一致场景 |
下游任务一:像素匹配
因为 pointmap 和像素一一对应,匹配可以转成 3D 最近邻搜索。
给两个 pointmap:
可以在 3D 空间寻找 nearest neighbor。论文使用 mutual / reciprocal matching:
i 是 j 的最近邻,并且 j 也是 i 的最近邻
这样可以减少单向最近邻带来的错误匹配。
下游任务二:恢复相机内参
由于 表达在图像 1 坐标系中,可以反过来拟合 focal length。
在主点近似位于图像中心、像素为正方形的假设下,只需要估计一个 focal:
其中:
这其实是在利用针孔相机投影关系:
从预测出来的 3D 点反推出最合理的 focal。
⭐ 这里和我们前面的 point-map 实验有什么关系?
前面的实验通常是:
已知 K + depth
-> 反投影
-> point map
而 DUSt3R 这里更像反过来:
网络已经预测 point map
-> 利用 point map 和像素坐标
-> 估计 K 里的 focal
也就是说,普通几何里 是输入;DUSt3R 中, 可以从输出的 pointmap 里再恢复出来。
下游任务三:相对位姿
DUSt3R 可以通过多种方式估计 relative pose。
一种方式是:
pointmap -> 2D matching
pointmap -> intrinsics
matching + intrinsics -> essential matrix
essential matrix -> relative pose
另一种更直接的方式是用 Procrustes alignment,对两个 3D pointmap 做相似变换配准:
这里 是尺度, 是旋转, 是平移。
论文也指出 Procrustes 对噪声和 outlier 敏感,因此更鲁棒的方案仍然可以用 RANSAC + PnP。
多视角:Global Alignment
前面说的是图像对。对于多张图像,DUSt3R 先构建一个图:
其中:
- 每张图像是一个 vertex。
- 每个有重叠的图像对是一条 edge。
- 每条 edge 上都有 DUSt3R 对该图像对预测出的 pairwise pointmaps。
然后通过 global alignment,把所有 pairwise pointmaps 放进同一个全局 3D 空间。
图源说明:根据 Wang et al., DUSt3R 的 global alignment 思路重绘,非论文原图。
传统 bundle adjustment 通常最小化的是 reprojection error:
3D point -> project to image -> compare 2D pixel error
DUSt3R 的 global alignment 更直接地在 3D 空间中对齐 pointmaps:
pairwise pointmaps
-> optimize poses / scales / point clouds
-> one consistent global 3D reconstruction
⭐ Global Alignment 公式是在什么架构里优化的?
⭐ 它不是另一个 Transformer,而是场景级可微图优化
容易误解的一点是:下面这个公式不是放进另一个 Transformer、GNN,或者“带全局记忆的神经网络”里优化的。
DUSt3R 的网络 只负责逐图像对预测 pointmap 和置信度。随后系统把当前场景中所有图像对的预测收集起来,建立一个普通的可微优化问题,在 GPU 上用梯度下降联合求解。论文中也说明,全局优化使用标准梯度下降,通常几百步收敛。
1. 整体结构分成两阶段
阶段一是神经网络逐对推理。
对于连接图中的每条边:
将两张图输入同一个 DUSt3R 网络:
得到 pairwise pointmaps:
以及置信度:
每条边的预测彼此独立。例如:
edge e12 = (1, 2) -> X^{1,e12}, X^{2,e12}
edge e23 = (2, 3) -> X^{2,e23}, X^{3,e23}
edge e13 = (1, 3) -> X^{1,e13}, X^{3,e13}
此时不同边仍处于各自的局部坐标系中。
阶段二是场景级数值优化。
网络推理结束后,把当前场景的全部 pairwise pointmaps 放进同一个损失:
然后联合优化:
- 每张图的全局 pointmap:
- 每条边的局部到全局变换:
- 每条边的尺度:
所以这里的“架构”更接近:
图优化 / 因子图 / 场景级可微优化
而不是一个负责读取整套图像的神经网络。
2. 为什么一条边能够和“全局”发生关系?
关键不是模型提前知道全局,而是:一条边和其他边共享同一个全局变量。
考虑三张图:
连接图只有两条边:
损失中会出现:
以及:
注意,图像 2 在两条边中共享同一个变量:
因此优化必须同时满足:
以及:
于是自然得到:
这就把边 和边 连接起来了。
3. 全局不是预先存在的,而是优化出来的
不要把 理解成“系统已经知道的世界点云”。
在优化开始之前:
都是待求变量。它们并不是数据库中的真实世界模型,也不是网络记忆中的场景。
优化过程在同时寻找:
- 每张图像最合理的全局 pointmap。
- 每条边到这个公共空间的变换。
- 每条边的相对尺度。
可以把它理解为:
没有预先给定的全局点云
-> 所有局部预测互相施加约束
-> 共同找到一组最一致的 χ、P、σ
-> 这组结果就被定义为全局重建
世界坐标原点和整体朝向通常存在规范自由度:如果把所有结果一起旋转和平移,损失可能不变。因此实际实现需要固定某个参考系或施加规范约束。论文在尺度上使用:
来避免所有尺度收缩到 0 的退化解。
4. 梯度下降如何传递“全局关系”
设边 对图像 2 的误差为:
边 对图像 2 的误差为:
总损失中:
因此对共享变量 的梯度是:
也就是说, 的更新同时受到所有包含图像 2 的边影响。
接着, 的变化又会改变:
- 边 的最优
- 边 的最优
于是信息沿图传播:
edge (1, 2)
-> shared χ²
-> edge (2, 3)
-> shared χ³
-> edge (3, 4)
这可以看成一种由联合优化产生的隐式消息传递,但它并不是一个训练好的 GNN。
5. 它是否需要“留存所有图片集的记忆”?
需要区分两种“记忆”。
当前场景的临时内存是需要的。在执行全局对齐时,程序通常需要持有当前场景中的:
- 图像连接图
- 每条边的 pointmap
- 每条边的置信度
- 优化变量
因此,对于当前这一组图片,它确实需要保存足够的数据来联合计算损失和梯度。但这是普通的运行时内存,例如 GPU 显存或 CPU 内存。
跨场景的永久记忆不需要。完成场景 A 的全局对齐后,处理场景 B 时,不需要记住场景 A 的所有图片和 pointmaps。
网络参数中包含的是训练数据学到的通用几何先验,但不包含当前场景的具体“全局地图”。当前场景的全局结构是在推理后临时优化出来的。
因此不是:
网络记住了所有图像
-> 查询记忆
-> 知道全局是什么
而是:
网络逐对产生局部几何
-> 当前场景的全部局部几何进入联合损失
-> 优化器现场构造全局一致解
6. 为什么不用一次把所有图片输入 Transformer?
理论上可以设计一个多图像 Transformer,让所有图片共同注意。但 DUSt3R 采用了另一种更灵活的设计:
- 网络只需处理两张图。
- 图像数量 可以变化。
- 用连接图控制需要处理哪些图像对。
- 后处理优化负责把任意数量的 pairwise 结果融合起来。
这样不要求 Transformer 的输入长度随图片数无限增长,也更容易处理几十张甚至更多图像。
代价是:必须保留和优化当前场景的 pairwise 预测。图像和边很多时,内存与计算量会增加。
和传统 SfM / MVS 的差异
| 传统 SfM + MVS | DUSt3R |
|---|---|
| 先做特征匹配 | 直接输入图像对 |
| 需要估计或已知相机参数 | 不要求预先知道内参和外参 |
| 依赖 epipolar geometry、triangulation、BA | 用 pointmap regression 统一表达 |
| 输出通常是 camera + sparse / dense points | 输出 pointmaps + confidence |
| 多视角融合依赖传统几何 pipeline | 使用 pointmap global alignment |
更直接地说:传统方法先恢复“相机怎么拍”,再恢复“世界长什么样”;DUSt3R 则先让网络预测“每个像素看到的 3D 点在哪里”,然后再从这些 3D 结果中恢复相机、匹配和全局结构。
和 DeepSDF / ConvONet / NeuS 的关系
| 方法 | 输入 | 3D 表示 | 主要监督 | 输出用途 |
|---|---|---|---|---|
| DeepSDF | SDF samples + latent code | continuous SDF | SDF regression | shape reconstruction |
| ConvONet | point cloud / voxel + query point | occupancy field | occupancy labels | object / scene surface |
| NeuS | posed images + camera rays | neural SDF + color | image rendering loss | multi-view surface reconstruction |
| DUSt3R | unposed image pair | dense pointmaps | supervised 3D point regression | depth、pose、matching、3D reconstruction |
DUSt3R 和前几篇隐式重建论文的差异很明显:它不是学习一个可以任意查询的连续隐式场,而是学习一个 pixel-aligned 的 dense 3D point field。
它更贴近你现在正在整理的 point-map / depth / camera geometry 路线。
训练数据与监督信号
DUSt3R 是 supervised 方法。训练时需要 ground-truth pointmaps:
这些真值可以来自:
- 合成数据。
- SfM / MVS 重建结果。
- RGB-D 或专用传感器采集的数据。
因此它的“无需相机参数”主要是指推理阶段输入图像时不需要提前给相机内外参;训练阶段仍然依赖大量具有几何监督的数据。
⭐ DUSt3R 是不是完全不需要几何?
不是。
DUSt3R 不是抛弃几何,而是把很多显式几何步骤改成了网络学习和 pointmap 回归。
传统 pipeline 在推理时显式执行:
matching -> epipolar geometry -> triangulation -> BA -> MVS
DUSt3R 在训练时从大量几何真值中学习这些规律,推理时直接输出 aligned pointmaps。
所以更准确的说法是:
DUSt3R 减少了推理阶段对显式相机几何 pipeline 的依赖,
但它仍然利用几何监督来学习 3D 结构。
优点
- 输入限制少:可以处理未知相机内参、未知外参的图像集合。
- 输出信息密度高:pointmap 同时包含像素对应关系和 3D 几何。
- 统一多个任务:depth、matching、relative pose、absolute pose、3D reconstruction 都能从 pointmap 派生出来。
- 架构通用:使用 Transformer encoder-decoder 和 cross-attention,而不是手工设计复杂几何模块。
- 对 monocular 和 binocular 情况统一:单图和双图都可以落到 pointmap 表达上。
局限
- 依赖监督数据:训练需要 ground-truth 3D pointmaps。
- 几何一致性不是硬约束:输出 pointmap 不一定严格对应真实针孔相机模型。
- scale 可能有歧义:训练 loss 中需要尺度归一化,多视角融合也要处理尺度。
- 复杂材质和开放空间仍困难:sky、反光、透明物体等区域需要 confidence 来降低影响。
- 多视角仍需后处理:对于多张图像,仍需要 global alignment 把 pairwise 结果合并。
对我理解 point-map 的启发
这篇论文和前面的 ray-depth-pointmap 实验可以放在一起理解。
传统几何路线是:
K, pose, depth
-> point map
-> multi-view fusion
DUSt3R 的路线是:
image pair
-> network predicts aligned pointmaps
-> recover K / pose / matching / 3D
也就是说,pointmap 在这里变成了核心中间表示。它既不像 depth map 那样强依赖相机参数,也不像隐式场那样需要对任意 3D 点查询;它直接把图像像素和 3D 点绑定起来。
对后续学习来说,最值得盯住三个问题:
- 为什么能表达在图像 1 坐标系?
- confidence map 如何影响后续 matching 和 alignment?
- global alignment 如何从 pairwise pointmaps 变成全局一致重建?
速记
DUSt3R 的核心可以记成:
DUSt3R = Transformer image pair -> aligned pointmaps -> everything geometric
其中最关键的输出是:
它们把两张图像看到的 3D 点放在同一个坐标系里,因此可以直接支持:
- 3D reconstruction
- depth estimation
- pixel matching
- relative pose
- visual localization
- multi-view global alignment