Implementation:CARLA simulator Carla Image Save To Disk
| Knowledge Sources | |
|---|---|
| Domains | Simulation, Perception |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
Concrete tool for saving sensor images to disk with optional color conversion and for accessing raw sensor data as numpy arrays provided by the CARLA simulator.
Description
Image.save_to_disk() writes a camera sensor's output to a file on disk in a standard image format (determined by the file extension). An optional ColorConverter argument transforms the raw sensor data before saving, enabling conversions such as depth buffer encoding to grayscale or semantic segmentation IDs to color palettes. For LiDAR data, LidarMeasurement.save_to_disk() writes a PLY-format point cloud file.
For in-memory processing, raw sensor data can be accessed as numpy arrays. Camera images provide a flat BGRA byte buffer via raw_data that can be reshaped to (height, width, 4). LiDAR measurements expose a structured array with shape (N, 4) for (x, y, z, intensity) via the same mechanism.
Usage
This method is called inside the data collection loop for each sensor frame that needs to be persisted to disk. It is typically the final step in the per-frame processing pipeline, after synchronization and any in-memory transformations.
Code Reference
Source Location
- Repository: CARLA
- File:
PythonAPI/carla/src/SensorData.cpp - Lines: Full file (Image, LidarMeasurement, RadarMeasurement data accessors and save methods)
Signature
Image.save_to_disk(path: str, color_converter: carla.ColorConverter = carla.ColorConverter.Raw) -> None
LidarMeasurement.save_to_disk(path: str) -> None
Import
import carla
import numpy as np
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| path | str | Yes | Output file path. The file format is determined by the extension (e.g., .png, .jpg, .ply). Directories must exist. |
| color_converter | carla.ColorConverter | No | Color conversion to apply before saving. Options: Raw (default, no conversion), Depth (depth buffer to grayscale), LogarithmicDepth (log-scaled depth), CityScapesPalette (semantic segmentation to color). Only applicable to Image objects. |
Outputs
| Name | Type | Description |
|---|---|---|
| (none) | None | The method writes the file to disk and returns None. Raises an exception if the path is invalid or the directory does not exist. |
Usage Examples
Basic Example
import carla
# Inside a sensor callback or after Queue.get()
def save_camera_data(image):
"""Save an RGB camera image to disk."""
image.save_to_disk(f'output/rgb/{image.frame:06d}.png')
def save_depth_data(image):
"""Save a depth camera image with logarithmic depth conversion."""
image.save_to_disk(
f'output/depth/{image.frame:06d}.png',
carla.ColorConverter.LogarithmicDepth
)
def save_segmentation_data(image):
"""Save a semantic segmentation image with CityScapes palette."""
image.save_to_disk(
f'output/semseg/{image.frame:06d}.png',
carla.ColorConverter.CityScapesPalette
)
Numpy Array Access and Processing
import carla
import numpy as np
import os
def process_rgb_image(image, output_dir='output/rgb'):
"""Convert RGB image to numpy array and save."""
os.makedirs(output_dir, exist_ok=True)
# Convert raw BGRA data to numpy array
array = np.frombuffer(image.raw_data, dtype=np.uint8)
array = array.reshape((image.height, image.width, 4)) # BGRA
# Convert BGRA to RGB (drop alpha, swap B and R)
rgb_array = array[:, :, :3][:, :, ::-1] # shape: (H, W, 3)
# Save using save_to_disk for convenience
image.save_to_disk(f'{output_dir}/{image.frame:06d}.png')
return rgb_array
def process_depth_image(image, output_dir='output/depth_raw'):
"""Decode depth image to metric depth array."""
os.makedirs(output_dir, exist_ok=True)
# Convert to numpy array
array = np.frombuffer(image.raw_data, dtype=np.uint8)
array = array.reshape((image.height, image.width, 4)) # BGRA
# Decode depth from RGB channels:
# depth_meters = 1000 * (R + G*256 + B*65536) / (256^3 - 1)
r = array[:, :, 2].astype(np.float64) # Red channel
g = array[:, :, 1].astype(np.float64) # Green channel
b = array[:, :, 0].astype(np.float64) # Blue channel
depth_meters = 1000.0 * (r + g * 256.0 + b * 65536.0) / (16777215.0)
# Save as numpy binary for exact values
np.save(f'{output_dir}/{image.frame:06d}.npy', depth_meters)
# Also save a visualization
image.save_to_disk(
f'{output_dir}/{image.frame:06d}.png',
carla.ColorConverter.LogarithmicDepth
)
return depth_meters
def process_lidar_data(lidar_measurement, output_dir='output/lidar'):
"""Process LiDAR point cloud data."""
os.makedirs(output_dir, exist_ok=True)
# Convert to numpy array: shape (N, 4) with columns (x, y, z, intensity)
points = np.frombuffer(lidar_measurement.raw_data, dtype=np.float32)
points = points.reshape((-1, 4))
num_points = points.shape[0]
x, y, z = points[:, 0], points[:, 1], points[:, 2]
intensity = points[:, 3]
# Save as PLY file
lidar_measurement.save_to_disk(f'{output_dir}/{lidar_measurement.frame:06d}.ply')
# Also save as numpy for fast loading
np.save(f'{output_dir}/{lidar_measurement.frame:06d}.npy', points)
return points
def process_radar_data(radar_measurement):
"""Extract radar detections as structured data."""
detections = []
for detection in radar_measurement:
detections.append({
'velocity': detection.velocity, # m/s (radial)
'azimuth': detection.azimuth, # radians
'altitude': detection.altitude, # radians
'depth': detection.depth, # meters
})
return detections