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:
parent
a549f44792
commit
8a4063086f
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
[
|
||||
|
|
|
|||
Loading…
Reference in New Issue