Skip to main content

Depth image compression

Depth compression must preserve geometry, not visual similarity. A small mean error does not compensate for a large error at an object boundary: that error creates a false 3D point between foreground and background surfaces.

Two compression layers

Per-frame codecs and recording-container codecs solve different problems:
MCAP compresses chunks of messages with LZ4 or Zstd. This generic compression is lossless and complements a depth-aware codec; it does not define depth precision, invalid pixels, or image reconstruction. ROS 2โ€™s compressed_depth_image_transport uses PNG or RVL. Both preserve native 16UC1 values. For 32FC1, the plugin first converts floating-point depth to quantized inverse depth, so its PNG path is not bit-exact. RVL is a useful fast uint16 codec, but dimOS does not depend on its native implementation. The experimental ROS depthz proposal combines depth prediction, bounded quantization, and Zstd. It closely matches dimOSโ€™s requirements but remains an unmerged, unreviewed proposal. RealSense documents a depth-colorization method that maps depth into hue before JPEG, WebP, or video compression. This approach can use common hardware codecs, but it reduces depth to about 1,529 hue levels and can create flying pixels, depth inversion, and color-boundary gaps. It is better suited to bandwidth-constrained visual streaming than metric recording.

Default: lossless JPEG XL

The default Image storage codec uses lossless JPEG XL for DEPTH/float32 and DEPTH16/uint16. It uses ordinary lossy JPEG for visual image formats. This runtime dispatch keeps depth metric while retaining the existing visual-image tradeoff:
no-result
Use LERC when bounded error saves enough space to justify losing millimeter precision.

Why LERC

Limited Error Raster Compression (LERC) is an Apache-2.0 numeric-raster codec. It supports integer and floating-point arrays, validity masks, zero-error operation, and an explicit maximum error per sample. dimOS already receives LERC through its imagecodecs dependency. The lerc storage codec uses one contract: The codec also preserves shape, dtype, timestamp, frame ID, and the valid-pixel mask. Invalid float sentinels are canonicalized to NaN, so even zero-error LERC is exact for valid samples rather than bit-exact for the whole array. LERC remains opt-in.
no-result

Compare codecs

The benchmark processes complete depth streams through the same four codecs available to recordings: LCM, LZ4-wrapped LCM, the default jpeg codec (which uses lossless JPEG XL for depth), and 5 mm LERC. A source can be a SQLite recording, a directory containing depth/*.png or timestamped depth/*.pickle frames, or a named LFS dataset. PNG depth is interpreted as uint16 millimeters; float32 pickle arrays are interpreted as meters. Only load pickle data from trusted recordings. Frames are streamed instead of retained in memory.
skip
Check the harness without downloading recordings:
Real-recording runs require --output; the directory must be new or empty. They write results.json and results.md. Ratios use total raw and encoded bytes across the stream. Timing includes p50, p95, total wall and process-CPU time, plus effective frames per second. Fidelity includes global maximum, mean, and root-mean-square depth error and invalid-mask mismatches. The command fails if a codec violates its fidelity contract or a stream changes format, dtype, or dimensions. After every stream completes, the terminal prints one summary with the wall-time and fidelity figures most useful for choosing a codec; the artifact files retain the complete measurements.