SegmentationImage
Represents a 2D per-pixel segmentation label map.
Reference semantics on construction
A contiguous input array is stored by reference, not copied. Pass data.copy() explicitly if the source array may be mutated afterward.
Parameters
| Field | Type | Description |
|---|---|---|
data | np.ndarray | Label array, shape (H, W), dtype from the allowlist below. |
compression | ImageCompression | int | On-wire compression codec (see ImageCompression), or a matching int. Default ImageCompression.NONE. |
Raises
| Exception | Condition |
|---|---|
TypeError | data isn't an np.ndarray |
ValueError | data isn't 2-D, is empty (H or W is 0), has an unsupported dtype, contains a negative label (checked for signed dtypes only), or compression is invalid |
Supported Dtypes
uint8, uint16, uint32, uint64, int8, int16, int32, int64. No floating-point dtypes.
Attributes
| Attribute | Type | Description |
|---|---|---|
data | np.ndarray | Defensive copy of the label array. Assigning re-validates and invalidates the memoized label_codes/number_of_labels scan. |
shape | tuple[int, int] | (height, width). |
height | int | Image height. |
width | int | Image width. |
dtype | np.dtype | Dtype of the label array. |
compression | ImageCompression | On-wire codec. Read-only (no setter). |
label_codes | np.ndarray | Defensive copy of the sorted unique label codes present in data. Memoized (an np.unique scan) and invalidated by the data setter. |
number_of_labels | int | Count of distinct label codes present, from the same memoized scan. |
Methods
| Method | Description |
|---|---|
to_numpy(copy=True) | Returns the label array as np.ndarray; copy=False returns the internal array directly. |
to_binary_mask() | Returns a new SegmentationImage where every non-zero label becomes 1 and 0 stays 0 (dtype uint8). Note: despite its docstring mentioning a threshold argument, the method takes no parameters -- it always thresholds at "non-zero". |
SegmentationImage.from_raw_buffer(buffer, shape, dtype, compression=NONE) | Builds a SegmentationImage from raw label bytes via np.frombuffer + reshape. Raises ValueError if buffer's size doesn't match shape. |
SegmentationImage.coerce(value) | Returns value unchanged if already a SegmentationImage; otherwise wraps an np.ndarray. Raises TypeError for anything else. |
Operators
| Operation | Behavior |
|---|---|
img == other | True only if other is a SegmentationImage with an element-equal label array; compression is not compared. NotImplemented if other isn't a SegmentationImage. |
np.asarray(img) | Returns a copy of the label array. copy=False raises ValueError; use to_numpy(copy=False). |
hash(img) | Not supported. |
repr(img) | Shows label_codes/number_of_labels when compression is NONE; otherwise just shape/dtype/compression (skips the label scan). |
Serialization
Arrow layout:
text
StructArray length 1
├── data: binary
├── height: int32
├── width: int32
├── dtype: string
└── compression: int8from_pyarrow treats a payload with no compression field (written before the field existed) as ImageCompression.NONE.
Visualization
datatypes.visualize(segmentation_image, entity_path=...) logs an AnnotationContext mapping label 0 to a fully transparent color (so the background doesn't occlude anything logged beneath it), then logs data as rr.SegmentationImage.
Example
python
"""Demonstrates the Telekinesis SegmentationImage datatype."""
import time
import numpy as np
from loguru import logger
import rerun as rr
from telekinesis import datatypes
def segmentation_image_example():
"""Demonstrate creation, access, visualization, update, NumPy interop, and serialization."""
# ======================= Create ============================================
data = np.random.randint(0, 255, (480, 640), dtype=np.uint8)
image = datatypes.SegmentationImage(data)
logger.info(f"Original SegmentationImage: {image}")
# ======================= Inspect ===========================================
label_codes = image.label_codes
number_of_labels = image.number_of_labels
shape = image.data.shape
dtype = image.data.dtype
height = image.height
width = image.width
compression = image.compression
numpy_array = image.to_numpy()
logger.info(
f"label_codes={label_codes}, "
f"number_of_labels={number_of_labels}, "
f"shape={shape}, "
f"dtype={dtype}, "
f"height={height}, "
f"width={width}, "
f"compression={compression}"
)
logger.info(f"SegmentationImage data:\n{image.data}")
logger.info(f"NumPy array:\n{numpy_array}")
# ======================= Visualize =========================================
rr.init("segmentation_image_example", spawn=True)
datatypes.visualize(
image,
entity_path="/SegmentationImage/my_segmentation_image",
)
# ======================= Update ============================================
updated_data = np.random.randint(0, 255, (480, 640), dtype=np.uint8)
image.data = updated_data
logger.info(f"Updated SegmentationImage: {image}")
datatypes.visualize(
image,
entity_path="/SegmentationImage/my_updated_segmentation_image",
)
# ======================= NumPy Interop =====================================
mean = np.mean(image)
flipped = np.flipud(image)
logger.info(f"Mean pixel value: {mean}")
logger.info(f"Flipped shape={flipped.shape}, dtype={flipped.dtype}")
# ======================= Serialize / Deserialize ===========================
start = time.perf_counter()
serialized = datatypes.serialize(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 SegmentationImage: {deserialized}")
logger.info(f"Round-trip successful: {image == deserialized}")
logger.info(f"Serialization time: {serialization_ms:.3f} ms")
logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")
if __name__ == "__main__":
segmentation_image_example()
