Image
SUMMARY
An image with a flexible channel layout.
python
from telekinesis import datatypes
import numpy as np
image = datatypes.Image(np.zeros((4, 4, 3), dtype=np.uint8))Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
data | np.ndarray | Required | Pixel values with shape (H, W), (H, W, 3), or (H, W, 4) and a supported dtype. |
compression | ImageCompression | int | ImageCompression.NONE | Compression codec used during serialization. Compression does not change the in-memory pixel values. |
Raises
| Exception | Condition |
|---|---|
TypeError | data isn't an np.ndarray |
ValueError | data's dtype isn't in the allowlist, its shape isn't (H, W)/(H, W, 3)/(H, W, 4), or compression isn't a valid ImageCompression member/matching int |
Supported Dtypes
| Category | Dtypes |
|---|---|
| Unsigned integer | uint8 |
| Signed integer | int32, int64 |
| Floating-point | float16, float32, float64 |
Other dtypes are not supported.
Attributes
| Attribute | Type | Description |
|---|---|---|
data | np.ndarray | Defensive copy of the pixel array. Assigning re-validates like construction. |
shape | tuple[int, ...] | (H, W), (H, W, 3), or (H, W, 4). |
height | int | First axis of shape. |
width | int | Second axis of shape. |
dtype | np.dtype | Dtype of the pixel array. |
channels | int | 1 (grayscale), 3 (RGB), or 4 (RGBA). |
compression | ImageCompression | On-wire codec. Read-only. Construct a new Image to change it. |
Methods
| Method | Type | Description |
|---|---|---|
Image.coerce(value) | Image | Converts array-like data into an Image. If value is already an Image, it is returned unchanged; otherwise a np.ndarray is wrapped the same way as the constructor. |
Image.from_raw_buffer(buffer, shape, dtype, compression=NONE) | Image | Builds an image directly from raw, already-decoded pixel bytes at the given shape and dtype, without copying. For encoded files (JPEG, PNG, ...), use from_encoded_buffer instead. |
Image.from_encoded_buffer(buffer, compression=NONE, dtype=np.uint8) | Image | Decodes an encoded image (JPEG, PNG, ...) into RGB, or RGBA if the source has transparency. Use dtype=np.uint8 for 0-255 values, or a floating dtype to get values normalized to 0.0-1.0. |
Image.from_path(path, compression=NONE, dtype=np.uint8) | Image | Reads an image file from disk and decodes it the same way as from_encoded_buffer. |
Image.from_url(url, compression=NONE, dtype=np.uint8, connect_timeout=5.0, read_timeout=30.0) | Image | Downloads an image from a URL and decodes it the same way as from_encoded_buffer, with configurable connect/read timeouts. |
expand_dims() | ImageBatch | Wraps this image in a length-1 ImageBatch for use with batch-oriented code. |
to_numpy(copy=True) | np.ndarray | Returns the pixel array. With the default copy=True you get an independent copy; pass copy=False for a direct reference to the internal array instead. |
to_rgb() | Image | Converts to 3-channel RGB. Grayscale input is returned unchanged as a copy; 3-channel input is treated as BGR and has its channel order reversed; 4-channel input is treated as BGRA, reordered to RGB, and loses its alpha channel. The result is always 3-channel. Use to_rgba() instead if you need to keep alpha. |
to_bgr() | Image | Converts to 3-channel BGR. Grayscale input is returned unchanged as a copy; 3-channel input is treated as RGB and has its channel order reversed; 4-channel input is treated as RGBA, reordered to BGR, and loses its alpha channel. The result is always 3-channel. Use to_bgra() instead if you need to keep alpha. |
to_rgba() | Image | Converts to 4-channel RGBA. Grayscale input is returned unchanged as a copy, not expanded to 4 channels. 3-channel input is treated as BGR, reversed, and given a new fully-opaque alpha channel. 4-channel input is treated as BGRA, reordered to RGBA, and keeps its existing alpha values. |
to_bgra() | Image | Converts to 4-channel BGRA. Grayscale input is returned unchanged as a copy, not expanded to 4 channels. 3-channel input is treated as RGB, reversed, and given a new fully-opaque alpha channel. 4-channel input is treated as RGBA, reordered to BGRA, and keeps its existing alpha values. |
to_grayscale(colorspace="rgb") | Image | Converts to a single-channel image using BT.601 luminance weights (0.299/0.587/0.114), dropping alpha if present. Set colorspace to "rgb" (default) or "bgr" to match the input's channel order; no other values are accepted. Already-grayscale input is returned unchanged as a copy. |
copy() | Image | Returns a new, independent Image with the same pixels and compression setting. |
save_to_path(path, format=None) | None | Encodes and writes the image to disk. Floating-point pixel data is clipped to [0, 1] and rescaled to uint8 first. The file format is inferred from the path's extension if not given explicitly. |
Operators
| Operation | Behavior |
|---|---|
img == other | True only if other is an Image with an element-equal pixel array; compression is not compared. NotImplemented if other isn't an Image. |
np.asarray(img) | Returns a copy of the pixel array as an np.ndarray; NumPy functions accept an Image directly. Passing copy=False raises ValueError. |
Visualization
python
import rerun as rr
# Your code block
# ....
rr.init("image_example", spawn=True)
datatypes.visualize(image, entity_path="/image", label="Image")Example
python
"""Demonstrates the Telekinesis Image datatype."""
import time
from pathlib import Path
import numpy as np
import rerun as rr
from loguru import logger
from telekinesis import datatypes
def image_example():
"""Demonstrate creation, inspection, operations, visualization, and serialization."""
# ======================= Create ============================================
root = Path(__file__).parent
data = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
image = datatypes.Image(data)
logger.info(f"Created Image: {image}")
buffer = data.tobytes()
image_from_raw_buffer = datatypes.Image.from_raw_buffer(buffer, shape=data.shape, dtype=data.dtype)
logger.info(f"Image created from raw buffer: {image_from_raw_buffer}")
encoded_buffer = (root / "data/sample.jpg").read_bytes()
image_from_encoded_buffer = datatypes.Image.from_encoded_buffer(encoded_buffer)
logger.info(f"Image created from encoded buffer: {image_from_encoded_buffer}")
image_from_path = datatypes.Image.from_path(root / "data/sample.jpg")
logger.info(f"Image created from path: {image_from_path}")
url = "https://assets.telekinesis.ai/examples/v1/images/screws_standing.jpg"
image_from_url = datatypes.Image.from_url(url)
logger.info(f"Image created from URL: {image_from_url}")
# ======================= Inspect ===========================================
logger.info(f"compression={image.compression}")
logger.info(f"data={image.data}")
logger.info(f"shape={image.shape}")
logger.info(f"height={image.height}")
logger.info(f"width={image.width}")
logger.info(f"channels={image.channels}")
logger.info(f"dtype={image.dtype}")
# ======================= Operations =========================================
image.data = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
logger.info(f"Updated Image: {image}")
gray_image = image_from_path.to_grayscale()
logger.info(f"Grayscale image: {gray_image}")
bgr_image = image_from_path.to_bgr()
logger.info(f"BGR image: {bgr_image}")
rgb_image = bgr_image.to_rgb()
logger.info(f"RGB image: {rgb_image}")
image_batch = image.expand_dims()
logger.info(f"Expanded to ImageBatch: {image_batch}")
image_copy = image.copy()
logger.info(f"Copied Image: {image_copy}")
image_numpy = image.to_numpy(copy=True)
logger.info(f"NumPy Image:\n{image_numpy}")
output_path = root / "data/output_image.jpg"
gray_image.save_to_path(output_path)
logger.info(f"Image saved to: {output_path}")
mean_pixel_value = np.mean(image)
flipped_image = np.flipud(image)
logger.info(f"Mean pixel value: {mean_pixel_value}")
logger.info(f"Flipped shape={flipped_image.shape}, dtype={flipped_image.dtype}")
# ======================= Visualize =========================================
rr.init("image_example", spawn=True)
datatypes.visualize(image, entity_path="/image")
datatypes.visualize(image_from_path, entity_path="/image/from_path")
datatypes.visualize(image_from_url, entity_path="/image/from_url")
datatypes.visualize(gray_image, entity_path="/image/grayscale")
datatypes.visualize(bgr_image, entity_path="/image/bgr")
datatypes.visualize(rgb_image, entity_path="/image/rgb")
# ======================= 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 Image: {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__":
image_example()