{"record":{"id":"9ba5a0f4bb82ffb7","repo":"roboflow/supervision","slug":"is-obb-true-requires-oriented-box-coordinates","errorCode":null,"errorMessage":"`is_obb=True` requires `'{ORIENTED_BOX_COORDINATES}'` in `detections.data` with shape (N, 4, 2). Load OBB datasets via `DetectionDataset.from_yolo(..., is_obb=True)` or set `detections.data['{ORIENTED_BOX_COORDINATES}']` (shape (N, 4, 2)) before exporting.","messagePattern":"`is_obb=True` requires `'(.+?)'` in `detections\\.data` with shape \\(N, 4, 2\\)\\. Load OBB datasets via `DetectionDataset\\.from_yolo\\(\\.\\.\\., is_obb=True\\)` or set `detections\\.data\\['(.+?)'\\]` \\(shape \\(N, 4, 2\\)\\) before exporting\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/dataset/formats/yolo.py","lineNumber":367,"sourceCode":"        ```pycon\n        >>> import numpy as np\n        >>> from supervision.detection.core import Detections\n        >>> from supervision.dataset.formats.yolo import detections_to_yolo_annotations\n        >>> detections = Detections(\n        ...     xyxy=np.array([[10, 10, 90, 90]], dtype=np.float32),\n        ...     class_id=np.array([0]),\n        ... )\n        >>> detections_to_yolo_annotations(detections, image_shape=(100, 100, 3))\n        ['0 0.50000 0.50000 0.80000 0.80000']\n\n        ```\n    \"\"\"\n    if (\n        is_obb\n        and len(detections) > 0\n        and ORIENTED_BOX_COORDINATES not in detections.data\n    ):\n        raise ValueError(\n            f\"`is_obb=True` requires `'{ORIENTED_BOX_COORDINATES}'` in \"\n            \"`detections.data` with shape (N, 4, 2). Load OBB datasets via \"\n            \"`DetectionDataset.from_yolo(..., is_obb=True)` or set \"\n            f\"`detections.data['{ORIENTED_BOX_COORDINATES}']` \"\n            \"(shape (N, 4, 2)) before exporting.\"\n        )\n\n    if is_obb and detections.mask is not None:\n        warnings.warn(\n            \"`detections.mask` is ignored when `is_obb=True`; \"\n            \"OBB annotations use corner coordinates from \"\n            f\"`detections.data['{ORIENTED_BOX_COORDINATES}']`.\",\n            UserWarning,\n            stacklevel=2,\n        )\n\n    annotation: list[str] = []\n    for xyxy, mask, _, class_id, _, data in detections:","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/dataset/formats/yolo.py#L349-L385","documentation":"Raised by detections_to_yolo_annotations when is_obb=True but detections.data does not contain the ORIENTED_BOX_COORDINATES entry (shape (N, 4, 2) of OBB corner points). OBB export cannot be derived from axis-aligned xyxy boxes, so the oriented corners must already be attached to the Detections — typically by loading an OBB dataset with DetectionDataset.from_yolo(..., is_obb=True).","triggerScenarios":"Calling sv.detections_to_yolo_annotations(detections, image_shape=..., is_obb=True) on Detections built from a normal detector output (no oriented corners in data), or exporting a from_yolo(..., is_obb=False) dataset with is_obb=True.","commonSituations":"Copy-pasting an OBB export snippet onto regular HBB detections; loading the dataset without is_obb=True and then trying to round-trip OBB annotations; manually constructing Detections and forgetting the data field.","solutions":["If the source dataset is OBB, load it with DetectionDataset.from_yolo(..., is_obb=True) so ORIENTED_BOX_COORDINATES is populated, then export with is_obb=True.","If building Detections by hand, set detections.data[sv.ORIENTED_BOX_COORDINATES] to an (N, 4, 2) array of corner points before exporting.","If your detections are actually axis-aligned, drop is_obb=True from the export call."],"exampleFix":"# before\nlines = sv.detections_to_yolo_annotations(dets, image_shape=shape, is_obb=True)\n# after\nimport supervision as sv\nimport numpy as np\ndets.data[sv.ORIENTED_BOX_COORDINATES] = corners  # (N, 4, 2)\nlines = sv.detections_to_yolo_annotations(dets, image_shape=shape, is_obb=True)","handlingStrategy":"type-guard","validationCode":"import supervision as sv\n\ndef can_export_obb(detections: sv.Detections) -> bool:\n    \"\"\"OBB export requires oriented corner data on non-empty detections.\"\"\"\n    return (len(detections) == 0\n            or sv.ORIENTED_BOX_COORDINATES in detections.data)","typeGuard":"def has_obb_data(detections) -> bool:\n    \"\"\"True when detections carry (N, 4, 2) oriented box coordinates.\"\"\"\n    corners = detections.data.get(sv.ORIENTED_BOX_COORDINATES)\n    return corners is not None and getattr(corners, 'ndim', 0) == 3 and corners.shape[1:] == (4, 2)","tryCatchPattern":"try:\n    lines = sv.detections_to_yolo_annotations(dets, image_shape=shape, is_obb=True)\nexcept ValueError as e:\n    if 'ORIENTED_BOX_COORDINATES' in str(e):\n        raise SystemExit('Load dataset with from_yolo(..., is_obb=True) or set '\n                         \"detections.data[sv.ORIENTED_BOX_COORDINATES]\") from e\n    raise","preventionTips":["Always load OBB datasets with from_yolo(..., is_obb=True) so corners are attached.","Keep load and export is_obb flags symmetric within a pipeline.","When converting model OBB output, store corners from cv2.boxPoints as (N, 4, 2)."],"tags":["yolo","obb","export","detections"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}