{"record":{"id":"107caaea7426af37","repo":"roboflow/supervision","slug":"oriented-bounding-boxes-must-be-shaped-n-4-2","errorCode":null,"errorMessage":"Oriented bounding boxes must be shaped (N, 4, 2)","messagePattern":"Oriented bounding boxes must be shaped \\(N, 4, 2\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/metrics/utils/object_size.py","lineNumber":239,"sourceCode":"        The size category of each bounding box, matching\n        the enum values of ObjectSizeCategory. Shaped (N,).\n\n    Example:\n        ```pycon\n        >>> import numpy as np\n        >>> from supervision.metrics.utils.object_size import get_obb_size_category\n        >>> obb = np.array([\n        ...     [[0, 0], [10, 0], [10, 10], [0, 10]],   # 100 (Small)\n        ...     [[0, 0], [50, 0], [50, 50], [0, 50]],   # 2500 (Medium)\n        ...     [[0, 0], [100, 0], [100, 100], [0, 100]] # 10000 (Large)\n        ... ])\n        >>> get_obb_size_category(obb)\n        array([1, 2, 3])\n\n        ```\n    \"\"\"\n    if len(xyxyxyxy.shape) != 3 or xyxyxyxy.shape[1] != 4 or xyxyxyxy.shape[2] != 2:\n        raise ValueError(\"Oriented bounding boxes must be shaped (N, 4, 2)\")\n\n    # Shoelace formula\n    x = xyxyxyxy[:, :, 0]\n    y = xyxyxyxy[:, :, 1]\n    x1, x2, x3, x4 = x.T\n    y1, y2, y3, y4 = y.T\n    areas = 0.5 * np.abs(\n        (x1 * y2 + x2 * y3 + x3 * y4 + x4 * y1)\n        - (x2 * y1 + x3 * y2 + x4 * y3 + x1 * y4)\n    )\n\n    result = np.full(areas.shape, ObjectSizeCategory.ANY.value)\n    SM, LG = SIZE_THRESHOLDS\n    result[areas < SM] = ObjectSizeCategory.SMALL.value\n    result[(areas >= SM) & (areas < LG)] = ObjectSizeCategory.MEDIUM.value\n    result[areas >= LG] = ObjectSizeCategory.LARGE.value\n    return result\n","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/metrics/utils/object_size.py#L221-L257","documentation":"Raised by get_obb_size_category() when the oriented-bounding-box input is not shaped (N, 4, 2) — N boxes, each with 4 corner points, each point an (x, y) pair. The function unpacks the 4 corners per box to run the shoelace area formula, so the shape is a hard requirement. It checks ndim==3, shape[1]==4, shape[2]==2 up front.","triggerScenarios":"Passing axis-aligned xyxy boxes shaped (N, 4); passing corner points as (N, 8) or (N, 2, 4); passing a single box without the leading N dimension.","commonSituations":"Converting between xyxy and OBB formats incorrectly; OBB connectors that flatten corners; forgetting that ORIENTED_BOUNDING_BOXES metric_target requires the 4-corner representation stored under the ORIENTED_BOX_COORDINATES data key.","solutions":["Reshape to (N, 4, 2): corners.reshape(N, 4, 2)","Convert axis-aligned xyxy to corners: [[x1,y1],[x2,y1],[x2,y2],[x1,y2]] per box","Ensure OBB model connectors store the (N,4,2) array in detections.data[ORIENTED_BOX_COORDINATES]"],"exampleFix":"# before\nobb = np.array([[0, 0, 10, 10]])       # xyxy, wrong format\nget_obb_size_category(obb)\n\n# after\nx1, y1, x2, y2 = 0, 0, 10, 10\nobb = np.array([[[x1, y1], [x2, y1], [x2, y2], [x1, y2]]])  # (1, 4, 2)\nget_obb_size_category(obb)","handlingStrategy":"validation","validationCode":"obb = np.asarray(obb)\nif obb.shape[-2:] != (4, 2):\n    obb = obb.reshape(-1, 4, 2)\ncats = get_obb_size_category(obb)","typeGuard":"import numpy as np\n\ndef is_obb_corners(arr: np.ndarray) -> bool:\n    \"\"\"True when arr is (N, 4, 2) oriented box corners.\"\"\"\n    return arr.ndim == 3 and arr.shape[1] == 4 and arr.shape[2] == 2","tryCatchPattern":"try:\n    cats = get_obb_size_category(obb)\nexcept ValueError as e:\n    if '(N, 4, 2)' in str(e):\n        cats = get_obb_size_category(obb.reshape(-1, 4, 2))\n    else:\n        raise","preventionTips":["Convert xyxy to corners explicitly when mixing formats: corners = np.stack([[x1,y1],[x2,y1],[x2,y2],[x1,y2]])","Store OBB corners under detections.data[ORIENTED_BOX_COORDINATES] at construction"],"tags":["metrics","object-size","obb","shape-validation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}