tlc.core.data_formats.keypoints

Defines representations of keypoints in 3LC.

Module Contents

Classes

Class

Description

Keypoints2DInstances

A helper class for working with 2D keypoints instances in 3LC Tables.

API

class Keypoints2DInstances

A helper class for working with 2D keypoints instances in 3LC Tables.

This class handles conversion to and from the internal dictionary representation of 2D keypoint instances, providing a convenient numpy-based interface for reading, manipulating, and writing keypoint data.

Objects can be created in three ways:

  1. Standard initialization: Direct instantiation with numpy arrays

  2. From table row: Use from_row() to convert a 3LC Table row to numpy arrays

  3. Build incrementally: Use create_empty() and add_instance() to build up keypoint data

Example:

# Read from table row
kpts = Keypoints2DInstances.from_row(table_row)
print(kpts.keypoints.shape)  # (num_instances, num_keypoints, 2)

# Build incrementally
kpts = Keypoints2DInstances.create_empty(640, 480)
kpts.add_instance(
    keypoints=[[100, 150], [120, 160], [140, 170]],
    bbox=[90, 140, 150, 180],
    label=0
)

# Write back to table
updated_row = kpts.to_row()
x_min: float = None

Minimum x coordinate of the coordinate system.

y_min: float = None

Minimum y coordinate of the coordinate system.

x_max: float = None

Maximum x coordinate of the coordinate system.

y_max: float = None

Maximum y coordinate of the coordinate system.

keypoints: ndarray[tuple[int, int, int], dtype[numpy.float32]] = None

A numpy array of shape (num_instances, num_keypoints, 2) with x and y coordinates per keypoint.

keypoint_visibilities: ndarray[tuple[int, int], dtype[numpy.int32]] | None = None

A numpy array of shape (num_instances, num_keypoints,) of integer visibilities per keypoint.

keypoint_confidences: ndarray[tuple[int, int], dtype[numpy.float32]] | None = None

A numpy array of shape (num_instances, num_keypoints,) of float confidences per keypoint.

instance_labels: ndarray[tuple[int], dtype[numpy.int32]] | None = None

Optional numpy array of shape (num_instances,) with integer class labels per instance.

instance_confidences: ndarray[tuple[int], dtype[numpy.float32]] | None = None

Optional numpy array of shape (num_instances,) of float confidences per instance.

instance_bbs: ndarray[tuple[int, int, int, int], dtype[numpy.float32]] | None = None

Optional numpy array of shape (num_instances, 4) with [x_min, y_min, x_max, y_max] per instance.

instance_extras: dict[str, ndarray] = None

Dictionary of arbitrary per-instance attributes as arrays with leading dimension (num_instances, …). Scalars and fixed-size vectors are supported. Always initialized, may be empty.

property image_width: float

Convenience property: width of the coordinate system.

property image_height: float

Convenience property: height of the coordinate system.

classmethod from_row(
row: Mapping[str, object],
) Keypoints2DInstances

Create a Keypoints2DInstances object from a 3LC Table row.

Parses the hierarchical table row dictionary into structured numpy arrays for easier manipulation. Automatically detects whether per-keypoint visibility or confidence values are present.

Parameters:

row – A dictionary representing a single row from a 3LC Table with keypoint data. Must contain the ‘instances’ key with a list of instance dictionaries, each containing ‘vertices_2d’ and ‘bbs_2d’.

Returns:

A Keypoints2DInstances object with all keypoint data converted to numpy arrays.

Raises:

ValueError – If the row does not contain instances, if both visibility and confidence are present, if visibility/confidence is only provided for a subset of instances, or if the number of labels doesn’t match the number of instances.

Example:

table = tlc.Table.from_names(...)
for row in table:
    kpts = Keypoints2DInstances.from_row(row)
    # Manipulate keypoint data
    kpts.keypoints[:, :, 0] *= scale_factor  # Scale x coordinates
    # Write back to table
    updated_row = kpts.to_row()
to_row() dict[str, Any]

Convert a Keypoints2DInstances object to the internal 3LC Table row format.

Converts the numpy arrays back into the hierarchical dictionary structure expected by 3LC Tables.

Returns:

A dictionary with the structure expected by 3LC Tables, containing ‘instances’ and ‘instances_additional_data’ keys.

Raises:

ValueError – If both visibility and confidence arrays are present (only one is supported).

Example:

kpts = Keypoints2DInstances.from_row(row)
# Modify keypoints
kpts.keypoints[:, 0, :] += [10, 10]  # Shift first keypoint
# Convert back to table format
updated_row = kpts.to_row()
classmethod create_empty(
image_width: float | None = None,
image_height: float | None = None,
x_min: float = 0.0,
y_min: float = 0.0,
x_max: float | None = None,
y_max: float | None = None,
include_keypoint_confidences: bool = False,
include_keypoint_visibilities: bool = False,
include_instance_confidences: bool = False,
include_instance_labels: bool = True,
include_instance_bbs: bool = True,
per_keypoint_extras_keys: Sequence[str] | None = None,
instance_extras_keys: Sequence[str] | None = None,
) Keypoints2DInstances

Create an empty Keypoints2DInstances object to build up incrementally.

Useful for creating keypoint data from scratch by adding instances one at a time using add_instance(). Will contain labels and bounding boxes by default.

Parameters:
  • x_min – Minimum x coordinate (default 0.0)

  • y_min – Minimum y coordinate (default 0.0)

  • x_max – Maximum x coordinate (provide this OR image_width)

  • y_max – Maximum y coordinate (provide this OR image_height)

  • image_width – Convenience parameter, sets x_max = x_min + image_width

  • image_height – Convenience parameter, sets y_max = y_min + image_height

  • include_keypoint_confidences – If True, initialize for storing per-keypoint confidence values. Mutually exclusive with include_keypoint_visibilities.

  • include_keypoint_visibilities – If True, initialize for storing per-keypoint visibility values. Mutually exclusive with include_keypoint_confidences.

  • include_instance_confidences – If True, initialize for storing per-instance confidence values.

  • include_instance_labels – If True, initialize for storing per-instance label values. Default is True.

  • include_instance_bbs – If True, initialize for storing per-instance bounding box values. Default is True.

  • per_keypoint_extras_keys – Sequence of keys for additional per-keypoint attributes to initialize

  • instance_extras_keys – Sequence of keys for additional per-instance attributes to initialize

Returns:

An empty Keypoints2DInstances object ready for adding instances.

Raises:

ValueError – If bounds are not properly specified

Example:

kpts = Keypoints2DInstances.create_empty(
    image_width=640,
    image_height=480,
    include_keypoint_confidences=True
)
kpts.add_instance(
    keypoints=[[100, 150], [120, 160]],
    bbox=[90, 140, 130, 170],
    label=0,
    confidence=[0.9, 0.8]
)
property instance_bbs_xywh: ndarray | None

Return the instance bounding boxes in xywh format.

Converts from the internal xyxy format [x_min, y_min, x_max, y_max] to xywh format [x_min, y_min, width, height], which is commonly used by some training frameworks.

Returns:

A numpy array of shape (num_instances, 4) with bounding boxes in [x, y, width, height] format, or None if no bounding boxes are present.

add_instance(
keypoints: list[float] | list[list[float]] | list[tuple[float, float]] | ndarray | None,
bbox: list[float] | tuple[float, float, float, float] | ndarray | None = None,
label: int | None = None,
visibility: list[int] | ndarray | None = None,
confidence: list[float] | ndarray | None = None,
normalized: bool = False,
bbox_format: str = 'xyxy',
instance_confidence: float | None = None,
instance_extras: Mapping[str, Any] | None = None,
) None

Add a single keypoint instance to the object.

Adds one instance (e.g., one person, one object) with its keypoints, bounding box, and label. Keypoints can be provided in multiple formats and will be normalized internally.

Parameters:
  • keypoints

    Keypoint coordinates in one of these formats:

    • Flat list: [x1, y1, x2, y2, …] or [x1, y1, v1, x2, y2, v2, …]

    • List of pairs: [[x1, y1], [x2, y2], …]

    • List of triplets: [[x1, y1, v1], [x2, y2, v2], …] (visibility derived from 3rd value)

    • NumPy array of shape (K, 2) or (K, 3)

  • bbox – Optional bounding box in xyxy format [x_min, y_min, x_max, y_max].

  • label – Optional integer class label for this instance.

  • visibility – Optional per-keypoint visibility flags (0=not labeled, 1=occluded, 2=visible). Mutually exclusive with confidence. If keypoints are provided with a 3rd column, that will be used as visibility unless explicitly overridden.

  • confidence – Optional per-keypoint confidence scores. Mutually exclusive with visibility.

  • normalized – Must be False. Normalized coordinates are not currently supported.

  • bbox_format – Must be “xyxy”. Other formats are not currently supported.

  • instance_confidence – Optional confidence score for the entire instance.

  • instance_extras – Optional dictionary of arbitrary per-instance attributes (e.g., {“track_id”: 42, “area”: 1500}). Values should be scalars. If an extra field is introduced after instances have been added, previous instances will be padded with NaN (float), -1 (int), or None (object).

Raises:

ValueError – If keypoints are None, if both visibility and confidence are provided, if normalized=True or bbox_format!=”xyxy”, or if the number of keypoints doesn’t match existing instances.

Example:

kpts = Keypoints2DInstances.create_empty(480, 640)
# Add first instance with 3 keypoints
kpts.add_instance(
    keypoints=[[100, 150], [120, 160], [140, 170]],
    bbox=[90, 140, 150, 180],
    label=0
)
# Add second instance (must also have 3 keypoints)
kpts.add_instance(
    keypoints=[[200, 250, 2], [220, 260, 2], [240, 270, 1]],  # with visibility
    bbox=[190, 240, 250, 280],
    label=0
)