chore: update YOLO OBB annotation export support (#2302)

* fix(yolo): validate OBB corner shape and test is_obb=False passthrough
* docs(config): add attribute docstring to ORIENTED_BOX_COORDINATES

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
This commit is contained in:
Tamil Adhavan S K 2026-06-10 18:58:42 +05:30 committed by GitHub
parent a549f44792
commit 8a4063086f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 39 additions and 3 deletions

View File

@ -1,5 +1,12 @@
CLASS_NAME_DATA_FIELD: str = "class_name"
# Used by move_detections (coordinate transform) and InferenceSlicer (OBB thread-safety
# detection). Any code that sets this key in Detections.data also affects slicer
# scheduling: InferenceSlicer switches to sequential mode when this key is present.
#: Key for oriented bounding-box corner coordinates in ``Detections.data``.
#:
#: Value layout: ``np.ndarray`` of shape ``(N, 4, 2)``, dtype ``float32``, pixel
#: coordinates ordered as ``[[x1, y1], [x2, y2], [x3, y3], [x4, y4]]`` per
#: detection where the four points are the corners of the oriented box.
#: Used by :func:`~supervision.dataset.formats.yolo.detections_to_yolo_annotations`
#: (``is_obb=True``) and
#: :func:`~supervision.dataset.formats.yolo.yolo_annotations_to_detections`
#: (``is_obb=True``).
#: Also triggers sequential mode in ``InferenceSlicer`` when present.
ORIENTED_BOX_COORDINATES: str = "xyxyxyxy"

View File

@ -379,6 +379,13 @@ def detections_to_yolo_annotations(
if is_obb:
corners = np.asarray(data[ORIENTED_BOX_COORDINATES], dtype=np.float32)
if corners.shape != (4, 2):
raise ValueError(
f"OBB data for each detection must have shape (4, 2), "
f"got {corners.shape}. Ensure "
f"`detections.data['{ORIENTED_BOX_COORDINATES}']` has "
"shape (N, 4, 2) before exporting."
)
next_object = object_to_yolo(
xyxy=xyxy,
class_id=class_id_int,

View File

@ -617,6 +617,28 @@ def test_detections_to_yolo_annotations_obb_multiple_detections() -> None:
)
def test_detections_to_yolo_annotations_obb_data_ignored_when_is_obb_false() -> None:
"""OBB data in detections.data must be silently ignored when is_obb=False."""
corners = np.array(
[[[50.0, 10.0], [90.0, 50.0], [50.0, 90.0], [10.0, 50.0]]],
dtype=np.float32,
)
detections = Detections(
xyxy=np.array([[10.0, 10.0, 90.0, 90.0]], dtype=np.float32),
class_id=np.array([0], dtype=int),
data={ORIENTED_BOX_COORDINATES: corners},
)
lines = detections_to_yolo_annotations(
detections=detections, image_shape=(100, 100, 3), is_obb=False
)
assert len(lines) == 1
assert len(lines[0].split()) == 5, (
"Without is_obb=True, OBB data must be ignored and bbox format (5 tokens) used"
)
@pytest.mark.parametrize(
("is_obb_save", "expected_tokens"),
[