Data format

How the dataset is laid out on disk and what each file contains, for reading it without the devkit.

The carlanomaly package reads all of this for you: it loads every modality as a PyTorch dataset, downloads the parts it needs and evaluates detectors at all four tiers. Install it with pip install git+https://github.com/carlanomaly/devkit; its documentation covers the full API. The rest of this page is for reading the files directly.

Directory structure

Scenarios are grouped by split and CARLA town (Town01–Town05, Town10HD). In the anomaly test split, scenarios are additionally grouped by anomaly type (e.g. change-weather, vanish-actor).

  • carlanomaly/
    • train/<town>/scenario-<n>/101 scenarios, 3,000 timesteps each
    • test/
      • normal/<town>/scenario-<n>/107 scenarios, 300 timesteps each
      • anomaly/<town>/<anomaly-type>/scenario-<n>/520 scenarios, 300 timesteps each

Inside a scenario

Every scenario-<n>/ contains the entries below. Files inside a scenario are numbered by timestep: rgb-front/000099.jpg is the front image at timestep 99. Tags show the download part that ships each entry and the splits it occurs in. Select a part to see what it adds.

Cameras

Front camera image
RGB
Instance segmentation mask of the same frame
Instance segmentation
Depth map of the same frame
Depth

Every pixel carries a semantic class and an instance ID. Since these annotations were generated in a simulation, they are exact.

Segmentation

Segmentation masks are RGBA PNGs named by timestep, e.g. segmentation-front/000099.png. The R channel holds the semantic class ID, the G and B channels the instance ID:

import numpy as np
from PIL import Image

img = np.asarray(Image.open("segmentation-front/000099.png"))
class_ids = img[:, :, 0]
instance_ids = img[:, :, 1].astype(np.int32) | (img[:, :, 2].astype(np.int32) << 8)
Semantic class IDs
IDClass
0Unlabeled
1Road
2Sidewalk
3Building
4Wall
5Fence
6Pole
7Traffic light
8Traffic sign
9Vegetation
10Terrain
11Sky
12Pedestrian
13Rider
14Car
15Truck
16Bus
17Train
18Motorcycle
19Bicycle
20Static
21Dynamic
22Other
23Water
24Road line
25Ground
26Bridge
27Rail track
28Guard rail

These are CARLA's semantic tags; the LiDAR uses the same IDs.

Depth

Depth maps are 8-bit grayscale PNGs named by timestep, e.g. depth-front/000099.png, in CARLA’s logarithmic encoding. They hold the distance along the camera’s viewing axis and convert to metres as follows:

depth = np.asarray(Image.open("depth-front/000099.png"), dtype=np.float32)
metres = 1000 * np.exp(5.70378 * (depth / 255 - 1))

The encoding covers 3.3 m to 1000 m, and each grey level spans about 2 % of the distance.

Semantic LiDAR

Point clouds for each timestep with per-point semantic class and instance labels. Instance IDs match those in the camera segmentation masks.

Loading point cloud…

Each file loads with pandas:

import pandas as pd
points = pd.read_feather("pointclouds/000000.feather")
ColumnContent
x, y, zPosition in metres in the sensor frame: x forward, y left, z up
cos_inc_angleCosine of the angle at which the laser ray hits the surface
object_idInstance ID, 0 for static map geometry
object_tagSemantic class ID (see the class table)

KITTI annotations

Every camera has a kitti-<camera>/ directory with 3D bounding boxes of the objects in its view, in the KITTI object format: label_2/ holds one label file per timestep and calib/ the camera calibration. extended/ contains the same boxes as feather tables, together with the simulator’s attributes of each object.

Anomaly annotations

Anomaly labels are provided at four levels of granularity, matching the evaluation tiers.

Sample level

For cameras, anomaly-<camera>/ holds one single-channel PNG per timestep, where 0 means normal and any other value means anomaly.

For LiDAR, anomaly-lidar/ holds one feather file per timestep with an anomaly column, one row per point of the matching point cloud.

Sensor level

anomaly-<sensor>/sensor.feather holds one row per timestep with an anomaly column.

Timestep level

A timestep is anomalous when any sensor reading at that point in time contains an anomaly. anomaly-observation.feather holds one row per timestep:

ColumnContent
anomalyTrue or False
tickCurrent timestep number
anomaly_obj_idsIDs of objects considered anomalous
anomaly_class_idsClass IDs of objects considered anomalous
metaMetadata

Scenario level

Scenario labels are given by the directory: everything under test/anomaly/ is anomalous.

Additional data

Each scenario also contains the following readings, one row per timestep unless noted:

FileColumns
imu.featheracceleration_x/y/z in m/s²; compass heading in radians; angular velocity in rad/s, stored as longitude_x/y/z
gnss.featherlatitude and longitude in degrees, altitude in metres
weather.featherCARLA’s 14 weather parameters, e.g. cloudiness, precipitation and fog_density (0–100), sun_altitude_angle and sun_azimuth_angle in degrees, fog_distance in metres
actions.featherframe, throttle and brake (0–1), steer (−1 to 1), hand_brake, reverse, manual_gear_shift, gear: the control command CARLA’s traffic manager applied after the timestep was recorded
collisions.featherOne row per collision, several per timestep possible: frame, ego_id, ego_type, other_id, other_type, normal_impulse_x/y/z and normal_impulse_norm

All of them load as pandas dataframes:

import pandas as pd
imu = pd.read_feather("imu.feather")