DepthImage
SUMMARY
A metric depth map with optional aligned RGB data.
python
from telekinesis import datatypes
import numpy as np
depth_image = datatypes.DepthImage(np.ones((4, 4), dtype=np.float32))Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
depth | np.ndarray | Required | Metric depth values in metres with shape (H, W) and a supported dtype. |
colors | np.ndarray | None | None | Optional aligned RGB image with shape (H, W, 3) and dtype uint8. Its height and width must match the depth image. |
compression | ImageCompression | int | ImageCompression.NONE | Compression codec used during serialization. |
Raises
| Exception | Condition |
|---|---|
TypeError | depth or colors (when not None) isn't an np.ndarray |
ValueError | depth's dtype isn't in the allowlist or its shape isn't (H, W); colors isn't dtype uint8/shape (H, W, 3) matching depth; or compression is invalid |
Supported Dtypes
| Field | Dtypes |
|---|---|
depth | float16, float32, float64 |
colors | uint8 |
Attributes
| Attribute | Type | Description |
|---|---|---|
depth | np.ndarray | Defensive copy, shape (H, W), dtype one of SUPPORTED_DEPTH_DTYPES (meters). Read-only. 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 | Type | Description |
|---|---|---|
DepthImage.coerce(value) | DepthImage | Converts array-like data into a DepthImage. If value is already a DepthImage, it is returned unchanged; otherwise a np.ndarray is wrapped as the depth map. |
DepthImage.from_raw_buffer(buffer, shape, dtype, depth_scale=1.0, compression=NONE) | DepthImage | Builds a depth image straight from a raw sensor-count buffer (e.g. uint16 values straight off a depth camera), scaling to meters by multiplying by depth_scale. |
DepthImage.from_encoded_buffer(buffer, depth_scale=1.0, compression=NONE) | DepthImage | Decodes a single-channel encoded image (typically a 16-bit PNG) into raw sensor counts, then scales to meters the same way as from_raw_buffer. |
DepthImage.from_path(path, depth_scale=1.0, compression=NONE) | DepthImage | Reads an encoded depth image file from disk and decodes it the same way as from_encoded_buffer. |
DepthImage.from_url(url, depth_scale=1.0, compression=NONE, connect_timeout=5.0, read_timeout=30.0) | DepthImage | Downloads an encoded depth image and decodes it the same way as from_encoded_buffer, with configurable connect/read timeouts. |
to_numpy(copy=True) | np.ndarray | Returns the depth map. With the default copy=True you get an independent copy; pass copy=False for a direct reference to the internal array instead. The aligned colors image, if any, isn't included; access it via the colors property. |
copy() | DepthImage | Returns a new, independent DepthImage with the same depth (and color, if present) data and compression setting. |
save_to_path(path, *, depth_scale=1.0) | None | Writes the depth map to disk as a 16-bit encoded image, the inverse of from_encoded_buffer/from_raw_buffer. The aligned color image, if any, isn't written. |
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) as an np.ndarray; NumPy functions accept a DepthImage directly. Passing copy=False raises ValueError. |
Visualization
python
import rerun as rr
# Your code block
# ....
rr.init("depth_image_example", spawn=True)
datatypes.visualize(depth_image, entity_path="/depth_image", label="DepthImage")Example
python
"""Demonstrates the Telekinesis DepthImage datatype."""
import time
from pathlib import Path
import numpy as np
import rerun as rr
from loguru import logger
from telekinesis import datatypes
def depth_image_example():
"""Demonstrate creation, inspection, operations, visualization, 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"Created DepthImage: {depth_image}")
depth_image_from_coerce = datatypes.DepthImage.coerce(depth)
logger.info(f"DepthImage created via coerce: {depth_image_from_coerce}")
depth_scale = 0.001
raw_counts = np.round(depth / depth_scale).astype(np.uint16)
depth_image_from_raw_buffer = datatypes.DepthImage.from_raw_buffer(
raw_counts.tobytes(), shape=depth.shape, dtype=raw_counts.dtype, depth_scale=depth_scale
)
logger.info(f"DepthImage created from raw buffer: {depth_image_from_raw_buffer}")
save_path = Path("results/depth_image_example.png")
save_path.parent.mkdir(parents=True, exist_ok=True)
depth_image.save_to_path(save_path, depth_scale=depth_scale)
depth_image_from_path = datatypes.DepthImage.from_path(save_path, depth_scale=depth_scale)
logger.info(f"DepthImage created from path: {depth_image_from_path}")
encoded_buffer = save_path.read_bytes()
depth_image_from_encoded_buffer = datatypes.DepthImage.from_encoded_buffer(
encoded_buffer, depth_scale=depth_scale
)
logger.info(f"DepthImage created from encoded buffer: {depth_image_from_encoded_buffer}")
# ======================= Inspect ===========================================
logger.info(f"depth={depth_image.depth}")
logger.info(f"colors={depth_image.colors}")
logger.info(f"shape={depth_image.shape}")
logger.info(f"height={depth_image.height}")
logger.info(f"width={depth_image.width}")
logger.info(f"has_colors={depth_image.has_colors}")
logger.info(f"compression={depth_image.compression}")
# ======================= Operations =========================================
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}")
zstd_image = datatypes.DepthImage(
depth, colors=colors, compression=datatypes.ImageCompression.ZSTD
)
logger.info(f"ZSTD-compressed DepthImage: {zstd_image}")
depth_image_copy = depth_image.copy()
logger.info(f"Copied DepthImage: {depth_image_copy}")
depth_image_numpy = depth_image.to_numpy(copy=True)
logger.info(f"NumPy depth array: {depth_image_numpy}")
numpy_array = np.asarray(depth_image)
logger.info(f"Mean depth value: {np.mean(numpy_array)}")
logger.info(f"Flipped depth shape: {np.flipud(numpy_array).shape}")
# ======================= Visualize =========================================
rr.init("depth_image_example", spawn=True)
datatypes.visualize(depth_image, entity_path="/depth_image/original")
datatypes.visualize(rgbd_image, entity_path="/depth_image/rgbd")
datatypes.visualize(zstd_image, entity_path="/depth_image/zstd")
# ======================= 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: {rgbd_image == deserialized}")
logger.info(f"Serialization time: {serialization_ms:.3f} ms")
logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")
if __name__ == "__main__":
depth_image_example()
