Skip to main content

KITTI Bounding Boxes

The KITTI dataset is a widely-used computer vision dataset for benchmarking and evaluating autonomous driving systems. Due to the popularity of this dataset, many researchers and developers have adopted its label format for their own datasets and applications. Encord Active enhances your experience by migrating such labels to the Encord format.

caution

The following approach only works for bounding boxes.

When running an importer, any previously imported predictions will be overwritten! To ensure the ability to revert to previous model iterations, it is important to version your projects.

If you possess KITTI predictions saved as TXT or CSV files, a utility function is available to import the predictions from those files, provided that each file is associated with a single image and its filename contains the data_hash of the related image.

The following file structure is required:

labels_root
├── labels
│   ├── aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee__whatever_you_may_need.txt
│   ├── ...
│   └── aaaaaaaa-bbbb-cccc-dddd-ffffffffffff__whatever_you_may_need.csv
└── ontology_label_map.json

That is, a root directory with two components:

  1. A subdirectory named "labels" that contains TXT/CSV files with filenames that begin with the data_hash followed by two underscores.
  2. A json file which maps class names to Encord ontology classes.

We cover these two components in detail below.

Label Files Format

The KITTI importer supports the label format described here with the addition of a column corresponding to the model confidence.

An example:

car 0.00 0 0.00 587.01 173.33 614.12 200.12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 97.85
cyclist 0.00 0 0.00 665.45 160.00 717.93 217.99 0.00 0.00 0.00 0.00 0.00 0.00 0.00 32.65
pedestrian 0.00 0 0.00 423.17 173.67 433.17 224.03 0.00 0.00 0.00 0.00 0.00 0.00 0.00 3.183

Columns are:

  • class_name: str
  • truncation: float ignored
  • occlusion: int ignored
  • alpha: float ignored
  • xmin: float
  • ymin: float
  • xmax: float
  • ymax: float
  • height: float ignored
  • width: float ignored
  • length: float ignored
  • location_x: float ignored
  • location_y: float ignored
  • location_z: float ignored
  • rotation_y: float ignored
  • confidence: float
note

The columns flagged as ignored have to appear in the label format but their values will be ignored.

The JSON Class Map

The JSON class map should follow a specific format where the keys should correspond to the featureNodeHash of the bounding box objects in the project ontology, and the values should correspond to their respective KITTI class names.

{
# featureNodeHash: class_name
"OTk2MzM3": "pedestrian",
"NzYyMjcx": "cyclist",
"Nzg2ODEx": "car"
}
info

To obtain a list of available featureNodeHashes for your project, you can use the following script:

import json

from encord_active.lib.project import ProjectFileStructure

fs = ProjectFileStructure("/path/to/your/project/root")
ontology = json.loads(fs.ontology.read_text())

print({o["featureNodeHash"]: o["name"] for o in ontology["objects"]})
# Example output:
# {'OTk2MzM3': 'Pedestrian', 'NzYyMjcx': 'Cyclist', 'Nzg2ODEx': 'Car'}

Importing the Predictions

Once you have a valid KITTI predictions folder, you can import the predictions into an Encord Active project running the following script:

import json
from pathlib import Path

from encord import EncordUserClient

from encord_active.lib.model_predictions.importers import import_KITTI_labels
from encord_active.lib.model_predictions.writer import PredictionWriter
from encord_active.lib.project import Project
from encord_active.lib.project.metadata import fetch_project_meta

project_path = Path("/path/to/your/project/root")
project_meta = fetch_project_meta(project_path)
private_key = Path(project_meta["ssh_key_path"]).read_text()

client = EncordUserClient.create_with_ssh_private_key(private_key)
encord_project = client.get_project(project_hash=project_meta["project_hash"])

predictions_root = Path("/path/to/your/predictions/root")
object_map = json.loads((predictions_root / "ontology_label_map.json").read_text())

with PredictionWriter(project=Project(project_path), custom_object_map=object_map) as writer:
import_KITTI_labels(encord_project, data_root=predictions_root, prediction_writer=writer)