站点图标 高效码农

MapAnything:把任意照片变成带尺度的 3D 模型,只需一次前向计算

——Meta Reality Labs 与卡内基梅隆大学联合开源的通用度量三维重建模型


一、为什么需要“通用”三维重建?

过去要做一套**度量级(metric)**三维场景,得把 pipeline 拆成七零八落的小模块:

步骤 典型工具 痛点
特征点提取 SIFT/SuperPoint 参数多、夜景/白墙失效
匹配与几何验证 SuperGlue 内存随图平方增长
姿态解算 5-Point + RANSAC 需要足够基线,否则退化
三角化 & BA COLMAP 迭代耗时,尺度模糊
稠密匹配 MVSNet / PatchMatch 需 GPU 反复调度

每换一个任务(单目深度、双目立体、SfM、定位、深度补全)就要重写数据流和损失函数。
MapAnything 的核心思想:用一套前向网络,一次性把“相机-几何-尺度”全部回归出来,跳过碎片化优化。


二、MapAnything 到底是什么?

一句话:

给 1~2000 张普通照片(可附带相机内参、位姿、稀疏深度),模型直接输出度量级点云相机参数,无需 BA 后处理。

关键特征:

  1. 12 种以上任务同一权重:
    单目深度、多视立体、未标定 SfM、已标定 SfM、相机定位、深度补全、宽角相机标定……
  2. 真·度量输出
    预测全局尺度因子 m,点云单位=米,不再“比例未知”。
  3. 任意数量视图
    训练时 2-24 张,推理可扩到 2000 张,显存用“梯度检查点+块注意力”换时间。
  4. 完全前向
    0 次迭代,0 次 BA;位姿、深度、射线方向、尺度同时回归。
  5. 开源友好
    代码 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 空间

  1. 图像支路
    用 DINOv2 ViT-L/14 最后一层 patch token,1024-d,空间 stride=14。
  2. 几何支路
    • 稠密信号(深度、射线方向)→ 一层 PixelUnshuffle + 轻量 CNN,拉到 1024-d。
    • 全局信号(四元数、平移、尺度)→ 4 层 MLP,输出 1024-d 向量,再广播到空间尺寸。
  3. 归一化 & 相加
    所有模态同维度后直接相加,再 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 直接拖拽图片。
  • 本地 Gradiopip 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)仅限研究。


九、局限与未来方向

  1. 尚未显式建模输入不确定性(如 GPS 噪声)。
  2. 动态场景/非刚性物体暂不支持,点云会出现“鬼影”。
  3. 大场景显存仍随像素线性增长,需要分层或流式解码。
  4. 目前一次推理即终局,未探索“测试时扩算力”迭代 refine 的效果。

十、总结:一张图看懂 MapAnything

任意照片 ──► 编码(DINOv2+几何) ──► 多视 transformer ──► 四件套(R, D̃, P, m)
                                                                       │
                                                                       ▼
                                                               度量点云 + 相机
  • :12 任务一套权重,训练成本 < 2× 专用模型。
  • :0 次 BA,单卡 2 000 视图小时级。
  • :两视图即得 <1 cm 误差,多数据集 SoTA。
  • :Apache 代码+商用模型,pip install 即可玩。

如果你厌倦了“调参-跑 BA-换数据集-再调参”的循环,MapAnything 提供了一条“端到端、带尺度、可商用”的新路径。打开 GitHub,把照片拖进去,你的第一张度量级点云就在 30 分钟后等你。

退出移动版