Skip to main content

Bounding Box Conversion

Guide for bidirectional V1/V2 conversion of bounding box annotations.

Data Structure

V1 Structure

# annotations
{
"id": "ann_1",
"tool": "bounding_box",
"isLocked": False,
"isVisible": True,
"isValid": True,
"classification": {
"class": "person",
"color": "red" # additional attribute
},
"label": ["person"]
}

# annotationsData
{
"id": "ann_1",
"coordinate": {
"x": 100,
"y": 200,
"width": 150,
"height": 100,
"rotation": 0.5236 # optional
}
}

V2 Structure

{
"id": "ann_1",
"classification": "person",
"attrs": [
{"name": "color", "value": "red"},
{"name": "rotation", "value": 0.5236}
],
"data": [100, 200, 150, 100] # [x, y, width, height]
}

Conversion Rules

V1 → V2

V1 FieldV2 Field
coordinate.{x, y, width, height}data[0, 1, 2, 3]
coordinate.rotationattrs[{name: "rotation", value}]
classification.classclassification
classification.{other}attrs[{name, value}]

V2 → V1

V2 FieldV1 Field
data[0, 1, 2, 3]coordinate.{x, y, width, height}
attrs.rotationcoordinate.rotation
classificationclassification.class
attrs[{name, value}]classification.{name: value}

Usage Examples

Basic Conversion

from synapse_sdk.utils.converters.dm import convert_v1_to_v2, convert_v2_to_v1

# V1 bounding box data
v1_data = {
"annotations": {
"image_1": [
{
"id": "Cd1qfFQFI4",
"tool": "bounding_box",
"isLocked": False,
"isVisible": True,
"classification": {"class": "person", "color": "red"}
}
]
},
"annotationsData": {
"image_1": [
{
"id": "Cd1qfFQFI4",
"coordinate": {"x": 100, "y": 200, "width": 150, "height": 100}
}
]
}
}

# Convert to V2
result = convert_v1_to_v2(v1_data)
annotation_data = result["annotation_data"]

# Check V2 result
bbox = annotation_data["images"][0]["bounding_box"][0]
print(bbox["data"]) # [100, 200, 150, 100]
print(bbox["classification"]) # "person"
print(bbox["attrs"]) # [{"name": "color", "value": "red"}]

Rotation Handling

# Bounding box with rotation
v1_rotated = {
"annotations": {
"image_1": [
{
"id": "Rot12345ab",
"tool": "bounding_box",
"classification": {"class": "text"}
}
]
},
"annotationsData": {
"image_1": [
{
"id": "Rot12345ab",
"coordinate": {
"x": 50, "y": 100,
"width": 200, "height": 50,
"rotation": 0.5236 # ~30 degrees (radians)
}
}
]
}
}

# Convert to V2
result = convert_v1_to_v2(v1_rotated)
bbox = result["annotation_data"]["images"][0]["bounding_box"][0]

# rotation is preserved in attrs
print(bbox["data"]) # [50, 100, 200, 50]
rotation_attr = [a for a in bbox["attrs"] if a["name"] == "rotation"][0]
print(rotation_attr["value"]) # 0.5236

# Restore to V1
v1_restored = convert_v2_to_v1(result)
restored_coord = v1_restored["annotationsData"]["image_1"][0]["coordinate"]
print(restored_coord["rotation"]) # 0.5236 (preserved)

Meta Information Restoration

Using annotation_meta restores all V1 meta fields:

# Complete conversion (with meta information)
v1_full = convert_v2_to_v1(result)

# Check meta fields
ann = v1_full["annotations"]["image_1"][0]
print(ann["isLocked"]) # False (original value)
print(ann["isVisible"]) # True (original value)
print(ann["isValid"]) # True (original value)

# Conversion with annotation_data only uses defaults
v1_basic = convert_v2_to_v1({"annotation_data": annotation_data})
ann_basic = v1_basic["annotations"]["image_1"][0]
print(ann_basic["isLocked"]) # False (default)
print(ann_basic["isValid"]) # False (default)