单目深度估计#
单目深度估计从单张 RGB 图像预测逐像素深度图。每个输出像素包含一个以米为单位的深度值,表示从相机到该表面点的估计距离。
深度模型的输出是一个与输入图像对齐的、形状为 (H, W) 的密集浮点地图。这种逐像素的表示方式使单目深度估计非常适合用于 3D 场景重建、机器人导航、AR/VR 内容创作以及任何需要从单个相机获取空间布局的应用。
使用 task=depth 或 yolo depth CLI 任务进行单目深度估计。YOLO26 深度模型文件使用 -depth 后缀,例如 yolo26n-depth.pt。
Watch: Monocular Depth Estimation with Ultralytics YOLO26 | Python Tutorial | Vision AI 🚀
模型#
在广泛的多数据集组合(室内 + 室外,~219 万张图像)上预训练的 YOLO26 深度模型如下所示。指标列基于 NYU Depth V2 Eigen 测试集划分报告。
模型会在首次使用时从最新的 Ultralytics 发布版本中自动下载。
| 模型 | 尺寸 (像素) | delta1NYU | abs_relNYU | rmseNYU | 速度 CPU ONNX (ms) | 速度 T4 TensorRT10 (ms) | 参数量 (M) | FLOPs (B) |
|---|---|---|---|---|---|---|---|---|
| YOLO26n-depth | 768 | 0.882 | 0.109 | 0.414 | 272.0 ± 27.2 | 2.7 ± 0.1 | 6.4 | 46.9 |
| YOLO26s-depth | 768 | 0.896 | 0.104 | 0.399 | 393.7 ± 13.1 | 3.8 ± 0.0 | 13.2 | 67.9 |
| YOLO26m-depth | 768 | 0.921 | 0.089 | 0.364 | 621.5 ± 49.7 | 6.0 ± 0.1 | 23.3 | 130.7 |
| YOLO26l-depth | 768 | 0.930 | 0.083 | 0.351 | 821.9 ± 50.7 | 7.7 ± 0.1 | 27.7 | 157.2 |
| YOLO26x-depth | 768 | 0.933 | 0.080 | 0.344 | 1240.9 ± 73.3 | 13.6 ± 0.2 | 57.0 | 302.0 |
- delta1NYU 是在 NYU Depth V2 Eigen 测试集(654 张图像)上,使用多尺度 + 水平翻转 TTA 和对数最小二乘对齐后,预测深度与真实值误差在 1.25 倍以内的像素百分比。
- 在不使用 TTA 的情况下,单尺度准确率可通过
yolo depth val model=yolo26n-depth.pt data=nyu-depth.yaml imgsz=768 device=0(各尺寸请相应替换为model=)进行复现,该方法采用中位数(仅尺度)对齐,得分较低:delta1 0.783 (n)、0.793 (s)、0.840 (m)、0.853 (l)、0.860 (x)。 - abs_rel 是预测深度值与真实深度值之间的平均绝对相对误差。
- rmse 是以米为单位的均方根误差。
- 速度是指在
imgsz=768、batch=1下仅推理的延迟(不含预处理/后处理),以热身后的计时运行的均值 ± 标准差报告。CPU ONNX 是在 32 核 Intel Xeon (Skylake) 上运行的 ONNX Runtime fp32;T4 TensorRT10 是在 Tesla T4 上运行的 TensorRT fp16。 - params 和 FLOPs 是在 768×768 分辨率(发布权重时的训练分辨率)下测量的。
与 Depth Anything V2 速度对比#
Depth Anything V2 是单目深度领域广泛使用的开源基准。其 DINOv2 视觉 Transformer 主干网络和 DPT 解码器计算量大,因此在配备 TensorRT fp16 的同一块 Tesla T4 上,已发布的最小 Depth Anything V2 模型比所有 YOLO26 深度模型(包括参数量超过两倍的 YOLO26x-depth)都要慢。
在 ~768 px 下——YOLO26 为 imgsz=768(其发布权重训练时的分辨率),Depth Anything V2 为 770 px(其 DINOv2 主干网络要求为 14 的补丁大小的倍数):
| 模型 | 参数量 (M) | FLOPs (B) | T4 TensorRT10 (ms) | FPS | 相比 V2 Small 加速比 | 相比 V2 Base 加速比 |
|---|---|---|---|---|---|---|
| Depth Anything V2 Base | 97.5 | 1025.5 | 55.40 | 18.1 | — | — |
| Depth Anything V2 Small | 24.8 | 346.9 | 20.99 | 47.6 | — | — |
| YOLO26x-depth | 57.0 | 302.0 | 13.57 | 73.7 | 1.5× | 4.1× |
| YOLO26l-depth | 27.7 | 157.2 | 7.68 | 130.2 | 2.7× | 7.2× |
| YOLO26m-depth | 23.3 | 130.7 | 6.00 | 166.7 | 3.5× | 9.2× |
| YOLO26s-depth | 13.2 | 67.9 | 3.82 | 261.6 | 5.5× | 14.5× |
| YOLO26n-depth | 6.4 | 46.9 | 2.73 | 365.8 | 7.7× | 20.3× |
在 ~640 px 下——分别为 imgsz=640 和 644 px——顺序保持不变,YOLO26n-depth 比 Depth Anything V2 Small 快 5.9 倍:
| 模型 | T4 TensorRT10 (ms) | FPS |
|---|---|---|
| Depth Anything V2 Base | 35.10 | 28.5 |
| Depth Anything V2 Small | 13.62 | 73.4 |
| YOLO26x-depth | 10.26 | 97.5 |
| YOLO26l-depth | 6.14 | 162.8 |
| YOLO26m-depth | 4.71 | 212.1 |
| YOLO26s-depth | 3.08 | 324.4 |
| YOLO26n-depth | 2.29 | 436.9 |
- 延迟为仅推理,
batch=1,Tesla T4 上的 TensorRT fp16——与上方模型表格相同的测试框架,此处显示两位小数;FPS 是未四舍五入延迟的倒数。加速比列将 Depth Anything V2 Small (20.99 毫秒) 和 Base (55.40 毫秒) 的延迟除以 YOLO26 的延迟。 - Depth Anything V2 Small 和 Base 为已发布的 ViT-S 和 ViT-B 检查点。
- 该对比仅涵盖延迟——两个模型系列在此处未在统一的准确率协议下进行评估。
深度范围和对数深度头 (log-depth head)#
深度头预测 exp(logit)——无界(~0.02–150 米)——并且将场景形状与绝对尺度解耦:网络预测相对对数深度场,绝对米数由评估时恢复的独立双参数变换(exp(a·log d + b))、轻量级校准或微调来设定。常见的替代方案是有界的 sigmoid × max_depth 头,它在架构中固定了一个上限,因此任何超过 max_depth 的深度都会被裁剪——这阻碍了对更远场景的训练和预测。
为什么深度头需要无界:跨深度范围的证据#
受控 A/B 测试 — 相同数据、相同计划,仅深度头不同。 在完全相同的室内 (≤10 米) 和室外 (≤80 米) 数据混合上从头开始训练两个深度头:
| 检测头 | 输出范围 | 混合范围验证 δ1 | 训练表现 |
|---|---|---|---|
sigmoid × max_depth (10 米) | 有界 0–10 米 | 0.221 | 在第 1 个 epoch 时达到平稳 |
log (无界) | 0–~150 m | 0.367 (+66%) | 持续改善 |
有界头无法表示占比超过 10 米的绝大多数室外像素,因此它几乎立即停止改进;log 头则从全范围中学习。
它修复的故障模式 — 单数据集微调,按范围分层。 在单个数据集上微调有界 (10 米) 头时,当数据符合上限时有效,超出上限时则会崩溃:
| 数据集 | 深度范围 | 有界头 δ1 |
|---|---|---|
| SUN RGB-D | ≤10 m | 0.78 ✅ |
| Hypersim | 大部分 ≤10 米 | 0.74 ✅ |
| KITTI | ~80 m | 0.08 ❌ (abs_rel ≈ 7.0 — 80/10 尺度不匹配) |
| vKITTI2 | 80 m | 0.04 ❌ |
坍塌刚好发生在上限边界处。log 头没有这样的边界。
发布的模型 —— 跨范围性能。 交付的 log 头系列模型,在跨越 10 米(NYU、iBims-1)到 80 米(KITTI)的基准上进行了评估,使用尺度对齐的 δ1:
| 基准测试 | 范围 | YOLO26x-depth (log) | 之前的有界版本 |
|---|---|---|---|
| NYU Eigen | 10 m | 0.933 | 0.934 |
| iBims-1 | 10 m | 0.961 | 0.945 |
| ETH3D | ~60 m | 0.959 | 0.931 |
| Make3D | ~70 m | 0.302 | 0.296 |
| KITTI Eigen | 80 m | 0.942 | 0.891 |
| 平均值 | — | 0.819 | 0.799 |
这两列都是按原样发布的。其余行均使用其数据集页面上描述的 TTA 和对数最小二乘协议进行评分,该协议本仓库中的验证器并未实现,因此无法在相同的基础上重新测量 KITTI 行;KITTI page 包含基于经典的 652 帧 Eigen 划分所测得的数值。
最大的收益体现在更长范围的室外基准测试(KITTI, ETH3D)中——这正是 10 米固定上限影响最大的地方——同时保持了室内性能。
训练#
在 Depth8 数据集上以图像大小 640 训练 YOLO26n-depth 100 个轮次。有关可用参数的完整列表,请参见配置页面。
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n-depth.yaml") # build a new model from YAML
model = YOLO("yolo26n-depth.pt") # load a pretrained model (recommended for training)
model = YOLO("yolo26n-depth.yaml").load("yolo26n-depth.pt") # build from YAML and transfer weights
# Train the model
results = model.train(data="depth8.yaml", epochs=100, imgsz=640)查看完整的 train 模式详情,请参阅Train页面。
在你的自定义数据上进行微调#
当将预训练的深度模型适应到自定义数据集时,请降低学习率并使用 AdamW 优化器。默认的优化器设置是为从头开始训练(使用 lr0=0.01 的 SGD)而调优的;如果将其应用于已经收敛的深度模型,可能会覆盖预训练知识并导致结果变差——在单个领域上微调时尤其如此。
from ultralytics import YOLO
model = YOLO("yolo26s-depth.pt") # start from pretrained weights
model.train(
data="path/to/your_dataset.yaml",
epochs=20,
imgsz=640,
optimizer="AdamW",
lr0=1e-4, # ~100x below the from-scratch default
warmup_bias_lr=1e-4, # keep warmup gentle too
)额外建议:
- 数据增强由标准参数控制(
degrees、translate、scale、shear、perspective、flipud、fliplr、hsv_h、hsv_s、hsv_v);几何变形和翻转会以相同的方式应用到配对的深度图上。要查看用于发布的 YOLO26-Depth 权重的确切方案,请检查存储在检查点中的train_args——参见检查 YOLO26 检查点训练参数。 mosaic、mixup、cutmix和copy_paste未针对深度实现。 深度数据集加载器会自动将这些概率设置为 0,因此传递它们没有任何效果。这些数据增强不受支持,因为它们结合了多张图像,这会产生无效的配对深度图。- 任何深度范围开箱即用。
log头模型预测无界深度,因此它们无需更改即可适应短距离(微距)或长距离(室外/驾驶)数据。在你的数据集 YAML 中设置max_depth:(以米为单位)来限制哪些 GT 像素计入验证指标。 - 保持通用性能。 如果你需要模型在训练集之外的场景中保持准确,请在训练数据中混入一小部分(约 5–10%)多样化的通用图像;这能显著减少微调过程中的遗忘。
- 仅在你的领域差异很大且拥有大型数据集时才从头开始训练(
model=yolo26s-depth.yaml)——此时默认的 SGDlr0=0.01是合适的,因为没有需要保留的预训练权重。
校准深度尺度#
深度头将形状(相对场景结构)与尺度(绝对米数)分开。如果模型在你的场景上已经输出了良好的相对深度,但绝对值对你的相机来说不准,你可以在几秒钟内用 model.calibrate() 校正尺度——这是对一小批带标签的数据集进行双参数对数仿射的闭式拟合,没有梯度训练,也没有对网络权重进行任何更改,因此它不会损害相对结构。
from ultralytics import YOLO
model = YOLO("yolo26s-depth.pt")
# Fit scale on a labeled split (~100+ images is enough), then persist it
model.calibrate(data="path/to/your_dataset.yaml")
model.save("yolo26s-depth-calibrated.pt")校准需要真值深度来进行拟合,因此它在带标签的分割上运行——它无法在盲推理中进行。它在验证指标评估的相同像素上进行拟合和评分:排除数据集 YAML 的 max_depth(默认 100 米)处及更远的 GT。当相对深度已经很好且只有尺度/范围错误时使用它;如果相对结构本身需要针对你的领域进行更改,请改用微调。
训练会自动为你完成此操作:在 model.train(...) 完成后,最佳和最后的检查点会在验证集上进行校准,以便它们开箱即用地产出带度量尺度的深度。
发布的 yolo26*-depth.pt 检查点自带此校准,在预训练验证组合上进行了拟合。这是跨所有领域的单一全局尺度,因此要在特定相机或场景类型上获得最准确的绝对深度,请在你自己数据的少数字段分割上运行 model.calibrate()——它会替换内置的拟合。
数据集格式#
深度估计数据集将每个 RGB 图像与相应的深度文件配对。深度目标存储为包含米制 float32 值的 .npy 数组。数据集 YAML 指向一个 images/ 目录;加载器通过将路径中的 images 组件替换为 depth 并将图像扩展名替换为 .npy 来推导深度文件路径。
dataset/
├── images/
│ ├── train/
│ └── val/
└── depth/
├── train/
└── val/例如,位于 images/train/scene_001.jpg 的图像与位于 depth/train/scene_001.npy 的深度图配对。有关完整的格式规范,请参阅深度估计数据集指南。
验证#
在深度估计数据集上验证已训练的 YOLO26n-depth 模型准确率。显式传递 data,以便验证使用预期的数据集 YAML。发布的权重是在 imgsz=768 下训练的,因此请在该尺寸下进行验证和预测以获得最佳准确率。
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n-depth.pt") # load an official model
model = YOLO("path/to/best.pt") # load a custom model
# Validate the model
metrics = model.val(data="nyu-depth.yaml")
metrics.delta1 # percentage of pixels within threshold δ=1.25
metrics.abs_rel # mean absolute relative error
metrics.rmse # root mean squared error (meters)
metrics.silog # scale-invariant logarithmic error预测#
使用已训练的 YOLO26n-depth 模型对图像进行预测。
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n-depth.pt") # load an official model
model = YOLO("path/to/best.pt") # load a custom model
# Predict with the model
results = model("https://ultralytics.com/images/bus.jpg") # predict on an image
# Access the results
for result in results:
depth_map = result.depth.data.cpu().numpy() # torch.Tensor -> NumPy float32, shape (H, W), meters查看完整的 predict 模式详情,请访问 Predict 页面。
结果输出#
YOLO 深度估计为每张图像返回一个 Results 对象。每个结果为整张图像存储一个稠密的浮点深度图。
| 属性 | 类型 | 形状 | 描述 |
|---|---|---|---|
result.depth | DepthMap | (H,W) | 逐像素的稠密深度图。 |
result.depth.data | torch.Tensor | (H,W) | 深度值以米为单位;调用 .cpu().numpy() 获取 NumPy。 |
result.boxes | - | - | 无实例框。 |
result.masks | - | - | 无实例掩膜。 |
有关所有任务特定于任务的 Results 字段,请参阅按任务划分的预测结果部分。
给深度图着色#
原始深度图是一个单通道浮点数数组,单位为米 —— 适合计算,但很难直接阅读。要将其转换为彩色图像,请使用 ultralytics.utils.plotting 中的 colorize_depth 辅助函数,它将 (H, W) 深度数组映射为 (H, W, 3) BGR uint8 图像(无效像素 <= 0 渲染为黑色)。
result.plot() 已经使用默认值(cmap="jet"、mode="disparity")将这种着色与输入图像进行了混合;当你想要一个独立的彩色深度图像或不同的色彩映射或归一化时,直接调用 colorize_depth。
import cv2
from ultralytics import YOLO
from ultralytics.utils.plotting import colorize_depth
model = YOLO("yolo26n-depth.pt")
result = model("https://ultralytics.com/images/bus.jpg")[0]
depth = result.depth.data.cpu().numpy() # (H, W) float32, meters
# Colorize with near = warm and save
cv2.imwrite("depth_colored.png", colorize_depth(depth, cmap="spectral")) # (H, W, 3) BGR uint8
# Fix the range to 0-20 m so the same color means the same distance across frames
cv2.imwrite("depth_metric.png", colorize_depth(depth, vmin=0.0, vmax=20.0, cmap="inferno", mode="metric"))
# Blended overlay straight from the Results object (uses cmap="jet", mode="disparity")
result.save("depth_overlay.png")每种色彩映射的运行方式都是冷色/暗色 → 暖色/亮色。mode 决定哪一端是近端,vmin/vmax 跨帧锁定范围,使某种颜色始终代表相同的距离。
| 参数 | 值 | 描述 |
|---|---|---|
cmap | jet (默认) | 高对比度蓝 → 绿 → 红,即 result.plot() 使用的调色板。 |
cmap | inferno | 黑 → 紫 → 橙 → 黄。感知均匀、对色觉障碍友好、在灰度下清晰可读。 |
cmap | spectral | 红 → 黄 → 绿 → 蓝 (matplotlib Spectral_r)。 |
mode | disparity (默认) | 在第 2 百分位数和第 98 百分位数之间对逆深度(1/d)进行归一化;暖色标记的近处和远处异常值会被吸收。 |
mode | metric | 在 vmin 和 vmax 之间以米为单位线性归一化深度;暖色标记远方,因此颜色会追踪真实距离。 |
导出#
将 YOLO26n-depth 模型导出为 ONNX、CoreML 等其他格式。
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n-depth.pt") # load an official model
model = YOLO("path/to/best.pt") # load a custom model
# Export the model
model.export(format="onnx")可用的 YOLO26 深度估计导出格式在下表中。你可以使用 format 参数导出为任何格式,例如 format='onnx' 或 format='engine'。你可以直接对导出的模型进行预测或验证,例如 yolo predict model=yolo26n-depth.onnx。导出完成后,将为你的模型显示使用示例。
| 格式 | format 参数 | 模型 | 元数据 | 参数 |
|---|---|---|---|---|
| PyTorch | - | yolo26n-depth.pt | ✅ | - |
| TorchScript | torchscript | yolo26n-depth.torchscript | ✅ | imgsz, quantize, dynamic, nms, batch, device |
| ONNX | onnx | yolo26n-depth.onnx | ✅ | imgsz, quantize, dynamic, simplify, opset, nms, batch, data, fraction, device |
| OpenVINO | openvino | yolo26n-depth_openvino_model/ | ✅ | imgsz, quantize, dynamic, nms, batch, data, fraction, device |
| TensorRT | engine | yolo26n-depth.engine | ✅ | imgsz, quantize, dynamic, simplify, opset, workspace, nms, batch, data, fraction, device |
| CoreML | coreml | yolo26n-depth.mlpackage | ✅ | imgsz, dynamic, quantize, nms, batch, device |
| TF SavedModel | saved_model | yolo26n-depth_saved_model/ | ✅ | imgsz, keras, quantize, opset, nms, batch, data, fraction, device |
| TF GraphDef | pb | yolo26n-depth.pb | ❌ | imgsz, opset, batch, device |
| TF Edge TPU | edgetpu | yolo26n-depth_edgetpu.tflite | ✅ | imgsz, quantize, opset, data, fraction, device |
| PaddlePaddle | paddle | yolo26n-depth_paddle_model/ | ✅ | imgsz, batch, device |
| MNN | mnn | yolo26n-depth.mnn | ✅ | imgsz, batch, dynamic, quantize, simplify, opset, nms, device |
| NCNN | ncnn | yolo26n-depth_ncnn_model/ | ✅ | imgsz, quantize, batch, device |
| IMX500 | imx | yolo26n-depth_imx_model/ | ✅ | imgsz, quantize, data, fraction, nms, device |
| RKNN | rknn | yolo26n-depth_rknn_model/ | ✅ | imgsz, batch, name, quantize, simplify, opset, data, fraction, device |
| ExecuTorch | executorch | yolo26n-depth_executorch_model/ | ✅ | imgsz, batch, device |
| Axelera | axelera | yolo26n-depth_axelera_model/ | ✅ | imgsz, batch, quantize, data, fraction, device |
| DEEPX | deepx | yolo26n-depth_deepx_model/ | ✅ | imgsz, quantize, simplify, opset, data, optimize, device |
| Qualcomm QNN | qnn | yolo26n-depth_qnn.onnx | ✅ | imgsz, batch, name, quantize, simplify, opset, data, fraction, device |
| LiteRT | litert | yolo26n-depth.tflite | ✅ | imgsz, quantize, batch, data, fraction, device |
| Hailo | hailo | yolo26n-depth_hailo_model/ | ✅ | imgsz, name, quantize, data, fraction, simplify, conf, iou |
| Huawei Ascend | ascend | yolo26n-depth_ascend_model/ | ✅ | imgsz, batch, name, quantize, opset, simplify, nms |
查看完整的 export 详情,请访问 Export 页面。
常见问题解答#
准备配对的 RGB 图像和
.npy深度文件,然后创建一个指向你的images/目录的数据集 YAML。加载器通过将路径中的images替换为depth并将图像扩展名交换为.npy来自动查找深度文件。从预训练权重开始,并结合 AdamW 使用较低的学习率,以便微调能够保留模型已知的内容(参见在自己的数据上微调了解原因):
示例from ultralytics import YOLO # Load a pretrained YOLO26 depth model model = YOLO("yolo26s-depth.pt") # Fine-tune on a custom depth dataset results = model.train( data="path/to/your_dataset.yaml", epochs=20, imgsz=640, optimizer="AdamW", lr0=1e-4, warmup_bias_lr=1e-4, )查看配置页面以获取更多可用参数。
深度估计验证会报告 Depth Anything 及相关单目深度任务所使用的指标集:
- delta1 / delta2 / delta3 — 预测深度与真实深度(或其倒数)的比值小于 1.25、1.25² 和 1.25³ 的像素百分比。数值越高越好。
- abs_rel — 平均绝对相对误差。数值越低越好。
- rmse — 以米为单位的均方根误差。数值越低越好。
- silog — 尺度不变对数误差。数值越低越好。
每个预测在每张图像中都与真实标签按中位数对齐,每个指标都在该图像上最终确定,然后将这些单张图像的结果在验证集上求平均,因此无论每张图像包含多少个有效的深度像素,每张图像的权重都相同。少于 10 个有效真实标签像素的图像会被跳过,不计入该平均值,因为对少数像素进行中位数对齐是没有意义的;非有限预测则改为在深度边界处进行评分。这与 Depth Anything V2 使用的单样本平均和 10 像素下限相匹配。
深度图存储为
torch.Tensor,其形状为(H, W),其中每个值都是以米为单位的预测深度(使用result.depth.data.cpu().numpy()获取 NumPyfloat32数组)。在运行预测后,通过result.depth.data访问它。该图与输入图像分辨率对齐。Ultralytics YOLO26 为多个深度估计数据集提供内置的数据集 YAML 配置,包括 NYU Depth V2、KITTI、Hypersim、SUN RGB-D 和 ARKitScenes。有关完整列表和格式详细信息,请参阅深度估计数据集指南。
通过提供用于评估的数据集 YAML 文件来验证预训练的 YOLO26 深度模型:
示例from ultralytics import YOLO # Load a pretrained model model = YOLO("yolo26n-depth.pt") # Validate the model metrics = model.val(data="nyu-depth.yaml") print("delta1:", metrics.delta1) print("abs_rel:", metrics.abs_rel) print("rmse:", metrics.rmse)使用 Python 或 CLI 将 YOLO26 深度模型导出为 ONNX:
示例from ultralytics import YOLO # Load a pretrained model model = YOLO("yolo26n-depth.pt") # Export the model to ONNX format model.export(format="onnx")有关导出到各种格式的更多详情,请参考导出页面。