Skip to content

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.

API Reference
Complete API documentation for COCOObjectDetectionAnnotation, including parameters, attributes, and methods.
View Reference →

Parameters

ParameterTypeDefaultDescription
idintRequiredAnnotation identifier.
image_idintRequiredIdentifier of the source image.
category_idintRequiredIdentifier of the annotated category.
bboxnp.ndarray | list[float] | list[int]RequiredBounding box [x, y, width, height] with shape (4,). Width and height must be non-negative.
areafloatRequiredAnnotation area. Must be greater than or equal to 0.
iscrowdboolRequiredWhether the annotation represents a crowd region. This also determines the expected segmentation representation.
segmentationCOCOPolygonSegmentationLike | COCORLESegmentationLike | NoneNoneOptional segmentation. Use polygon segmentation when iscrowd is False and COCO RLE segmentation when iscrowd is True.

Raises

ExceptionCondition
TypeErrorsegmentation 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).
ValueErrorbbox isn't shape (4,) or contains a non-finite value.
ValueErrorarea is negative or non-finite.
ValueErrorsegmentation fails RLE/polygon value validation (e.g. fewer than 3 points, non-finite coordinates, non-positive RLE size).

Attributes

AttributeTypeDescription
idintAnnotation id.
image_idintSource image id.
category_idintCategory id.
bboxnp.ndarrayDefensive copy of the box, shape (4,), [x, y, w, h]. Always present.
areafloatAnnotation area.
iscrowdboolCrowd flag; selects the segmentation representation.
segmentationCOCOPolygonSegmentation | COCORLESegmentation | NoneA polygon (iscrowd=False), an encoded RLE dict (iscrowd=True), or None.

Methods

MethodTypeDescription
COCOObjectDetectionAnnotation.coerce(value)COCOObjectDetectionAnnotationConverts 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)COCOObjectDetectionAnnotationBuilds 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=...)COCOObjectDetectionAnnotationAsMaskReturns 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)COCORLESegmentationEncodes a binary (H, W) mask as RLE, returning a canonical COCORLESegmentation.
COCOObjectDetectionAnnotation.polygon_to_rle(polygon, *, height, width)COCORLESegmentationRasterizes one or more polygons (a COCOPolygonSegmentationLike) and encodes the result as a canonical COCORLESegmentation.
COCOObjectDetectionAnnotation.rle_to_mask(rle)np.ndarrayDecodes a COCORLESegmentationLike into a binary (H, W) mask (uint8).
COCOObjectDetectionAnnotation.rle_to_polygon(rle, *, min_points=3, epsilon=0.0)COCOPolygonSegmentationApproximates a COCORLESegmentationLike as a COCOPolygonSegmentation by tracing the mask's boundary with marching squares.

Operators

OperationBehavior
a == bTrue 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

RepresentationMethodResult
Maskas_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()