Link to this sectionKITTI 深度数据集#
KITTI 数据集是一个真实的户外自动驾驶基准,由在卡尔斯鲁厄市及其周边地区移动的车辆采集。对于单目深度估计,真实深度是从 Velodyne HDL-64 LiDAR 扫描仪中获取的,并使用 Uhrig et al. 2017 的方法进行了稠密化处理。得到的深度图仍然是稀疏的,大约只有 16–20% 的像素带有有效的深度值。KITTI 是 YOLO26-Depth 预训练混合数据中唯一的真实户外远距离来源,也用作 KITTI Eigen 评估基准。
Link to this section主要特性#
- 真实的户外驾驶场景,深度跨度可达约 80 米,远超典型的室内范围。
- 从 Velodyne HDL-64 LiDAR 获取的深度真实值,并使用 Sparsity Invariant CNNs (Uhrig et al. 2017) 的方法进行了稠密化。
- 稀疏监督:每张图像中只有约 16–20% 的像素带有有效的深度值;无效像素在损失函数和指标计算中会被遮蔽。
- 立体图像对(左
image_02和右image_03)为训练提供了额外的视点。 - 深度值以米为单位存储为
.npyfloat32 数组,遵循 Ultralytics 深度数据集格式。
Link to this section数据集结构#
Ultralytics 使用的 KITTI 深度数据分为两个子集:
- 训练集:60,040 张图像(左
image_02和右image_03)。为了确保评估公平,排除了 28 个 KITTI Eigen 测试驱动序列。 - 评估集:KITTI Eigen 测试集,包含 32,378 张图像(两台摄像机)。评估使用了 Garg 裁剪、80 米深度上限以及预测值与真实值之间的对数最小二乘对齐。
深度范围达到约 80 米,数据集 YAML (depth-kitti.yaml) 相应地设置了 max_depth: 80。
Link to this section在 YOLO26-Depth 中的作用#
KITTI 提供了 YOLO26-Depth 预训练混合中唯一的真实户外、远距离监督,补充了以室内为主的数据来源。它也是用于报告驾驶场景深度精度的标准 KITTI Eigen 基准。
KITTI is a key example of why the depth head is unbounded (log mode): a fixed 10 m output ceiling cannot represent 80 m driving scenes. See the depth task page for details on the head output range and max_depth handling.
Link to this section结果#
按模型大小划分的 KITTI Eigen delta1 精度(越高越好):
| 模型 | KITTI Eigen δ1 |
|---|---|
| YOLO26n-Depth | 0.888 |
| YOLO26s-Depth | 0.882 |
| YOLO26m-Depth | 0.924 |
| YOLO26l-Depth | 0.927 |
| YOLO26x-Depth | 0.939 |
Link to this section数据集 YAML#
YAML (Yet Another Markup Language) 文件用于定义数据集配置。它包含关于数据集路径、类别以及最大深度等其他相关信息。
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
# KITTI dataset for monocular depth estimation — real outdoor driving, Velodyne HDL-64 LiDAR (densified), sparse, up to ~80 m
# Documentation: https://docs.ultralytics.com/datasets/depth/kitti
# Example usage: yolo depth train data=depth-kitti.yaml model=yolo26n-depth.pt
# parent
# ├── ultralytics
# └── datasets
# └── depth-kitti ← downloads here (~190 GB archives, ~230 GB converted)
# ├── images/{train,val} # RGB images
# └── depth/{train,val} # paired *.npy, float32 meters (images/ -> depth/)
# If an interrupted download leaves a partial dataset, delete the depth-kitti dir and re-run to rebuild it.
path: depth-kitti # dataset root dir (relative to Ultralytics settings 'datasets_dir')
train: images/train # train images (relative to 'path') 60040 images
val: images/val # val images (relative to 'path') 32378 images (KITTI Eigen test split)
max_depth: 80 # (m) maximum valid depth; GT beyond this is excluded from val metrics
nc: 1
names:
0: depth
channels: 3
# Download script/URL (optional)
download: |
import shutil
from pathlib import Path
import cv2
import numpy as np
from ultralytics.utils import TQDM
from ultralytics.utils.downloads import download
# Drives of the 28 KITTI Eigen test scenes -> val; every other annotated drive -> train
VAL_DRIVES = """2011_09_26_drive_0002 2011_09_26_drive_0009 2011_09_26_drive_0013 2011_09_26_drive_0020
2011_09_26_drive_0023 2011_09_26_drive_0027 2011_09_26_drive_0029 2011_09_26_drive_0036 2011_09_26_drive_0046
2011_09_26_drive_0048 2011_09_26_drive_0052 2011_09_26_drive_0056 2011_09_26_drive_0059 2011_09_26_drive_0064
2011_09_26_drive_0084 2011_09_26_drive_0086 2011_09_26_drive_0093 2011_09_26_drive_0096 2011_09_26_drive_0101
2011_09_26_drive_0106 2011_09_26_drive_0117 2011_09_28_drive_0002 2011_09_29_drive_0026 2011_09_29_drive_0071
2011_09_30_drive_0016 2011_10_03_drive_0034 2011_10_03_drive_0042 2011_10_03_drive_0047""".split()
# Annotated drives excluded from the release training set (raw data was unavailable at build time)
SKIP_DRIVES = {"2011_09_28_drive_0104", "2011_09_28_drive_0135", "2011_09_28_drive_0177", "2011_09_28_drive_0214"}
# Download the improved sparse GT (~14 GB) and the raw recordings it covers (~175 GB)
dir = Path(yaml["path"]) # dataset root dir
base = "https://s3.eu-central-1.amazonaws.com/avg-kitti"
download([f"{base}/data_depth_annotated.zip"], dir=dir / "source", delete=True, exist_ok=True)
gt_drives = sorted(p for p in (dir / "source" / "data_depth_annotated").glob("*/*_sync") if p.name[:-5] not in SKIP_DRIVES)
urls = [f"{base}/raw_data/{p.name[:-5]}/{p.name}.zip" for p in gt_drives]
download(urls, dir=dir / "source" / "raw", delete=True, exist_ok=True, threads=4)
# Convert: GT PNGs are uint16 meters*256; RGB frames come from the matching raw drive
for split in ("train", "val"):
(dir / "images" / split).mkdir(parents=True, exist_ok=True)
(dir / "depth" / split).mkdir(parents=True, exist_ok=True)
for gt in TQDM(gt_drives, desc="Converting"):
drive = gt.name[:-5] # 2011_09_26_drive_0002
split = "val" if drive in VAL_DRIVES else "train"
for cam in ("image_02", "image_03"):
for png in sorted((gt / "proj_depth" / "groundtruth" / cam).glob("*.png")):
name = f"{drive}_{cam[-2:]}_{png.stem}"
depth = cv2.imread(str(png), cv2.IMREAD_ANYDEPTH).astype(np.float32) / 256.0
np.save(dir / "depth" / split / f"{name}.npy", depth)
raw = dir / "source" / "raw" / drive[:10] / gt.name / cam / "data" / png.name
raw.replace(dir / "images" / split / f"{name}.png")
shutil.rmtree(dir / "source")Link to this section用法#
要通过 KITTI 数据集训练 100 个 epochs 的 YOLO26n-Depth 模型,你可以使用以下代码片段。有关可用参数的完整列表,请参考模型 Training 页面。
from ultralytics import YOLO
# Load a pretrained depth model
model = YOLO("yolo26n-depth.pt")
# Train the model on KITTI
results = model.train(data="depth-kitti.yaml", epochs=100, imgsz=640)Link to this section预训练模型#
预训练的 YOLO26-Depth 模型在首次按名称引用时会从 Ultralytics v8.4.0 资产发布 自动下载:
Link to this section引用与致谢#
如果你在研究或开发工作中使用了 KITTI 数据集,请引用以下论文:
@article{geiger2013vision,
title={Vision meets Robotics: The KITTI Dataset},
author={Geiger, Andreas and Lenz, Philip and Stiller, Christoph and Urtasun, Raquel},
journal={The International Journal of Robotics Research},
year={2013},
publisher={SAGE Publications}
}
@inproceedings{uhrig2017sparsity,
title={Sparsity Invariant CNNs},
author={Uhrig, Jonas and Schneider, Nick and Schneider, Lukas and Franke, Uwe and Brox, Thomas and Geiger, Andreas},
booktitle={International Conference on 3D Vision (3DV)},
year={2017}
}我们衷心感谢卡尔斯鲁厄理工学院和芝加哥丰田技术学院创建并维护 KITTI 数据集,同时也感谢 Uhrig 等人提出的深度稠密化方法,该方法使得稠密监督成为可能。