首页
/ DepthPro 深度指南:用 Transformers 实现零样本公制单目深度估计

DepthPro 深度指南:用 Transformers 实现零样本公制单目深度估计

2026-09-07 15:33:18作者:郁楠烈Hubert

DepthPro 是 2024 年 10 月发表于 Hugging Face 论文页、由社区贡献者 geetu040 移植进 🤗 Transformers 的深度估计基础模型(模型文档)。它无需任何元数据(如相机内参)即可从单张 RGB 图像输出带绝对尺度的公制深度图,同时保持边界锐利与高频细节。本文将以该文档为主体,结合 depth_pro 模型源码 与配置实现,讲解其多尺度 ViT + DPT 融合架构、DepthProConfig 全量配置项、FOV(视场角)预测开关、图像预处理/后处理管线,并给出可直接运行的推理脚本与 SDPA 加速建议,帮助你快速把 DepthPro 接入自己的深度估计流程。

DepthPro 是什么:零样本、公制尺度、亚秒级

DepthPro(论文名《Depth Pro: Sharp Monocular Metric Depth in Less Than a Second》)是一个面向 zero-shot metric monocular depth estimation(零样本公制单目深度估计)的基础模型。与只能输出相对深度的经典单目深度模型不同,DepthPro 的预测是 metric(带绝对物理尺度) 的,不依赖相机内参这类元数据即可直接给出与真实世界尺度对齐的深度;其设计目标还包括在标准 GPU 上约 0.3 秒内产出 2.25 兆像素(约 225 万像素)的高分辨率深度图。

从论文摘要与文档描述可以归纳出支撑这些能力的几项关键技术贡献:

  • 面向稠密预测的高效多尺度 Vision Transformer:对输入做多尺度缩放与切块,用共享的 ViT 编码器提取 patch 级特征,再重建、上采样并融合,兼顾高分辨率与计算效率;
  • 真实数据 + 合成数据的联合训练协议:让模型在获得较高公制精度的同时具备精细的边界追踪能力;
  • 专门的深度图边界精度评估指标
  • 单图焦点长度(focal length)估计:模型扩展出 FOV/焦点长度预测能力。

模型由 DepthPro 编码器与融合模块 实现,DepthProForDepthEstimation 负责端到端的深度估计推理。仓库中同时提供将 Apple 官方权重转换为 Transformers 格式的脚本 convert_depth_pro_weights_to_hf.py,对应检查点为 apple/DepthPro-hf

整体架构:多尺度 ViT 编码 + DPT 式融合解码

按照 DepthPro 模型文档 的说明,DepthPro 的处理流水线可拆成四条主线:

  1. 输入图像在多个尺度上被降采样,每个缩放版本再被切成若干重叠 patch
  2. 所有 patch 由一个共享的 Dinov2 patch 编码器处理,与此同时完整图像被送入另一个独立的 image 编码器
  3. patch 编码得到的特征经过 merge / upsample / refine 重建为特征图;
  4. 重建出的特征送入 DPT-like 的 FeatureFusionStage 融合,最终输出深度图。

在源码中,这一架构由 DepthProModelDepthProForDepthEstimation 等类具体实现,其中 DepthProForDepthEstimation 使用一个 DepthProEncoder(编码输入图像)和一个 FeatureFusionStage(融合编码器输出特征)。

DepthProEncoder 内部包含两个编码器,均在 modeling_depth_pro.py 中定义:

  • patch_encoder源码):
    • 输入图像按 scaled_images_ratios 配置的多个比例缩放(默认 [0.25, 0.5, 1.0],即三级图像金字塔);
    • 每个缩放图像按 patch_size 切成小 patch,重叠比例由 scaled_images_overlap_ratios 决定(源码中通过 F.unfold 实现,见 split_to_patches);
    • patch 被 torch.cat 拼接后以 batch 方式整体送入共享 patch 编码器(源码注释:高分辨率 patch 在前);
    • 编码器输出经过 reconstruct_feature_maps(reshape → 去重叠 padding 合并 → 双线性插值回目标尺寸)重建成特征图。
  • image_encoder源码):
    • 输入图像被重缩放到 patch_size(默认 384),由独立的 image 编码器整体处理,提供全局上下文特征。

两个编码器均可通过配置项 patch_model_configimage_model_config 分别定制,默认都是独立的 Dinov2Model(配置构造时自动回退,见下文 DepthProConfig 一节)。

融合阶段则使用 DPT 风格解码:patch 编码器输出的 last_hidden_state 与选中的若干中间层 hidden_states(由 intermediate_hook_ids 指定)一起进入 FeatureFusionStage。融合网络由三个关键组件构成(源码):

  • DepthProPreActResidualLayer:pre-activation 残差单元(ReLU → Conv → ReLU → Conv + 残差相加,可选 BatchNorm);
  • DepthProFeatureFusionLayer:双残差单元 + 可选转置卷积上采样 + 1×1 投影;
  • DepthProFeatureFusionStage:层数为 len(intermediate_hook_ids) + len(scaled_images_ratios)(默认 2+3=5),其中除最后一层外都带转置卷积上采样,最后一层用 1×1 投影收尾。

值得注意:DepthProModelDepthProEncoder 输出的是特征集合DepthProOutput.features),真正的深度回归发生在 DepthProForDepthEstimation:它由 DepthProModel + FeatureFusionStage + 3 层卷积的深度估计头组成,深度头(DepthProDepthEstimationHead)逐层降维并上采样,最终压成单通道深度图,输出结构为 DepthProDepthEstimatorOutput(含 predicted_depth、可选的 field_of_view)。

DepthProConfig:配置参数全解

DepthProConfig 定义在 configuration_depth_pro.pymodel_type = "depth_pro"。与多数模型不同,它声明了三个子配置 sub_configs = {"image_model_config", "patch_model_config", "fov_model_config"},子配置通过 AutoConfig 解析。

核心字段与默认值

配置参数 默认值 含义
fusion_hidden_size 256 融合阶段(各子网统一投影到)的通道数
patch_size 384 patch 边长,同时用于切块与图像重缩放目标尺寸
initializer_range 0.02 权重初始化范围
intermediate_hook_ids (11, 5) 从 patch 编码器取中间层特征用于融合的层索引
intermediate_feature_dims (256, 256) 上述每个中间层特征上采样过程的隐层维度
scaled_images_ratios (0.25, 0.5, 1.0) patch 编码器使用的多尺度图像缩放比例(需升序排列)
scaled_images_overlap_ratios (0.0, 0.5, 0.25) 每个缩放级别下相邻 patch 的重叠比例
scaled_images_feature_dims (1024, 1024, 512) 每个缩放级别特征重建/上采样过程的隐层维度
merge_padding_value 3 小块合并回整图时,相邻块重叠边缘需要裁掉的宽度
use_batch_norm_in_fusion_residual False 融合残差单元是否使用 BatchNorm
use_bias_in_fusion_residual True 融合残差单元卷积是否使用 bias
use_fov_model False 是否启用 DepthProFovModel 预测水平视场角
num_fov_head_layers 2 FOV 预测头的卷积层数量
image_model_config None image 编码器配置(通过 AutoModel 加载,默认 Dinov2)
patch_model_config None patch 编码器配置(通过 AutoModel 加载,默认 Dinov2)
fov_model_config None FOV 编码器配置(通过 AutoModel 加载,默认 Dinov2)

(默认值对应关系见 configuration_depth_pro.py 中的字段声明。)

自动解析与一致性校验

__post_init__源码)会处理三个子配置,规则如下:

  • 若子配置为 None:自动以 CONFIG_MAPPING["dinov2"] 生成 Dinov2Config,且将其 image_size 强制设为 config.patch_size(默认 384);
  • 若子配置为 dict:必须包含受支持的 model_type 键,image_size 若不等于 patch_size 会被自动修正并打印日志;
  • 若子配置为 PreTrainedConfig:其 image_size 必须与 patch_size 一致,否则抛 ValueError

此外 validate_architecture源码)会在严格模式下校验架构合法性:

  • scaled_images_ratios 必须从低到高升序排列
  • scaled_images_ratios / scaled_images_overlap_ratios / scaled_images_feature_dims 三者长度必须一致;
  • intermediate_hook_idsintermediate_feature_dims 长度必须一致;
  • fusion_hidden_size // 2**num_fov_head_layers 必须大于 0(保证 FOV 头逐层减半通道后仍有意义)。

这些长度一致性约束直接呼应上面的参数表——改动某个比例列表时,务必同步更新配套列表,否则会构造失败。

快速上手:单张图片的端到端深度估计

最小推理示例

仓库文档给出了完整推理脚本,流程为:取图 → DepthProImageProcessor 预处理 → DepthProForDepthEstimation 前向 → post_process_depth_estimation 后处理 → 可视化。下文在其基础上补充了逐行注释:

import requests
import torch
from PIL import Image

from transformers import DepthProForDepthEstimation, DepthProImageProcessor

# 1. 加载示例图片(COCO 验证集)
url = 'http://images.cocodataset.org/val2017/000000039769.jpg'
image = Image.open(requests.get(url, stream=True).raw)

# 2. 加载图像处理器与模型(device_map="auto" 便于自动分配到可用设备)
image_processor = DepthProImageProcessor.from_pretrained("apple/DepthPro-hf")
model = DepthProForDepthEstimation.from_pretrained("apple/DepthPro-hf", device_map="auto")

# 3. 预处理并前向
inputs = image_processor(images=image, return_tensors="pt").to(model.device)
with torch.no_grad():
    outputs = model(**inputs)

# 4. 后处理:把预测深度插值回原图尺寸,并解析 FOV / 焦距
post_processed_output = image_processor.post_process_depth_estimation(
    outputs, target_sizes=[(image.height, image.width)],
)

field_of_view = post_processed_output[0]["field_of_view"]
focal_length = post_processed_output[0]["focal_length"]
depth = post_processed_output[0]["predicted_depth"]

# 5. 归一化到 0-255 并转成可视灰度图
depth = (depth - depth.min()) / depth.max()
depth = depth * 255.
depth = depth.detach().cpu().numpy()
depth = Image.fromarray(depth.astype("uint8"))

DepthProModel 也可独立使用(不含深度头)。模型文档DepthProModel.forward 的 docstring 展示了用 AutoProcessor / AutoImageProcessor 的等价写法:此时 processor = AutoImageProcessor.from_pretrained(checkpoint),模型输出 last_hidden_state 的形状形如 (1, 35, 577, 1024)(patch 编码的多尺度特性使序列维较大)。

预处理与后处理的两个"反直觉"细节

DepthProImageProcessorimage_processing_depth_pro.py)默认参数为:输入尺寸 1536×1536、双线性插值、ImageNet 均值和方差、do_resize / do_rescale / do_normalize 全为 True

其自定义 _preprocess源码)有一个特殊顺序——先 rescale+normalize,再做 resize,并且 resize 关闭抗锯齿(antialias=False),使用 torch 插值以正确处理负像素值。这与大多数"先缩放后归一化"的视觉模型相反,是对齐原版实现的重要细节。

后处理 post_process_depth_estimation源码)内部完成三件事:

  1. 若启用了 FOV 且提供了 target_sizes,按公式 focal_length = 0.5 * width / tan(0.5 * deg2rad(fov)) 估算焦距,并用 depth * width / focal_length 做尺度校正;
  2. 把深度图双线性插值回 target_sizes
  3. 对深度取倒数还原真实深度(1.0 / clamp(depth, min=1e-4, max=1e4)),因为网络内部预测的是逆深度。

返回的 dict 包含三个键:predicted_depthfield_of_viewfocal_length

视场角(FOV)预测:开关与两种开启方式

FOV 预测是 DepthPro 的附加能力,用于从单张图片估计相机水平视场角,进而辅助得到焦点长度、提升深度精度。文档指出:一个小型卷积头同时吞入深度估计网络产出的冻结特征(frozen features)与来自独立 ViT 图像编码器的任务特征,输出水平视场角

从源码看,FOV 分支由三层组成(modeling_depth_pro.py):

  • DepthProFovEncoder:独立 ViT(默认 Dinov2)+ 线性投影到 fusion_hidden_size // 2 通道;
  • 一个 3×3 stride=2 卷积 + ReLU,处理深度分支传来的全局特征;
  • DepthProFovHead:按 num_fov_head_layers 逐层将通道减半并下采样,最后卷积出标量 FOV 值并 flatten

DepthProForDepthEstimation.forward 中,深度分支用于 FOV 的特征是 features[0].detach()源码),即冻结梯度的全局特征,这与文档"frozen features"的描述一致。

DepthProConfig.use_fov_model 控制是否启用 FOV 预测,默认 False 以节省显存与计算。启用时会依据 fov_model_config(默认 Dinov2Model)实例化 FOV 编码器。需要强调的是:

  • 预训练检查点 apple/DepthPro-hf 本身带 FOV 编码器。若想省计算,可在加载时显式传 use_fov_model=False
from transformers import DepthProForDepthEstimation

model = DepthProForDepthEstimation.from_pretrained("apple/DepthPro-hf", use_fov_model=False, device_map="auto")
  • 新建模型并启用 FOV,可在 config 中开启:
from transformers import DepthProConfig, DepthProForDepthEstimation

config = DepthProConfig(use_fov_model=True)
model = DepthProForDepthEstimation(config)
  • 也可以在构造模型时直接传参,此时会覆盖 config 中的值
from transformers import DepthProConfig, DepthProForDepthEstimation

config = DepthProConfig()
model = DepthProForDepthEstimation(config, use_fov_model=True)

当前推理态约束

需要注意:本仓库实现的 DepthProForDepthEstimation.forward 目前只支持推理。若向 forward 传入 labels(真实深度图用于计算损失),会直接抛出 NotImplementedError("Training is not implemented yet")源码)。即当前版本不支持在 Transformers 内直接微调训练,仅提供加载预训练权重做零样本估计的能力。

用 SDPA 与半精度加速推理

DepthPro 的模型类声明了 _supports_sdpa = True源码),因此可无缝使用 PyTorch 原生的 scaled dot-product attention(SDPA) 算子。SDPA 是 torch.nn.functional.scaled_dot_product_attention 提供的融合注意力实现,会根据输入与硬件自动选择最优内核。

torch>=2.1.1 且存在可用实现时,SDPA 默认开启;也可以在 from_pretrained() 里显式指定 attn_implementation="sdpa"

from transformers import DepthProForDepthEstimation

model = DepthProForDepthEstimation.from_pretrained(
    "apple/DepthPro-hf", attn_implementation="sdpa", device_map="auto"
)

想获得最大加速,建议把模型加载为半精度(torch.float16torch.bfloat16)。模型文档给出了一组本地基准示例(A100-40GB、PyTorch 2.3.0、Ubuntu 22.04、float32google/vit-base-patch16-224),SDPA 相对 eager 模式在 batch size 1~8 时约有 1.17×~1.33× 的推理加速;不同模型、分辨率与硬件上的实际收益会有差异,DepthPro 这类高分辨率输入通常更能体现 SDPA 的显存与延迟优势。

扩展到其他子任务

模型文档与社区实践显示,DepthPro 不仅可用于深度估计:由于 patch 编码器能产出锐利、多尺度、含高频细节的特征,研究者已将其用于超分辨率与图像分割(模型文档 Resources 节 中列出的 depthpro-beyond-depth 代码即演示了这类用法)。因此可把 DepthProModel 当作通用特征提取主干,替换默认的深度头来适配新任务——配置项里 patch_model_config / image_model_config 通过 AutoModel API 加载,理论上也允许替换成其他 ViT 变体作主干。

测试与本地验证

仓库为 DepthPro 提供了配套测试,可作为理解与验证实现的参考:

  • test_modeling_depth_pro.pyDepthProModelTester 以小尺寸(如 image_size=64, patch_size=16)构造 DepthProConfig 做前向一致性检查,并通过 ModelTesterMixin 覆盖序列化、from_pretrained 加载、梯度检查点等通用行为;
  • test_image_processing_depth_pro.py:覆盖 DepthProImageProcessor 的预处理与 post_process_depth_estimation 后处理。

运行模型相关测试的通用方式(仓库根目录)为 python -m pytest tests/models/depth_pro/,慢速集成测试需联网加载 apple/DepthPro-hf 权重。

小结

DepthPro 把"多尺度 patch 编码 + 全局 image 编码 + DPT 式逐级融合"三条线索拧在一起,实现了零样本、带公制尺度、亚秒级的高分辨率单目深度估计,并附带单图 FOV/焦距估计能力。在你的 Transformers 应用中,记住三条实操要点即可顺畅上手:

  1. DepthProImageProcessor(1536×1536、先归一化后缩放)完成预处理,用 post_process_depth_estimation(..., target_sizes=...) 还原分辨率并得到 focal_length / field_of_view / predicted_depth
  2. apple/DepthPro-hf 自带 FOV 分支,若只关心深度可用 use_fov_model=False 加载以省算力;反之在 config 或构造参数里开启;
  3. 优先 torch>=2.1.1 + 半精度 + SDPA 以获得最佳推理性能;当前实现仅支持推理,labels 训练路径尚未开放。

想要继续深入,可在仓库中直接阅读 configuration_depth_pro.pymodeling_depth_pro.pyimage_processing_depth_pro.py 与权重转换脚本 convert_depth_pro_weights_to_hf.py

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391