VGGT方法部分
VGGT到底在解决什么、输入输出是什么、网络怎么设计、为什么这么设计、训练怎么做、它的方法论意义是什么
一个大一统的多视图 3D transformer:输入一组同一场景的图片,直接输出每张图对应的相机、深度、3D 点图,以及可用于点跟踪的特征。
尽量少写死 3D 几何结构,用一个大 transformer + 多任务 3D 监督,让模型自己学会多视图几何。
1. 到底在做什么
问题定义:输入是同一 3D 场景的 (N) 张 RGB 图像:\((I_i)_{i=1}^N\)
模型 (f) 输出每一帧对应的一组 3D 量:\(f((I_i)_{i=1}^N) = (g_i, D_i, P_i, T_i)_{i=1}^N\)
每个符号分别表示:
- \(g_i\):第 (i) 张图的相机参数
- \(D_i\):深度图
- \(P_i\):point map
- \(T_i\):用于点跟踪的 dense feature map
也就是说,它不是只做一个任务,而是一次性做四件事:
- 相机估计
- 深度估计
- 3D 点恢复
- 点跟踪特征提取
第一个核心点:统一建模。
2. 它输出的每个量到底是什么意思
2.1 相机参数 \(g_i\)
论文里用:
\(g=[q,t,f]\)
其中:
- \(q \in \mathbb{R}^4\):旋转四元数
- \(t \in \mathbb{R}^3\):平移
- \(f \in \mathbb{R}^2\):视场或等价焦距参数
也就是说,VGGT 直接预测每张图的: - 外参:旋转 + 平移
- 内参:至少焦距类参数
并且假设 principal point 在图像中心。
2.2 深度图 \(D_i\)
这个比较标准:
\(D_i(y) \in \mathbb{R}^+\)
表示图像中像素 \(y\) 的深度值。
注意这里的深度是:
从第 (i) 个相机视角看到的深度
所以它是 view-dependent 的。
2.3 Point map \(P_i\)
这个你前面已经问过了。
point map 里每个像素都对应一个 3D 点:
\(P_i(y) \in \mathbb{R}^3\)
但这里很关键的一点是:VGGT 的 point map 是 viewpoint invariant 的。
这些 3D 点不是定义在“当前相机自己的坐标系里”,而是定义在第一帧相机 \(g_1\) 的坐标系里
也就是:
- 第一张图的相机坐标系被拿来当作 世界参考系
- 所有帧的 point map 都在这个统一坐标系里表达
VGGT 这里明确规定:point map 的原点在第一帧相机坐标系中。
2.4 跟踪特征 \(T_i\)
这里它不是直接输出轨迹本身,而是输出:
\(T_i \in \mathbb{R}^{C \times H \times W}\)
也就是一个 dense feature map,后面交给单独的 tracking module 去做任意点跟踪。
也就是说,VGGT 主干网络输出的是:
- 给 tracking 用的表征
- 而不是最终的点轨迹坐标
3. 为什么第一帧这么重要
VGGT 明确规定:
- 输入图片顺序基本可以任意
- 但第一张图被选为参考帧
- 整个 3D 预测都在第一帧坐标系中表达
这带来两个效果:
1. 解决坐标系歧义
3D 重建本身存在 gauge freedom:
- 整体平移不变
- 整体旋转不变
- 尺度也可能不确定
所以必须选一个规范。
VGGT 就选:
第一帧相机作为 reference frame
2. 给模型一个统一输出空间
这样相机、point map、depth 都能放在同一个坐标约定下预测。
但你也能看到,这其实也引入了一点 inductive bias:
第一帧被特殊对待
所以严格说,VGGT 并不是完全没有 bias,而是 除第一帧参考系之外,尽量少加 3D-specific bias。
4. 网络主干怎么做的
这部分是方法最核心的地方。
4.1 先用 DINO 把图像变成 patch tokens
每张图像\(I\)先被 patchify,再通过 DINO 提取成\(K\)个 token:
\(t^I \in \mathbb{R}^{K \times C}\)
也就是说,每张图被编码成一串 patch features。
这里 DINO 起的作用就是:
提供一个比较强的视觉 patch 表征起点
4.2 把所有帧的 tokens 放在一起
所有帧的图像 tokens 合起来,形成整个输入序列。
然后送进主干 transformer。
但这里还没完,它做了一个额外设计。
4.3 每一帧加一个 camera token 和四个 register tokens
对每张输入图\(I_i\),除了图像 patch tokens,还额外加:
- 一个 camera token \(t_i^g\)
- 四个 register tokens \(t_i^R\)
所以每帧的输入变成:
\((t_i^I, t_i^g, t_i^R)\)
camera token 的作用
专门用来聚合与相机有关的信息,最后用于预测相机参数。
register tokens 的作用
它们像额外的可学习缓冲槽,帮助网络存储和交换一些中间全局信息。
这是 transformer 里越来越常见的技巧:给模型一些专门的“工作内存 token”。
4.4 第一帧的 camera/register token 是单独学习的
论文特别写了:
- 第一帧的 camera token / register token
- 和其他帧不共享
- 用一套单独的可学习 token 初始化
这件事的意义是:
让模型显式知道“谁是第一帧”
因为第一帧是参考系。
所以模型需要能区分:
- 第一帧
- 其他帧
这也是它把 reference frame 机制写进架构的方法。
5. Alternating-Attention 是什么
这是 VGGT 结构里最有辨识度的地方。
它没有直接用一种统一的 self-attention,而是交替使用两种 attention:
- frame-wise self-attention
- global self-attention
并且一共用了 (L=24) 层这种交替结构。
5.1 Frame-wise self-attention
这一步里:
每一帧内部的 token 自己互相 attention
- 同一张图里的 patch token、camera token、register token 互相交流
- 不同帧之间不直接交流
作用是:
1. 学单帧内部结构
比如:
- 纹理
- 局部几何
- 图像整体布局
2. 让 camera token 绑定当前帧内容
因为 frame-wise attention 只看本帧,所以 camera token 能变成“这张图自己的 summarization”。
这也是为什么后面它能拿来预测相机。
5.2 Global self-attention
这一步里:
所有帧的 token 一起做 attention
也就是跨帧全局交互。
作用是:
1. 聚合多视图信息
不同视角的对应区域可以互相通信。
2. 学多视图几何关系
谁和谁是同一物体、同一结构、不同视角下怎么对应,都在这里学。
5.3 为什么要交替,而不是只用 global
论文自己说,这样做是在平衡两件事:
- 跨图像的信息整合
- 每张图内部 token 激活的稳定/归一化
更直白地说:
如果你全程只做 global attention,会有两个问题:
1. 容易太混
所有帧 token 全部一锅炖,单帧内部结构不容易稳定保存。
2. 每帧 identity 变弱
token 容易过快变成“跨帧平均表示”,而不是既有自身视角特征,又吸收多视图信息。
而交替结构相当于:
- 先在每张图里整理本地信息
- 再跨帧交换信息
- 再回到每张图内部精炼
- 再跨帧聚合
这就像“局部处理”和“全局对齐”反复交替。
这是一个轻量但有效的 inductive bias。
不是显式 3D 几何模块,但确实是一种专门适合多图建模的结构设计。
6. 预测头怎么做
主干 transformer 输出后,分成两类预测:
- camera prediction
- dense prediction
6.1 Camera head
相机参数 \(\hat g_i\) 是从输出的 camera tokens \(\hat t_i^g\)预测的。
具体做法是:
- 先再过 4 层 self-attention
- 再接一个线性层
- 输出相机参数
这里的直觉是:
每一帧的 camera token 已经在主干中吸收了本帧和多帧信息
所以拿它来回归 pose/intrinsics 是自然的
6.2 Dense head:DPT
输出的 image tokens \(\hat t_i^I\) 经过 DPT head 转成 dense feature map:
\(F_i \in \mathbb{R}^{C'' \times H \times W}\)
然后进一步映射到:
- depth map\(D_i\)
- point map\(P_i\)
- tracking feature\(T_i\)
这里 DPT 的作用就是:
把 patch token 重新还原成逐像素的 dense prediction
这是 ViT/transformer 做 dense task 时很常见的一步。
6.3 还预测了 uncertainty
对于 depth 和 point map,VGGT 还会预测:
- \(\Sigma_i^D\)
- \(\Sigma_i^P\)
这是 aleatoric uncertainty,表示模型对这个位置预测的不确定程度。
训练时用途
用来加权 loss,让模型学会“哪些地方我不确定”。
推理时用途
可作为置信度指标。
这其实很有用,因为:
- 反光区
- 无纹理区
- 遮挡边界
- 视图不一致区域
本来就更难预测,uncertainty 能让训练更稳。
7. 跟踪模块怎么接上
VGGT 里的 point tracking 不是主干直接做完的,而是:
- 主干先输出 dense tracking features \(T_i\)
- 再交给一个单独 tracking module \(\mathcal T\)
这里他们用的是 CoTracker2 风格的架构。
过程是:
- 给 query 图像中的一个点 \(y_q\)
- 从 query 图像的特征图 \(T_q\) 上双线性采样出这个点的特征
- 把这个特征和其他图像的特征图 \(T_i\) 做相关性计算
- 再通过 self-attention 预测在其他帧里的对应 2D 点
重要的是:
它不依赖视频的时间顺序
所以不是只能做连续视频跟踪,而是:
一组无序图像也能做“任意点跨图对应”
这和它前面整体的 set-of-images 设定是一致的。
8. 一个非常有意思的点:Over-complete Predictions
论文专门强调了一点:
VGGT 预测的量不是彼此独立的。
例如:
1 相机可以从 point map 推出来
如果 point map 已经在统一世界系下了,那么可以通过 PnP 求相机。
2 depth 可以由 point map + 相机得到
point map 给了 3D 点,已知相机就能投影出深度。
也就是说,从数学关系上看,它有点“重复预测”了。
那为什么还要全部预测?
论文回答是:
虽然这些量之间存在闭式关系,但训练时显式监督所有这些量,性能反而更好。
这很重要。
说明它不是在追求最小参数化,而是在追求:
多任务联合约束
也就是:
- camera supervision 约束全局几何
- depth supervision 约束视角相关局部几何
- point map supervision 约束统一三维结构
- tracking supervision 约束跨图对应
这些任务之间相互补强。
这也是现代大模型里很常见的一种思想:
即使某些输出冗余,它们也可以作为更强 supervision signal。
9. 它的 loss 是怎么设计的
总损失是:\(\mathcal L = \mathcal L_{camera} + \mathcal L_{depth} + \mathcal L_{pmap} + \lambda \mathcal L_{track}\),其中\(\lambda = 0.05\)
9.1 Camera loss
\(\mathcal L_{camera} = \sum_{i=1}^N |\hat g_i - g_i|\)
用 Huber loss 比较预测相机和真值相机。
9.2 Depth loss
用带 uncertainty 的损失,并且额外加了梯度项:
- 一项约束深度值本身
- 一项约束深度梯度
梯度项的意义是:
不只是数值接近,还要边界和局部结构对
这对 depth 很关键,因为平滑但模糊的深度图也可能数值上凑合,但几何边界会很差。
9.3 Point map loss
和 depth loss 类似,也是:
- 值误差
- 梯度误差
- uncertainty weighting
这保证 point map 不只是全局方向对,局部几何也要细。
9.4 Tracking loss
对 ground truth query points 的跨图对应点做监督。
另外还有 visibility loss,估计该点在某帧是否可见。
这很重要,因为很多点在跨视图时会:
- 被遮挡
- 移出视野
不能强行让每一帧都必须匹配。
10. 它如何处理坐标系和尺度歧义
论文有一节叫 Ground Truth Coordinate Normalization,这是很关键的。
因为真实 3D 重建里有天然歧义:
- 全局原点在哪里
- 整体朝向如何
- 场景尺度是多少
这些变化并不影响图像。
所以他们先对训练真值做规范化:
第一步
把所有量表达在第一帧相机坐标系中。
第二步
计算所有 3D 点到原点距离的平均值,把它作为归一化尺度。
然后用这个尺度去归一化:
- 相机平移
- point map
- depth
也就是说,训练目标被 canonicalize 了。
但论文特别强调一点:
他们没有像某些方法那样在网络输出后再做这种归一化,
而是直接让 transformer 自己学会输出这种规范化后的量。
这是一个更强的要求,也更符合 end-to-end 的味道。
11. 训练规模有多大
VGGT 训练规格非常大:
- 24 层 alternating attention
- 约 1.2B 参数
- 160K iterations
- 64 张 A100
- 训练 9 天
- 输入每个 batch 随机采样 2 到 24 帧
- 图像最大边 518 px
训练数据非常杂而广:
- 室内
- 室外
- 合成
- 真实
- SfM 构建的
- 传感器采集的
- 引擎生成的
包括 Co3Dv2、BlendMVS、DL3DV、MegaDepth、Scannet、HyperSim、Replica 等一大堆。
这其实就是它“弱 3D inductive bias”路线成立的前提:
因为减少了手工几何结构,就必须用更大的模型和更多的数据来补。
12. 最重要的思想到
可以总结成四句话。
1 不是单任务 3D 网络,而是统一 3D 表征模型
它同时预测:
- camera
- depth
- point map
- tracking features
这意味着它学到的不是某一个 narrow task,而是更接近“通用 3D understanding”。
2 尽量不把几何写死在结构里
没有显式:
- cost volume
- epipolar layer
- triangulation module
- BA-style block
而是靠 transformer 在多任务监督下自己学。
3 仍然有非常克制的结构偏置
它不是完全无 bias,而是只保留少数很必要的偏置:
- 第一帧作参考系
- frame-wise / global attention 交替
- camera token / register token
- dense prediction 用 DPT
也就是说它不是“纯黑盒”,而是“只加少量通用偏置”。
4 方法论是 foundation-model 式的
它的真正主张不是“我发明了某个几何模块”,而是:
对于 3D 重建,可能不需要越来越特化的网络设计;一个大规模通用 transformer,在足够多 3D 数据上训练,也可以学出强几何能力。
这就是它说 “it is unnecessary to design a special network for 3D reconstruction” 的底气来源。
13. 可以怎么理解 VGGT 和传统 MVS / DUSt3R / MASt3R 的关系
相比传统 MVS
MVS:
- 强几何先验
- 显式 cost volume
- 已知相机时很强
VGGT: - 更少显式几何模块
- 更强数据驱动
- 更统一多任务
- 更接近 feed-forward foundation model
相比 DUSt3R / MASt3R
DUSt3R / MASt3R 更强调:
- pairwise 或局部几何关系
- point map / matching 为核心
VGGT 更进一步做的是: - 统一多图输入
- 直接输出 camera + depth + point + tracking
- 更像“多视图 3D 通用 backbone”
14. 一句话总结构图 + 方法
VGGT 的方法本质上是:把多张图编码成 patch tokens,为每帧加入相机 token,在交替的单帧与全局 self-attention 中学习多视图关系,然后通过不同 prediction heads 统一输出相机、深度、point map 和跟踪特征,并用多任务 3D 监督端到端训练。

浙公网安备 33010602011771号