DepthImage
Represents a per-pixel metric depth map, optionally paired with an aligned RGB image to form a full RGB-D frame.
Reference semantics on construction
Construction does not defensively copy a contiguous input array -- depth/colors are stored by reference. Pass arr.copy() explicitly if the source array may be mutated afterward. The depth/colors properties do return defensive copies.
Parameters
| Field | Type | Description |
|---|---|---|
depth | np.ndarray | Required depth map, shape (H, W), dtype float32, meters. |
colors | np.ndarray | None | Optional aligned RGB image, shape (H, W, 3), dtype uint8, matching depth's height/width. Default None. |
compression | ImageCompression | int | On-wire compression codec, or a matching int. Default ImageCompression.NONE. |
Raises
| Exception | Condition |
|---|---|
TypeError | depth or colors (when not None) isn't an np.ndarray |
ValueError | depth isn't dtype float32/shape (H, W); colors isn't dtype uint8/shape (H, W, 3) matching depth; or compression is invalid |
Attributes
| Attribute | Type | Description |
|---|---|---|
depth | np.ndarray | Defensive copy, shape (H, W) float32 (meters). Read-only (no setter) -- construct a new DepthImage to change it. |
colors | np.ndarray | None | Defensive copy, shape (H, W, 3) uint8, or None. Read-only. |
shape | tuple[int, int] | Shape of depth, (H, W). |
height | int | Depth map height. |
width | int | Depth map width. |
has_colors | bool | Whether an aligned color image is attached. |
compression | ImageCompression | On-wire codec. Read-only. |
Methods
| Method | Description |
|---|---|
DepthImage.coerce(value) | Returns value unchanged if already a DepthImage; otherwise wraps an np.ndarray as depth. Raises TypeError for anything else. |
There's no to_numpy() method (unlike Image/SegmentationImage) -- use the depth property or np.asarray(depth_image) for the depth map; colors is only reachable via the colors property.
Operators
| Operation | Behavior |
|---|---|
di == other | True only if other is a DepthImage with an equal depth map and equal (or equally absent) colors; compression is not compared. NotImplemented if other isn't a DepthImage. |
np.asarray(di) | Returns a copy of depth only (not colors). copy=False raises ValueError -- there is no zero-copy accessor for depth on this class. |
hash(di) | Not supported. |
Serialization
Arrow layout:
StructArray length 1
├── depth: binary (float32 (H, W) bytes, raw or ZSTD-framed)
├── colors: binary nullable (uint8 (H, W, 3) bytes, raw/ZSTD; null when absent)
├── height: int32
├── width: int32
└── compression: int8 (ImageCompression member value)depth and colors share the same compression codec.
Visualization
datatypes.visualize(depth_image, entity_path=...) logs depth at {entity_path}/depth as rr.DepthImage, and, if has_colors, logs colors at {entity_path}/color as rr.Image.
Example
"""Demonstrates the Telekinesis DepthImage datatype."""
import time
import numpy as np
from loguru import logger
import rerun as rr
from telekinesis import datatypes
def depth_image_example():
"""Demonstrate creation, inspection, visualization, update, RGB-D, compression, NumPy interop, and serialization."""
# ======================= Create ============================================
H, W = 480, 640
depth = (np.random.rand(H, W) * 5.0).astype(np.float32)
depth_image = datatypes.DepthImage(depth)
logger.info(f"Input depth shape={depth.shape}, dtype={depth.dtype}")
logger.info(f"Original DepthImage: {depth_image}")
# ======================= Inspect ===========================================
data = depth_image.depth
shape = depth_image.shape
height = depth_image.height
width = depth_image.width
has_colors = depth_image.has_colors
compression = depth_image.compression
numpy_array = np.asarray(depth_image)
logger.info(
f"shape={shape}, "
f"height={height}, "
f"width={width}, "
f"has_colors={has_colors}, "
f"compression={compression}"
)
logger.info(f"Data: {data}")
logger.info(f"NumPy array: {numpy_array}")
# ======================= Visualize =========================================
rr.init("depth_image_example", spawn=True)
datatypes.visualize(depth_image, entity_path="/DepthImage")
# ======================= Update ============================================
new_depth = (np.random.rand(H, W) * 5.0).astype(np.float32)
depth_image = datatypes.DepthImage(new_depth)
datatypes.visualize(depth_image, entity_path="/DepthImage")
# ======================= RGB-D =============================================
colors = np.random.randint(0, 255, (H, W, 3), dtype=np.uint8)
rgbd_image = datatypes.DepthImage(depth, colors=colors)
logger.info(f"RGB-D DepthImage: {rgbd_image}")
datatypes.visualize(rgbd_image, entity_path="/RGBDImage")
# ======================= ZSTD Compression ==================================
zstd_image = datatypes.DepthImage(
depth,
colors=colors,
compression=datatypes.ImageCompression.ZSTD,
)
logger.info(f"ZSTD DepthImage: {zstd_image}")
datatypes.visualize(zstd_image, entity_path="/ZSTDImage")
# ======================= NumPy Interop =====================================
mean_depth = np.mean(depth_image)
flipped_depth = np.flipud(depth_image)
logger.info(f"Mean depth value: {mean_depth}")
logger.info(f"Flipped depth shape={flipped_depth.shape}, dtype={flipped_depth.dtype}")
# ======================= Serialize / Deserialize ===========================
start = time.perf_counter()
serialized = datatypes.serialize(rgbd_image)
serialization_ms = (time.perf_counter() - start) * 1000
start = time.perf_counter()
deserialized = datatypes.deserialize(serialized)["param_0"]
deserialization_ms = (time.perf_counter() - start) * 1000
logger.info(f"Deserialized DepthImage: {deserialized}")
logger.info(f"Round-trip successful: {deserialized == rgbd_image}")
logger.info(f"Serialization time: {serialization_ms:.3f} ms")
logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")
if __name__ == "__main__":
depth_image_example()
