Link to this sectionVirtual KITTI 2 Depth Dataset#
Virtual KITTI 2 (vKITTI2) is a photorealistic synthetic recreation of the KITTI driving scenes. It clones 5 sequences from the original KITTI dataset and re-renders them under varied weather and lighting conditions, providing dense per-pixel ground truth.
As a synthetic outdoor-driving dataset, vKITTI2 offers a dense counterpart to the sparse real KITTI LiDAR returns, making it a useful source of clean outdoor driving geometry for training monocular depth estimation models.
Link to this sectionKey Features#
- Photorealistic synthetic recreation of KITTI driving scenes.
- 5 cloned sequences rendered under varied weather and lighting.
- Outdoor driving environments.
- Dense per-pixel ground truth (a dense counterpart to the sparse real KITTI LiDAR).
- Depth range ~80 m.
- Contributes 42,520 images (25,780 train / 16,740 val) to the Ultralytics depth training mix.
Link to this sectionDataset Structure#
The Virtual KITTI 2 depth dataset is split into two subsets:
- Train: 25,780 images with paired dense depth maps for training.
- Val: 16,740 images with paired dense depth maps for validation during training.
Each RGB image is paired with a .npy float32 depth map storing per-pixel distances in meters, following the Ultralytics depth dataset format.
Link to this sectionRole in YOLO26-Depth#
Virtual KITTI 2 is one of the training sources in the broad multi-dataset mixture (~2.19M images) used to pretrain the Ultralytics YOLO26-Depth models. Within this mix, vKITTI2 provides a dense synthetic outdoor-driving counterpart to the sparse real KITTI LiDAR ground truth.
There is no standalone held-out vKITTI2 benchmark in this setup. Instead, the resulting models are evaluated on the standard monocular depth benchmarks: NYU Depth V2, KITTI, Make3D, ETH3D, and iBims-1.
Link to this sectionDataset YAML#
A YAML (Yet Another Markup Language) file is used to define the dataset configuration. It contains information about the dataset's paths, classes, and other relevant information. For Virtual KITTI 2, the depth-vkitti2.yaml file defines the paths and the single depth class.
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
# Virtual KITTI 2 dataset for monocular depth estimation — photorealistic synthetic outdoor driving, dense per-pixel depth
# Documentation: https://docs.ultralytics.com/datasets/depth/vkitti2
# Example usage: yolo depth train data=depth-vkitti2.yaml model=yolo26n-depth.pt
# parent
# ├── ultralytics
# └── datasets
# └── depth-vkitti2 ← downloads here (15 GB archives, ~85 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-vkitti2 dir and re-run to rebuild it.
path: depth-vkitti2 # dataset root dir (relative to Ultralytics settings 'datasets_dir')
train: images/train # train images (relative to 'path') 25780 images
val: images/val # val images (relative to 'path') 16740 images
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
# Download and extract the official RGB + depth tars (~15 GB), then convert: Scene20 -> val, all
# other scenes -> train; depth PNGs are uint16 centimeters (sky = 655.35 m), clipped at 80 m
dir = Path(yaml["path"]) # dataset root dir
urls = [f"https://download.europe.naverlabs.com/virtual_kitti_2.0.3/vkitti_2.0.3_{s}.tar" for s in ("rgb", "depth")]
download(urls, dir=dir / "source", delete=True)
for split in ("train", "val"):
(dir / "images" / split).mkdir(parents=True, exist_ok=True)
(dir / "depth" / split).mkdir(parents=True, exist_ok=True)
for im in TQDM(sorted((dir / "source").rglob("rgb_*.jpg")), desc="Converting"):
scene, variation, camera = im.parts[-6], im.parts[-5], im.parts[-2] # Scene01/clone/frames/rgb/Camera_0/rgb_00000.jpg
split = "val" if scene == "Scene20" else "train"
name = f"{scene}_{variation}_{camera}_{im.stem[4:]}"
depth = cv2.imread(str(im.parents[2] / "depth" / camera / f"depth_{im.stem[4:]}.png"), cv2.IMREAD_ANYDEPTH)
np.save(dir / "depth" / split / f"{name}.npy", (depth.astype(np.float32) / 100.0).clip(max=80)) # cm -> m
im.replace(dir / "images" / split / f"{name}.jpg")
shutil.rmtree(dir / "source")Link to this sectionUsage#
To train a YOLO26n-Depth model on the Virtual KITTI 2 dataset with an image size of 640, you can use the following code snippets. For a comprehensive list of available arguments, refer to the model Training page.
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n-depth.pt") # load a pretrained model (recommended for training)
# Train the model
results = model.train(data="depth-vkitti2.yaml", epochs=100, imgsz=640)Link to this sectionPretrained Models#
The YOLO26 depth family (yolo26n-depth.pt, yolo26s-depth.pt, yolo26m-depth.pt, yolo26l-depth.pt, yolo26x-depth.pt) auto-downloads from the v8.4.0 release and is trained on the broad multi-dataset mix that Virtual KITTI 2 is part of.
Link to this sectionCitations and Acknowledgments#
If you use the Virtual KITTI 2 dataset in your research or development work, please cite the following paper:
@article{cabon2020vkitti2,
title={Virtual KITTI 2},
author={Yohann Cabon and Naila Murray and Martin Humenberger},
journal={arXiv preprint arXiv:2001.10773},
year={2020}
}We would like to acknowledge the creators of Virtual KITTI 2 for making this synthetic driving dataset available to the computer vision community.