——Meta Reality Labs 与卡内基梅隆大学联合开源的通用度量三维重建模型
一、为什么需要“通用”三维重建?
过去要做一套**度量级(metric)**三维场景,得把 pipeline 拆成七零八落的小模块:
步骤 | 典型工具 | 痛点 |
---|---|---|
特征点提取 | SIFT/SuperPoint | 参数多、夜景/白墙失效 |
匹配与几何验证 | SuperGlue | 内存随图平方增长 |
姿态解算 | 5-Point + RANSAC | 需要足够基线,否则退化 |
三角化 & BA | COLMAP | 迭代耗时,尺度模糊 |
稠密匹配 | MVSNet / PatchMatch | 需 GPU 反复调度 |
每换一个任务(单目深度、双目立体、SfM、定位、深度补全)就要重写数据流和损失函数。
MapAnything 的核心思想:用一套前向网络,一次性把“相机-几何-尺度”全部回归出来,跳过碎片化优化。
二、MapAnything 到底是什么?
一句话:
给 1~2000 张普通照片(可附带相机内参、位姿、稀疏深度),模型直接输出度量级点云与相机参数,无需 BA 后处理。
关键特征:
-
12 种以上任务同一权重:
单目深度、多视立体、未标定 SfM、已标定 SfM、相机定位、深度补全、宽角相机标定…… -
真·度量输出:
预测全局尺度因子 m,点云单位=米,不再“比例未知”。 -
任意数量视图:
训练时 2-24 张,推理可扩到 2000 张,显存用“梯度检查点+块注意力”换时间。 -
完全前向:
0 次迭代,0 次 BA;位姿、深度、射线方向、尺度同时回归。 -
开源友好:
代码 Apache 2.0,模型分“商用版”与“研究版”,HuggingFace 一键调用。
三、技术拆解:它如何把“图片”变“点云”?
3.1 输入侧:图片 +“可选”几何
输入类型 | 形式 | 是否必须 |
---|---|---|
RGB 图像 | (H, W, 3) uint8 | ✅ |
相机内参 K | 3×3 矩阵 | ❌ |
相机位姿 | 4×4 矩阵 或 (四元数, 平移) | ❌ |
深度图 | (H, W) float32 | ❌ |
尺度标记 | is_metric_scale 布尔 | ❌ |
只要给得出,模型就吃得下;不给也能跑,精度随缘。
3.2 编码器:把像素与几何拉进同一 latent 空间
-
图像支路
用 DINOv2 ViT-L/14 最后一层 patch token,1024-d,空间 stride=14。 -
几何支路 -
稠密信号(深度、射线方向)→ 一层 PixelUnshuffle + 轻量 CNN,拉到 1024-d。 -
全局信号(四元数、平移、尺度)→ 4 层 MLP,输出 1024-d 向量,再广播到空间尺寸。
-
-
归一化 & 相加
所有模态同维度后直接相加,再 LayerNorm,得到“多模态 token”。
3.3 多视图同步:交替注意力 transformer
-
24 层、768 隐维、12 头,无 RoPE(作者实验发现 patch 位置编码已够用)。 -
交替注意力:先 self-attention 再 cross-attention,循环 12 轮,避免 O(N²×H×W) 显存爆炸。 -
可学习尺度 token:单独一个向量,与 patch token 一起进网络,全局聚合后预测度量尺度 m。
3.4 解码:分治式输出“四件套”
输出 | 含义 | 形状 | 说明 |
---|---|---|---|
R_i | 单位射线方向 | (H, W, 3) | 相当于“自标定”相机 |
D̃_i | 沿射线深度 | (H, W, 1) | 无尺度,需乘 m |
P_i | 相机位姿 | (4, 4) | 相对第 1 视图 |
m | 全局尺度 | 标量 | 把 D̃_i → 米制深度 |
有了 R_i 与 D̃_i,可立刻算出局部点云 L_i = R_i · D̃_i;再用 P_i 转到世界坐标,乘 m 得度量点云。
3.5 损失函数:让 12 任务同时收敛的“组合拳”
总损失 = 10·点云 + 1·射线 + 1·旋转 + 1·平移 + 1·深度 + 1·局部点云 + 1·尺度 + 0.1·mask + (合成数据才加) 法向 + 梯度匹配
关键细节:
-
全部回归量取 log(1+|·|),抑制远处大数值梯度。 -
尺度不变:先算真值与预测各自的平均范数 ẑ、z̃,再归一化后比较。 -
置信度加权:给每个像素预测置信度 C_i,自动降低纹理缺失区权重。 -
鲁棒核:Adaptive Loss,c=0.05,α=0.5,自动把离群点拉回来。
四、训练揭秘:如何让一个模型“啥都会”?
4.1 数据来源
数据集 | 场景 | 是否商用 | 备注 |
---|---|---|---|
BlendedMVS | 建筑 | ✅ | 493 场景 |
ScanNet++ v2 | 室内 | ❌ | 926 场景,毫米级真值 |
TartanAirV2-WB | 合成 | ✅ | 49 大场景,多天气 |
Mapillary 行星深度 | 街景 | ❌ | 7.1 万张 |
Spring / ETH3D / MegaDepth … | 混合 | 部分商用 | 共 13 套 |
商用版用 6 套可商用数据;研究版再加 7 套非商用数据,性能更优。
4.2 采样策略:只看“连得上”的视图
-
预计算所有图像对的重投影共视分数。 -
训练时随机游走,取连通子图,确保视图间>25% 重叠。 -
单卡 4-24 视图,批大小动态调(视图越多 batch 越小)。
4.3 输入 Dropout:把“缺数据”变成特征
每轮训练以 0.5 概率丢弃射线、深度、位姿中的一种,0.05 概率把“真值尺度”也屏蔽,迫使网络靠图像自己估尺度。
→ 推理时哪怕只给图片,模型也能跑,且误差可控。
五、实验结果:真有那么神?
以下数字均来自原文,测试集 ETH3D、ScanNet++ v2、TartanAirV2-WB 平均。
5.1 多视稠密重建(50 张图)
指标↓/↑ | 仅图像 | +K | +K+Pose | +K+Pose+Depth |
---|---|---|---|---|
点云相对误差 | 0.16 | 0.12 | 0.05 | 0.01 |
内点率 (τ=1.03%) | 40.7% | 55.8% | 72.6% | 92.1% |
位姿 ATE | 0.03 m | 0.03 m | 0.01 m | <0.01 m |
结论:
-
只靠图像已超 VGGT(0.20)。 -
给越多先验,误差指数级下降,最终 1 cm 级。
5.2 两张图极限情况
方法 | 点云误差 | 内点率 | 备注 |
---|---|---|---|
DUSt3R | 0.20 | 43.9% | 无尺度 |
Pow3R | 0.19 | 42.5% | 需 K |
MapAnything | 0.12 | 53.6% | 仅图像 |
MapAnything +K+Pose | 0.06 | 91.7% | 两篇图即>90% 内点 |
5.3 单张图相机自标定
方法 | 平均角度误差 |
---|---|
AnyCalib | 2.01° |
MoGe-2 | 1.95° |
MapAnything | 1.18° |
模型根本没为“单图”专门训练,却拿了第一。
六、快速上手:30 分钟跑通示例
环境准备:
git clone https://github.com/facebookresearch/map-anything.git
cd map-anything
conda create -n mapanything python=3.12 -y && conda activate mapanything
# 按机器装 PyTorch,示例略
pip install -e ".[all]"
6.1 仅图像推理(最简)
import torch, os
from mapanything.models import MapAnything
from mapanything.utils.image import load_images
device = "cuda" if torch.cuda.is_available() else "cpu"
model = MapAnything.from_pretrained("facebook/map-anything-apache").to(device)
views = load_images("folder/of/jpg") # 支持文件夹或列表
preds = model.infer(views, memory_efficient_inference=True, use_amp=True)
for p in preds:
pts = p["pts3d"] # (H,W,3) 世界坐标,单位:米
cam = p["camera_poses"] # 4×4 矩阵
conf = p["conf"] # 置信度图
一行代码就能把 pts
写进 .ply
,用 MeshLab 直接看。
6.2 多模态:带 K+Pose+Depth 的高精度模式
views = [
{
"img": image_tensor, # 0-255 RGB
"intrinsics": K_tensor, # 3×3
"depth_z": depth_tensor, # 单位:米
"camera_poses": T_tensor, # 4×4 OpenCV 格式
"is_metric_scale": torch.tensor([True])
},
# ... 更多视图
]
processed = preprocess_inputs(views)
preds = model.infer(processed, **common_args)
6.3 可视化方案
-
在线 Demo:HuggingFace Space 直接拖拽图片。 -
本地 Gradio: pip install -e ".[gradio]" && python scripts/gradio_app.py
-
Rerun 交互: rerun --serve --port 2004 --web-viewer-port 2006 python scripts/demo_images_only_inference.py \ --image_folder /path --viz --save_glb
七、与流行工具链的“无缝对接”
7.1 导出 COLMAP
pip install -e ".[colmap]"
python scripts/demo_colmap.py --scene_dir /YOUR/SCENE_DIR \
--memory_efficient_inference --use_ba
输出 cameras.bin / images.bin / points3D.bin
,可直接用 COLMAP GUI 继续编辑,或做 NeRF/Gaussian Splatting。
7.2 Gaussian Splatting 训练(gsplat)
cd <gsplat>
python examples/simple_trainer.py default \
--data_dir /YOUR/SCENE_DIR --result_dir /output
八、常见疑问(FAQ)
Q1:没有 GPU 能跑吗?
A:CPU 可跑官方 Demo,但 512×384 图像单张需 ~6 GB 内存,建议至少 8 GB 显存显卡。
Q2:手机照片直接能用吗?
A:可以。模型对 EXIF 朝向自动处理,无需预标定;若给 K(可在手机相册“详情”里找到焦距),精度更高。
Q3:夜景/白墙/水面这种弱纹理场景如何?
A:论文显示在 TartanAir 的“雾+雪”子集仍领先,但弱纹理区置信度 mask 会自动降低;多拍几张重叠照片可缓解。
Q4:尺度因子 m 会出错吗?
A:仅图像输入时,误差约 5-15%;给 1 个真实深度或 1 个 GPS 位姿即可降到 <3%。
Q5:商用收费吗?
A:代码永远 Apache 2.0;模型选 map-anything-apache
可闭源商用,另一版(CC-BY-NC)仅限研究。
九、局限与未来方向
-
尚未显式建模输入不确定性(如 GPS 噪声)。 -
动态场景/非刚性物体暂不支持,点云会出现“鬼影”。 -
大场景显存仍随像素线性增长,需要分层或流式解码。 -
目前一次推理即终局,未探索“测试时扩算力”迭代 refine 的效果。
十、总结:一张图看懂 MapAnything
任意照片 ──► 编码(DINOv2+几何) ──► 多视 transformer ──► 四件套(R, D̃, P, m)
│
▼
度量点云 + 相机
-
省:12 任务一套权重,训练成本 < 2× 专用模型。 -
快:0 次 BA,单卡 2 000 视图小时级。 -
准:两视图即得 <1 cm 误差,多数据集 SoTA。 -
爽:Apache 代码+商用模型,pip install 即可玩。
如果你厌倦了“调参-跑 BA-换数据集-再调参”的循环,MapAnything 提供了一条“端到端、带尺度、可商用”的新路径。打开 GitHub,把照片拖进去,你的第一张度量级点云就在 30 分钟后等你。