COCOObjectDetectionAnnotation
SUMMARY
A single COCO-style object detection or instance segmentation annotation.
python
from telekinesis import datatypes
annotation = datatypes.COCOObjectDetectionAnnotation(
id=0,
image_id=7,
category_id=1,
bbox=[0, 0, 10, 10],
area=100.0, iscrowd=False
)Segmentation representation follows iscrowd
iscrowd=False stores segmentation as a native polygon; iscrowd=True stores it as an encoded COCO RLE dict. Call as_mask() to rasterize either one to a binary mask.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
id | int | Required | Annotation identifier. |
image_id | int | Required | Identifier of the source image. |
category_id | int | Required | Identifier of the annotated category. |
bbox | np.ndarray | list[float] | list[int] | Required | Bounding box [x, y, width, height] with shape (4,). Width and height must be non-negative. |
area | float | Required | Annotation area. Must be greater than or equal to 0. |
iscrowd | bool | Required | Whether the annotation represents a crowd region. This also determines the expected segmentation representation. |
segmentation | COCOPolygonSegmentationLike | COCORLESegmentationLike | None | None | Optional segmentation. Use polygon segmentation when iscrowd is False and COCO RLE segmentation when iscrowd is True. |
Raises
| Exception | Condition |
|---|---|
TypeError | segmentation is present but structurally doesn't match iscrowd's representation (e.g. a dict when iscrowd=False, or a list of polygons when iscrowd=True). |
ValueError | bbox isn't shape (4,) or contains a non-finite value. |
ValueError | area is negative or non-finite. |
ValueError | segmentation fails RLE/polygon value validation (e.g. fewer than 3 points, non-finite coordinates, non-positive RLE size). |
Attributes
| Attribute | Type | Description |
|---|---|---|
id | int | Annotation id. |
image_id | int | Source image id. |
category_id | int | Category id. |
bbox | np.ndarray | Defensive copy of the box, shape (4,), [x, y, w, h]. Always present. |
area | float | Annotation area. |
iscrowd | bool | Crowd flag; selects the segmentation representation. |
segmentation | COCOPolygonSegmentation | COCORLESegmentation | None | A polygon (iscrowd=False), an encoded RLE dict (iscrowd=True), or None. |
Methods
| Method | Type | Description |
|---|---|---|
COCOObjectDetectionAnnotation.coerce(value) | COCOObjectDetectionAnnotation | Converts a dict of constructor arguments into a COCOObjectDetectionAnnotation. If value is already a COCOObjectDetectionAnnotation, it is returned unchanged. |
COCOObjectDetectionAnnotation.from_mask(*, id, image_id, category_id, bbox, area, mask) | COCOObjectDetectionAnnotation | Builds an annotation from a binary (H, W) mask (an np.ndarray or SegmentationImage), encoding it as an RLE segmentation. Since a mask has no polygon representation, the result always has iscrowd=True. |
as_mask(image_height=..., image_width=...) | COCOObjectDetectionAnnotationAsMask | Returns this annotation with its segmentation rasterized to a binary mask at the given size. If the stored segmentation is RLE, image_height/image_width must match the size already embedded in it; if it's a polygon, they must be positive integers. See COCOObjectDetectionAnnotationAsMask for the returned fields. |
COCOObjectDetectionAnnotation.mask_to_rle(mask) | COCORLESegmentation | Encodes a binary (H, W) mask as RLE, returning a canonical COCORLESegmentation. |
COCOObjectDetectionAnnotation.polygon_to_rle(polygon, *, height, width) | COCORLESegmentation | Rasterizes one or more polygons (a COCOPolygonSegmentationLike) and encodes the result as a canonical COCORLESegmentation. |
COCOObjectDetectionAnnotation.rle_to_mask(rle) | np.ndarray | Decodes a COCORLESegmentationLike into a binary (H, W) mask (uint8). |
COCOObjectDetectionAnnotation.rle_to_polygon(rle, *, min_points=3, epsilon=0.0) | COCOPolygonSegmentation | Approximates a COCORLESegmentationLike as a COCOPolygonSegmentation by tracing the mask's boundary with marching squares. |
Operators
| Operation | Behavior |
|---|---|
a == b | True only if b is also a COCOObjectDetectionAnnotation with equal id, image_id, category_id, bbox (element-wise), area, iscrowd, and segmentation (size/counts if iscrowd, element-wise polygon otherwise); NotImplemented if b isn't a COCOObjectDetectionAnnotation. |
Representations
| Representation | Method | Result |
|---|---|---|
| Mask | as_mask(image_height=..., image_width=...) | COCOObjectDetectionAnnotationAsMask |
Visualization
python
import rerun as rr
# Your code block
# ....
rr.init("coco_object_detection_annotation_example", spawn=True)
datatypes.visualize(annotation, entity_path="/annotation", label="COCOObjectDetectionAnnotation")Example
python
"""Demonstrates the Telekinesis COCOObjectDetectionAnnotation datatype."""
import time
import numpy as np
import rerun as rr
from loguru import logger
from telekinesis import datatypes
def coco_object_detection_annotation_example():
"""Demonstrate creation, inspection, operations, visualization, and serialization."""
# ======================= Create ============================================
# Segmentation semantics: iscrowd=False -> polygon (stored natively, not
# converted), iscrowd=True -> encoded COCO RLE. The two representations are
# never silently converted between each other.
image_height, image_width = 720, 1280
annotation = datatypes.COCOObjectDetectionAnnotation(
id=0,
image_id=7,
category_id=1,
bbox=[0, 0, 10, 10],
area=100.0,
iscrowd=False,
segmentation=[[0, 2, 10, 0, 10, 10, 0, 10]],
)
logger.info(f"Created COCOObjectDetectionAnnotation: {annotation}")
# ======================= Inspect ===========================================
logger.info(f"id={annotation.id}")
logger.info(f"image_id={annotation.image_id}")
logger.info(f"category_id={annotation.category_id}")
logger.info(f"bbox={annotation.bbox}")
logger.info(f"area={annotation.area}")
logger.info(f"iscrowd={annotation.iscrowd}")
logger.info(f"segmentation={annotation.segmentation}")
# ======================= Operations =========================================
annotation_as_mask = annotation.as_mask(image_height=image_height, image_width=image_width)
logger.info(
f"Segmentation as mask: shape={annotation_as_mask['segmentation'].shape}, "
f"dtype={annotation_as_mask['segmentation'].dtype}"
)
# `from_mask` always yields iscrowd=True (matching the RLE segmentation it
# builds); `area` is still passed explicitly, since it's a labeling decision
# that can't be derived from the mask alone.
crowd_mask = np.zeros((image_height, image_width), dtype=np.uint8)
crowd_mask[100:200, 150:400] = 1
crowd_annotation = datatypes.COCOObjectDetectionAnnotation.from_mask(
id=1,
image_id=7,
category_id=2,
bbox=[150, 100, 250, 100],
area=float(crowd_mask.sum()),
mask=crowd_mask,
)
logger.info(f"Crowd annotation built from a mask: {crowd_annotation}")
crowd_annotation_as_mask = crowd_annotation.as_mask(
image_height=image_height, image_width=image_width
)
logger.info(
f"Crowd segmentation as mask: shape={crowd_annotation_as_mask['segmentation'].shape}, "
f"dtype={crowd_annotation_as_mask['segmentation'].dtype}"
)
# Mixin helpers shared across all COCO segmentation datatypes.
mask_from_rle = datatypes.COCOObjectDetectionAnnotation.rle_to_mask(crowd_annotation.segmentation)
logger.info(f"Mask decoded via rle_to_mask: shape={mask_from_rle.shape}, dtype={mask_from_rle.dtype}")
polygon_from_rle = datatypes.COCOObjectDetectionAnnotation.rle_to_polygon(
crowd_annotation.segmentation
)
logger.info(f"Polygon decoded via rle_to_polygon: {polygon_from_rle}")
rle_from_polygon = datatypes.COCOObjectDetectionAnnotation.polygon_to_rle(
annotation.segmentation, height=image_height, width=image_width
)
logger.info(f"RLE encoded via polygon_to_rle: {rle_from_polygon}")
# ======================= Visualize =========================================
rr.init("coco_object_detection_annotation_example", spawn=True)
datatypes.visualize(annotation, entity_path="/coco_object_detection_annotation")
datatypes.visualize(crowd_annotation, entity_path="/coco_object_detection_annotation/crowd")
# ======================= Serialize / Deserialize ===========================
start = time.perf_counter()
serialized = datatypes.serialize(annotation)
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 COCOObjectDetectionAnnotation: {deserialized}")
logger.info(f"Round-trip successful: {annotation == deserialized}")
logger.info(f"Serialization time: {serialization_ms:.3f} ms")
logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")
if __name__ == "__main__":
coco_object_detection_annotation_example()
