拆解 Metric-Video-Depth-Anything-Large-MLX 架构:DINOv2 + DPT + 时序运动模块如何实现一致的深度估计
拆解 Metric-Video-Depth-Anything-Large-MLX 架构:DINOv2 + DPT + 时序运动模块如何实现一致的深度估计
Metric-Video-Depth-Anything-Large-MLX 是字节跳动视频深度估计模型 Video Depth Anything(CVPR 2025 highlight)的 MLX 移植版:输入一段视频,逐帧输出单位为米(meters)的度量深度。本文拆解它的三大核心组件——DINOv2 主干、DPT 解码头与 AnimateDiff 风格时序运动模块——如何协同工作,并给出 MLX 环境下的快速上手步骤,帮助新手快速理解与落地。
这个模型能做什么?一句话看懂
传统单目深度估计只针对单张图像,逐帧独立计算会导致视频画面中出现明显的"深度闪烁"。Metric-Video-Depth-Anything-Large-MLX 解决的就是这个问题:它针对任意长视频生成前后帧一致的深度序列,并且直接输出米为单位的绝对深度,无需任何后处理对齐。
核心特性一览:
- ⚡ MLX 原生:针对 Apple Silicon(Metal 加速)转换,权重为 fp32
- 📏 度量输出:直接得到米,跳过相对深度模型必需的 scale/shift 窗口对齐
- 🎬 长视频可用:以 32 帧为窗口分段推理,任意长度视频保持一致
- ✅ 高保真:GPU 上与 PyTorch 参考实现相对误差约 1%,CPU 上约 1e-5
架构总览:三大部件的流水线
模型在 config.json 中声明 model_type 为 video_depth_anything,整条推理流水线由三个串行部件组成:
- DINOv2 ViT-L 主干 —— 负责"看清图像"
- DPT 解码头 —— 负责"把特征变成深度图"
- 时序运动模块 —— 负责"让相邻帧保持一致"
数据流向:视频帧序列 (B, T, H, W, 3) → DINOv2 提取多尺度特征 → 时序运动模块融合相邻帧信息 → DPT 头逐级上采样出全分辨率深度图 (T, H, W)。三者各司其职,缺一不可。
DINOv2 主干:强大的视觉特征提取
主干选用 DINOv2 的 ViT-L(Large 规格 Transformer),对应配置项 "encoder": "vitl"。DINOv2 是自监督视觉基础模型,其特征在语义与几何信息上都足够强,是深度估计任务的理想底座。
两个与输入相关的细节:
- 输入分辨率 518,定义于 preprocessor_config.json;H 和 W 必须是 14 的倍数(ViT patch 尺寸对齐要求)
- 位置编码采用绝对位置编码(
"pe": "ape"),在固定输入分辨率下数值更稳定
DPT 解码头:从多尺度特征到全分辨率深度
DPT(Dense Prediction Transformer)头负责把 ViT 各阶段的特征"膨胀"成稠密的深度图。关键参数同样在 config.json 中:
"features": 256:解码网络统一的特征通道数"out_channels": [256, 512, 1024, 1024]:四级融合分支的输出通道,与主干不同尺度特征对应,由低分辨率逐级上采样至全分辨率
正是这种多尺度融合 + 渐进上采样的结构,让输出的深度图能够与输入视频帧保持同等细腻度。
时序运动模块:视频一致性的关键
单帧深度模型跑在视频上会"闪烁",这个模型在编码层之间插入了 AnimateDiff 风格的时序运动模块(temporal motion module),它的作用是:
- 在时间维度上学习并融合相邻帧的特征
- 让同一场景在不同帧中的深度空间上保持一致
- 以
"num_frames": 32为窗口长度,更长的视频按 32 帧分段推理,段间衔接依然连贯
这正是它敢承诺"对任意长视频做一致性单目深度估计"的原因。
Metric 模式:为什么能直接输出米
config.json 中的 "metric": true 是一个关键开关。度量版与相对版的核心区别:
| 对比项 | 相对版(Relative) | 度量版(Metric) |
|---|---|---|
| 输出 | 无量纲的深度比值 | 绝对深度(米) |
| 后处理 | 需要 scale/shift 窗口对齐 | 直接跳过 |
| 典型场景 | 视觉效果、深度排序 | 三维重建、机器人导航 |
也就是说,推理完直接得到"带尺子"的结果,省去了额外对齐步骤,工程链路更短。
快速上手:MLX 下一键运行
推理入口是 mlx_vlm 提供的 VideoDepthPredictor。最小可用示例(完整说明见 README.md):
from mlx_vlm import load
from mlx_vlm.models.video_depth_anything.generate import (
VideoDepthPredictor,
read_video_frames,
)
model, processor = load("mlx-community/Metric-Video-Depth-Anything-Large-MLX")
predictor = VideoDepthPredictor(model, processor)
frames, fps = read_video_frames("input.mp4", max_len=300, target_fps=15)
depths = predictor.infer(frames) # (T, H, W) float32
使用时的三个注意点:
- 输入为 channel-last 的
(B, T, H, W, 3),H/W 需为 14 的倍数 max_len与target_fps控制采样帧数和帧率,建议先用短片段验证效果- 输出
depths是(T, H, W)的 float32 数组,数值即米为单位的绝对深度
文件清单与配置解读
| 文件 | 作用 |
|---|---|
| README.md | 用法示例、输入约束与精度说明 |
| config.json | 架构配置:ViT-L 主干、metric 模式、256 通道、32 帧窗口、ape 位置编码 |
| preprocessor_config.json | 预处理配置:输入分辨率 518 |
| model.safetensors | fp32 权重,约 15.4 GB(仓库中以 Git-LFS 指针存储) |
总结
Metric-Video-Depth-Anything-Large-MLX 把完整的 Video Depth Anything Large 流水线搬进了 MLX 生态:DINOv2 管特征、DPT 头管解码、时序运动模块管一致性,再配合 metric 模式让输出直接以米为单位。如果你在 Apple Silicon 上需要为长视频做 3D 重建或深度可视化,这是一个开箱即用且精度接近官方 PyTorch 版本的选择。
⚠️ 注意:项目采用 CC-BY-NC-4.0 许可,仅限非商业用途。