
"One image, full 3D world." —— 从一张普通照片,恢复可度量的三维空间
📌三句话读懂本文
1️⃣ Metric3Dv2 是一个单目几何基础模型,能从一张 RGB 图像同时预测 metric 尺度的深度图 + 表面法向图,在 10+ 个权威 benchmark 上达到零样本 SOTA。
2️⃣ 其核心创新在于 Label Scale Canonical Transformation(将不同焦距的数据映射到统一规范空间)+ DPT 多尺度解码 + RAFT 迭代优化 的深度融合架构。
3️⃣ 支持 ConvNeXt / ViT-DINO 双 Backbone、SSF / LoRA 高效微调、ONNX 导出,已落地于自动驾驶、机器人导航、AR/VR、3D 重建等多个领域。
一、🌍 背景:为什么单目几何估计需要"基础模型"?
深度估计是计算机视觉最古老的问题之一,但长期以来面临一个根本性困境:
| 时代 | 代表方法 | 核心痛点 |
|---|---|---|
| 传统 MDE | MiDaS / AdaBins | 只能输出相对深度,没有物理尺度 |
| 仿射不变 | LeReS / Metric3Dv1 | 形状正确,但尺度/位移模糊 |
| 基础模型时代 | Depth Anything / Marigold | 泛化强,但仍缺 metric 尺度 |
| ✅ 几何基础模型 | Metric3Dv2 | 一张图 → 可度量 3D + 表面法向 |
1.1 问题的本质:尺度歧义
单目深度估计的根本难点在于:同一张 2D 图像,可以对应无数种 3D 场景——近处的小物体和远处的大物体,在图像上可能完全一样。
Metric3Dv2 的解法是:
不在像素空间里"猜"深度,而是在一个精心设计的规范空间(Canonical Space)里学几何,再映射回物理世界。
1.2 为什么还要预测表面法向?
深度图告诉你"每个点离相机多远",但法向图告诉你"每个表面朝哪个方向"。两者结合,才能完整描述 3D 几何:
- 🧱 深度 → 场景的"骨架"
- 🪞 法向 → 表面的"皮肤"
这在光照估计、物理仿真、3D 重建等下游任务中至关重要。
二、🏗️ 核心技术解析(代码级 🔍)

2.1 整体架构:DensePredModel
整个模型由 Encoder + Decoder 两大部分组成,代码极其简洁:
# dense_pipeline.py
class DensePredModel(nn.Module):
def __init__(self, cfg) -> None:
super(DensePredModel, self).__init__()
# Encoder:ConvNeXt 或 ViT-DINO
self.encoder = get_func('mono.model.' + cfg.model.backbone.type)(**cfg.model.backbone)
# Decoder:RAFT + DPT 融合解码器
self.decoder = get_func('mono.model.' + cfg.model.decode_head.type)(cfg)
def forward(self, input, **kwargs):
features = self.encoder(input) # [f_32, f_16, f_8, f_4]
out = self.decoder(features, **kwargs)
return out
✅ 设计哲学:
- Encoder 负责"看懂图像"——提取多尺度语义与结构特征
- Decoder 负责"恢复几何"——将特征逐步解码为深度与法向
2.2 Backbone 双选择:ConvNeXt vs ViT-DINO
Metric3Dv2 支持两种 backbone,用户可按需选择:
🔹 ConvNeXt:CNN 的现代化复兴
# ConvNeXt.py
class Block(nn.Module):
def __init__(self, dim, drop_path=0., layer_scale_init_value=1e-6):
super().__init__()
self.dwconv = nn.Conv2d(dim, dim, kernel_size=7, padding=3, groups=dim) # 深度可分离卷积
self.norm = LayerNorm(dim, eps=1e-6) # 前置归一化
self.pwconv1 = nn.Linear(dim, 4 * dim) # 逐点卷积(用 Linear 实现)
self.act = nn.GELU()
self.pwconv2 = nn.Linear(4 * dim, dim)
self.gamma = nn.Parameter(layer_scale_init_value * torch.ones(dim)) # Layer Scale
self.drop_path = DropPath(drop_path)
def forward(self, x):
input = x
x = self.dwconv(x)
x = x.permute(0, 2, 3, 1) # (N,C,H,W) → (N,H,W,C) 用 Linear 做逐点卷积
x = self.norm(x)
x = self.pwconv1(x)
x = self.act(x)
x = self.pwconv2(x)
x = x.permute(0, 3, 1, 2) # 回到 (N,C,H,W)
return input + self.drop_path(self.gamma * x)
ConvNeXt 的设计精髓:
- 🔧 7×7 深度可分离卷积:扩大感受野,捕获大范围上下文
- 📐 前置 LayerNorm:训练更稳定
- 🎚️ Layer Scale(γ 参数):逐通道缩放残差,防止深层网络梯度爆炸
- 🔀 Inverted Bottleneck(1× Linear 升维 4 倍 → GELU → 1× Linear 降维):类 Transformer 的 FFN 设计
🔹 ViT-DINO:冻结的视觉 Transformer
# ViT_DINO_reg.py(关键片段)
class PatchEmbed(nn.Module):
def __init__(self, img_size=224, patch_size=14, in_chans=3, embed_dim=1024, ...):
self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_HW, stride=patch_HW)
self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
# SSF 微调参数
if tuning_mode == 'ssf':
self.ssf_scale_1, self.ssf_shift_1 = init_ssf_scale_shift(embed_dim)
ViT-DINO 的关键设计:
- 🧊 冻结主体权重:DINOv2 在亿级无标注图像上预训练,表征能力极强
- 🔧 SSF(Scale & Shift)微调:只学两个小向量(scale + shift),参数增量 < 0.1%
- 🔀 LoRA 可选:对 Linear 层注入低秩适配矩阵
# SSF 实现
def ssf_ada(x, scale, shift):
return x * scale + shift # 极其简单,但效果显著
💡 为什么冻结 Backbone? 因为 DINOv2 已经学会了"什么是边缘、什么是平面、什么是物体",这些通用视觉先验对几何估计极其有用。Metric3Dv2 要做的,只是在这个表征上学会"怎么量尺寸"。
2.3 核心创新①:Label Scale Canonical Transformation
这是 Metric3Dv2 最优雅、也最容易被忽视的创新。代码在 transform.py 中:
# transform.py
class LableScaleCanonical(object):
def __init__(self, **kwargs):
self.canonical_focal = kwargs['focal_length'] # 规范焦距,如 1000.0
def _get_scale_ratio(self, intrinsic):
target_focal_x = intrinsic[0]
label_scale_ratio = self.canonical_focal / target_focal_x
return label_scale_ratio, 1.0
def __call__(self, images, labels, intrinsics, ...):
for i in range(len(intrinsics)):
intrinsic_i = intrinsics[i].copy()
label_scale_ratio, _ = self._get_scale_ratio(intrinsic_i)
# 将焦距映射到规范空间
intrinsics[i] = [intrinsic_i[0] * label_scale_ratio, ...]
# 深度值同步缩放
labels[i] = label_i * label_scale_ratio
这个操作的物理含义:
想象你有两张照片——一张用广角镜头(f=500px),一张用长焦镜头(f=2000px),拍的是同一个场景。在像素空间里,它们的深度值分布完全不同。
Metric3Dv2 的做法是:
把所有图像的焦距都"拉伸"到同一个规范值(如 1000px),深度值也同步缩放。
这样,模型在训练时看到的"世界"永远是同一个尺度,消除了焦距带来的尺度歧义。
🎯 效果:
- 不同数据集(KITTI f≈721, NYU f≈518, ScanNet f≈578)可以混在一起训练
- 模型学到的不是"某一种相机的深度",而是"通用几何"
- 推理时只需知道焦距,就能输出正确的 metric 深度
2.4 核心创新②:DPT-style Token 解码
DPT(Dense Prediction Transformer)的核心思想是将 ViT 的 token 序列"还原"为多尺度 2D 特征图:
# RAFTDepthNormalDPTDecoder5.py(结构示意)
class Token2Feature(nn.Module):
def __init__(self, token_dim, feature_dim, scale_factor=1.0, ...):
self.readout = ReadOut(token_dim, ...) # CLS/Register tokens → 融合
self.token2feature = nn.Conv2d(...) # Token → 2D 特征
self.upsample = nn.Upsample(scale_factor=...) # 上采样到目标分辨率
def forward(self, tokens, ...):
x = self.readout(tokens) # (B, N, C) → (B, C')
x = self.token2feature(x) # → (B, feature_dim, H', W')
x = self.upsample(x) # → 目标分辨率
return x
多尺度特征融合路径:
ViT 输出 tokens (1/14 分辨率)
├─ read_3 → 1/14 特征 (256ch)
├─ read_2 → 1/14 特征 (256ch)
├─ read_1 → 上采样到 1/7 特征 (128ch)
└─ read_0 → 上采样到 1/4 特征 (64ch)
ConvNeXt 输出特征 (1/4 分辨率, 256ch)
└─ 与 read_0 拼接 → 融合特征 (320ch)
💡 为什么用 DPT 而不是直接卷积上采样? 因为 ViT 的全局注意力机制让每个 token 都"看到了全图",这种全局上下文对深度估计的遮挡推理、大平面一致性至关重要。DPT 是连接"Transformer 表征"和"密集预测"的桥梁。
2.5 核心创新③:RAFT-style 迭代优化
这是 Metric3Dv2 区别于所有 DPT 衍生方法的关键设计。代码在 RAFTDepthNormalDPTDecoder5.py:
# RAFT-style 多尺度 GRU 更新
self.gru08 = ConvGRU(...) # 1/8 分辨率 GRU
self.gru16 = ConvGRU(...) # 1/16 分辨率 GRU
self.gru32 = ConvGRU(...) # 1/32 分辨率 GRU
# 上下文特征编码器
self.context_feature_encoder = ContextFeatureEncoder(...)
self.context_feature_decoder = ContextFeatureDecoder(...)
# 迭代次数
self.iters = 22 # 22 次迭代 refine
RAFT 迭代优化的核心思想:
# 简化版 RAFT 流程
for iter in range(self.iters):
# 1. 从当前深度估计中提取特征
hidden_state = gru_update(hidden_state, current_depth_features, context_features)
# 2. 用 GRU 更新隐藏状态
delta_depth = predict_delta(hidden_state)
# 3. 预测残差并累加
current_depth = current_depth + delta_depth
为什么要迭代?
| 单次预测 | 迭代优化 |
|---|---|
| 容易在薄结构(栏杆、电线)处崩 | GRU 逐步"修复"错误区域 |
| 遮挡边界模糊 | 上下文特征提供遮挡推理能力 |
| 远距离深度噪声大 | 多次迭代平滑噪声 |
| 平面不平整 | GRU 记忆机制保证平面一致性 |
🎯 类比:就像画画——先画一个粗糙的轮廓(单次预测),再反复打磨细节(迭代优化)。RAFT 在光流领域已被证明极其有效,Metric3Dv2 将其成功迁移到了深度/法向估计。
2.6 深度回归:分类而非回归
Metric3Dv2 没有直接回归深度值,而是采用了分类 + 期望的策略:
# HourGlassDecoder.py
def compute_depth_expectation(prob, depth_values):
depth_values = depth_values.view(*depth_values.shape, 1, 1)
depth = torch.sum(prob * depth_values, 1) # 加权平均
return depth
class HourglassDecoder(nn.Module):
def __init__(self, cfg):
self.num_depth_regressor_anchor = 512 # 512 个深度 bin
# 深度 bin 在 log 空间均匀划分
depth_bins_vec = torch.linspace(math.log(min_val), math.log(max_val), 512)
depth_bins_vec = torch.exp(depth_bins_vec) # 指数空间
def regress_depth(self, feature_map):
prob = self.depth_regressor(feature_map).softmax(dim=1) # 分类概率
depth = compute_depth_expectation(prob, self.depth_bins) # 期望 = 连续深度
return depth
为什么用分类而不是直接回归?
| 直接回归 | 分类 + 期望 |
|---|---|
| 对异常值敏感 | 概率分布天然抗噪 |
| 远距离深度梯度消失 | Log 空间 bin 保证远近都有分辨率 |
| 输出是"硬值" | 输出是"分布",自带不确定性 |
| 训练不稳定 | 交叉熵损失更平滑 |
💡 直觉理解:模型不是直接说"这个像素深度是 5.23 米",而是说"这个像素有 30% 概率在 4-5 米,50% 概率在 5-6 米,20% 概率在 6-7 米",然后取加权平均。
2.7 表面法向预测 + 不确定性建模
法向头的设计非常精巧,同时输出法向向量 + 不确定性(kappa):
# RAFTDepthNormalDPTDecoder5.py
def norm_normalize(norm_out):
norm_x, norm_y, norm_z, kappa = torch.split(norm_out, 1, dim=1)
norm = torch.sqrt(norm_x**2 + norm_y**2 + norm_z**2) + 1e-10
kappa = F.elu(kappa) + 1.0 + 0.01 # 保证 kappa > 0.01
return torch.cat([norm_x/norm, norm_y/norm, norm_z/norm, kappa], dim=1)
输出含义:
(norm_x, norm_y, norm_z)→ 归一化的表面法向(单位向量)
kappa→ 不确定性度量(类似 von Mises 分布的集中度参数)
🎯 kappa 越大 → 法向预测越可靠 🎯 kappa 越小 → 该区域预测不可靠(如天空、镜面反射)
2.8 不确定性引导的上采样
这是 RAFT 的经典设计,Metric3Dv2 沿用并改进:
# 用预测的 mask 做凸组合上采样
self.upsample_flow = ConvexUpsample(...)
# 或用传统插值
def upflow4(flow, mode='bilinear'):
new_size = (4 * flow.shape[2], 4 * flow.shape[3])
return F.interpolate(flow, size=new_size, mode=mode, align_corners=True)
Convex Upsample 的核心思想:
不是简单地双线性插值放大 4 倍,而是学习每个像素的 3×3 邻域权重,做加权组合。这样边缘会更锐利,薄结构不会糊掉。
2.9 训练数据构建:JSON 驱动 + 焦距归一化
从 generate_json.py 和 eigen_test.json 可以看到数据组织的精妙:
{
"files": [
{
"rgb": "kitti_raw/.../0000000069.png",
"depth": "kitti_depth/.../0000000069.png",
"cam_in": [721.5377, 721.5377, 609.5593, 172.854]
}
]
}
每条数据都包含:
- 📷 RGB 路径
- 📏 深度图路径(可选,无标注数据也能训练)
- 🎯 相机内参
[fx, fy, cx, cy](关键! 用于焦距归一化)
💡 cam_in 是 Metric3Dv2 的灵魂字段——没有它,模型就无法做 Label Scale Canonical Transformation,也就无法跨数据集泛化。
2.10 评测体系:全面且严谨
从 avg_meter.py 可以看到 Metric3Dv2 的评测指标非常完备:
深度指标
| 指标 | 含义 | ||
|---|---|---|---|
| AbsRel | 绝对相对误差: | pred – gt | / gt |
| RMSE | 均方根误差 | ||
| SILog | Scale-Invariant Log 误差 | ||
| δ1 / δ2 / δ3 | 阈值准确率(1.25 / 1.25² / 1.25³) |
法向指标
| 指标 | 含义 |
|---|---|
| Mean Error | 平均角度误差(度) |
| RMSE | 角度误差的 RMS |
| 5° / 7.5° / 11.25° / 22.5° / 30° | 角度准确率(预测法向与 GT 夹角小于阈值的占比) |
# avg_meter.py(关键片段)
normal_error = torch.cosine_similarity(pred, target, dim=1) # 余弦相似度
angle_error = torch.acos(normal_error) * 180.0 / torch.pi # 转角度
a1_error = 100.0 * (torch.sum(angle_error < 5) / valid_pics) # 5° 准确率
✅ 支持 GPU 计算 + 分布式 all-reduce,评测速度极快。
三、🚀 部署与工程实践建议

3.1 模型推理流程
从 do_test.py 可以提炼出完整的推理 pipeline:
# 推理核心流程(简化版)
def inference(model, rgb_image, intrinsic):
# Step 1: 焦距归一化(Label Scale Canonical)
canonical_focal = 1000.0
scale_ratio = canonical_focal / intrinsic[0]
canonical_intrinsic = [intrinsic[0]*scale_ratio, intrinsic[1]*scale_ratio,
intrinsic[2], intrinsic[3]]
# Step 2: 图像预处理(resize + padding + normalize)
rgb, cam_model, pad, label_scale = transform_test_data(rgb_image, canonical_intrinsic, cfg)
# Step 3: 模型推理
pred_depth, confidence, output = model.inference({'input': rgb})
# Step 4: 后处理(去 pad + 还原尺度 + 裁剪异常值)
pred_depth = pred_depth[pad[0]:-pad[1], pad[2]:-pad[3]]
pred_depth = pred_depth * normalize_scale / label_scale
pred_depth = (pred_depth > 0) * (pred_depth < 300) * pred_depth
return pred_depth
3.2 尺度对齐策略
当有 GT 深度时,Metric3Dv2 提供多种尺度对齐方式:
# do_test.py
def align_scale(pred, target):
"""简单尺度对齐:用中位数比值"""
mask = target > 0
scale = torch.median(target[mask]) / torch.median(pred[mask])
return pred * scale, scale
def align_scale_shift(pred, target):
"""仿射对齐:用最小二乘拟合 scale + shift"""
mask = target > 0
scale, shift = np.polyfit(pred[mask].cpu().numpy(), target[mask].cpu().numpy(), deg=1)
return pred * scale + shift, scale
| 对齐方式 | 适用场景 | 特点 |
|---|---|---|
| Median | 快速验证 | 只修正尺度,不修正偏移 |
| Scale + Shift | 精确评测 | 仿射变换,更准但需足够有效像素 |
| 无对齐 | 零样本推理 | 直接用模型输出的 metric 值 |
3.3 部署建议
🔹 GPU 服务器部署
| 配置 | 推荐方案 | 说明 |
|---|---|---|
| 高精度 | ViT-giant2 + FP32 | 最大模型,精度最高 |
| 平衡 | ViT-large + FP16 | 精度/速度最佳平衡 |
| 实时 | ConvNeXt-base + FP16 + ONNX | 边缘场景首选 |
🔹 ONNX 导出
# ONNX 导出(社区已支持)
model.eval()
model.onnx_compatible_mode = True
torch.onnx.export(
model,
(dummy_input, dummy_cam_model),
"metric3dv2.onnx",
opset_version=14,
dynamic_axes={"input": {0: "batch"}, "output": {0: "batch"}}
)
🔹 推理参数选型建议
| 场景 | Backbone | 分辨率 | 精度 | 预期速度 (A100) |
|---|---|---|---|---|
| 离线重建 | ViT-giant2 | 518×518 | ⭐⭐⭐⭐⭐ | ~50ms |
| 在线服务 | ViT-large | 406×406 | ⭐⭐⭐⭐ | ~20ms |
| 实时机器人 | ConvNeXt-base | 304×304 | ⭐⭐⭐ | ~8ms |
| 边缘设备 | ConvNeXt-tiny | 256×256 | ⭐⭐⭐ | ~3ms (Jetson) |
3.4 点云重建流程
从 unproj_pcd.py 可以看到完整的深度→点云流程:
def reconstruct_pcd(depth, fx, fy, u0, v0, mask=None):
H, W = depth.shape
# 构建像素坐标系下的射线方向
x = (u - u0) / fx # 水平方向
y = (v - v0) / fy # 垂直方向
z = ones_like(x) # 深度方向
pcd_base = stack([x, y, z], axis=2) # (H, W, 3)
# 乘以深度值 → 3D 点云
pcd = depth[:, :, None] * pcd_base
if mask is not None:
pcd[~mask] = 0 # 屏蔽无效区域
return pcd
后处理建议(来自 pcd_filter.py):
# 1. 降采样(千万级点云保护)
if len(pcd.points) > 10_000_000:
pcd = pcd.uniform_down_sample(N // 10_000_000 + 1)
# 2. 半径离群点滤波
max_bound = pcd.get_max_bound()
ball_radius = np.linalg.norm(max_bound) / 750
pcd_filtered, _ = pcd.remove_radius_outlier(nb_points=8, radius=ball_radius)
四、🌐 应用领域与前景展望

4.1 当前可直接落地的场景
🚗 自动驾驶感知
- 单目深度作为 LiDAR 的补充/替代(低成本方案)
- 与 BEV 感知融合,提升远距离障碍物检测
- 雨雾天气下的深度补全
🤖 机器人导航与抓取
- 室内服务机器人:实时建图 + 避障
- 机械臂抓取:精确的深度 + 法向信息
- 无人机自主飞行:森林、城市峡谷等 GNSS 拒止环境
🎮 AIGC / 3D 内容生成
- 单图 → 3D 场景重建(Gaussian Splatting 初始化)
- 图像编辑中的深度引导(如 AI 换背景)
- 视频深度估计 → 3D 视频生成
🏗️ 工业测量与 AR
- 建筑扫描:手机拍一张照 → 快速获取尺寸
- AR 标注:在真实场景中叠加虚拟信息
- 文物数字化:博物馆藏品 3D 存档
🕶️ VR / MR 场景理解
- 实时空间感知(Apple Vision Pro / Meta Quest 3)
- 手势交互的深度引导
- 虚拟/真实遮挡关系处理
📷 计算摄影
- 人像模式背景虚化(Portrait Mode)
- 夜景增强:深度引导的多帧融合
- 超分辨率:深度引导的边缘保护
4.2 技术前景展望

| 方向 | 描述 | 难度 |
|---|---|---|
| 🎬 视频时序一致性 | 将 RAFT 的光流思想扩展为"时序深度",保证视频帧间几何一致 | ⭐⭐⭐ |
| 🌐 全景/鱼眼支持 | 扩展相机模型,支持 360° 全景深度估计 | ⭐⭐ |
| 🔄 深度 ↔ 法向联合优化 | 利用深度和法向的几何约束互相修正 | ⭐⭐⭐ |
| 📊 稀疏控制点 + 稠密补全 | 结合 LiDAR 稀疏点云,输出稠密 metric 深度 | ⭐⭐ |
| 🧠 端侧 NPU 极致优化 | INT8 量化 + 知识蒸馏,跑在手机/眼镜上 | ⭐⭐⭐⭐ |
| 🎨 与生成模型打通 | Depth + Normal → Diffusion 引导 → 3D 内容生成 | ⭐⭐⭐⭐ |
五、📊 与其他算法对比一览
| 方法 | Metric 深度 | 表面法向 | 零样本泛化 | 实时性 | 开源程度 |
|---|---|---|---|---|---|
| MiDaS v3.1 | ❌ | ❌ | ✅ | ✅ | 完全开源 |
| Depth Anything v2 | ❌ | ❌ | ✅✅ | ✅✅ | 完全开源 |
| Marigold | ❌ | ❌ | ✅ | ❌ | 完全开源 |
| MoGe-2 | ✅ | ✅ | ✅ | ✅ | 完全开源 |
| GeoWizard | ✅ | ✅ | ✅ | ❌ | 完全开源 |
| Metric3Dv2 | ✅✅ | ✅✅ | ✅✅ | ✅✅ | 完全开源 |
📌 Metric3Dv2 是目前唯一在深度 + 法向两个任务上都达到 SOTA 且支持零样本 metric 估计的开源方案。
六、📝 最佳实践建议
6.1 数据准备
| 建议 | 说明 |
|---|---|
| ✅ 尽量提供准确的内参 | cam_in: [fx, fy, cx, cy] 越准,深度越准 |
| ✅ 无内参时用默认值 | intrinsic = [1000, 1000, W/2, H/2] 可作为 fallback |
| ✅ 图像质量 > 分辨率 | 清晰的图像比高分辨率模糊图像效果好 |
| ❌ 避免极端鱼眼 | 标准透视投影效果最佳 |
6.2 精度/速度权衡
| 策略 | 效果 |
|---|---|
| 降低输入分辨率 | 速度 ↑↑,远处精度 ↓ |
| 减少 RAFT 迭代次数 | 速度 ↑,薄结构精度 ↓ |
| 使用 ConvNeXt-tiny | 速度 ↑↑↑,整体精度 ↓ |
| FP16 推理 | 速度 ↑,精度几乎无损 |
| ONNX + TensorRT | 速度 ↑↑,需额外部署工作 |
6.3 常见坑与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 深度整体偏近 | 内参 fx 给大了 | 校准相机焦距 |
| 深度整体偏远 | 内参 fx 给小了 | 校准相机焦距 |
| 天空区域有值 | 模型无法区分天空 | 用 confidence map 过滤 |
| 薄结构断裂 | 分辨率不够 | 提高输入分辨率 |
| 镜面反射异常 | 物理限制 | 用 kappa 不确定性掩码 |
七、🎬 总结
Metric3Dv2 不是"又一个深度估计模型",而是将单目几何估计推向"基础模型时代"的关键一步。
它的核心贡献可以浓缩为三句话:
- 🎯 Label Scale Canonical Transformation —— 解决了跨数据集、跨焦距的尺度歧义问题,让"统一训练、零样本泛化"成为可能。
- 🔗 DPT + RAFT 深度融合 —— 兼具 Transformer 的全局上下文理解力和 RAFT 的迭代精细化能力。
- 📐 Depth + Normal 联合预测 —— 不只恢复"形状",还恢复"表面朝向",为下游 3D 任务提供完整几何信息。

📚 参考资料
| 资源 | 链接 |
|---|---|
| 📄 Metric3Dv1 论文 | https://arxiv.org/abs/2307.10984 |
| 📄 Metric3Dv2 论文 | https://arxiv.org/abs/2404.15506 |
| 🌐 项目主页 | https://jugghm.github.io/Metric3Dv2 |
| 🤗 HuggingFace Demo | https://huggingface.co/spaces/JUGGHM/Metric3D |
| 💻 GitHub 仓库 | https://github.com/JUGGHM/Metric3D |
| 📄 GeoWizard(姊妹篇) | https://arxiv.org/abs/2403.12013 |
"Geometry is the foundation of perception. Metric3Dv2 makes it accessible from a single glance." ✍️ 本文档基于 Metric3Dv2 开源代码分析撰写,旨在帮助读者快速理解其技术原理与应用价值。