roboflow/supervision · error · ValueError

Oriented bounding boxes must be shaped (N, 4, 2)

Error message

Oriented bounding boxes must be shaped (N, 4, 2)

What it means

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.

Source

Thrown at src/supervision/metrics/utils/object_size.py:239

        The size category of each bounding box, matching
        the enum values of ObjectSizeCategory. Shaped (N,).

    Example:
        ```pycon
        >>> import numpy as np
        >>> from supervision.metrics.utils.object_size import get_obb_size_category
        >>> obb = np.array([
        ...     [[0, 0], [10, 0], [10, 10], [0, 10]],   # 100 (Small)
        ...     [[0, 0], [50, 0], [50, 50], [0, 50]],   # 2500 (Medium)
        ...     [[0, 0], [100, 0], [100, 100], [0, 100]] # 10000 (Large)
        ... ])
        >>> get_obb_size_category(obb)
        array([1, 2, 3])

        ```
    """
    if len(xyxyxyxy.shape) != 3 or xyxyxyxy.shape[1] != 4 or xyxyxyxy.shape[2] != 2:
        raise ValueError("Oriented bounding boxes must be shaped (N, 4, 2)")

    # Shoelace formula
    x = xyxyxyxy[:, :, 0]
    y = xyxyxyxy[:, :, 1]
    x1, x2, x3, x4 = x.T
    y1, y2, y3, y4 = y.T
    areas = 0.5 * np.abs(
        (x1 * y2 + x2 * y3 + x3 * y4 + x4 * y1)
        - (x2 * y1 + x3 * y2 + x4 * y3 + x1 * y4)
    )

    result = np.full(areas.shape, ObjectSizeCategory.ANY.value)
    SM, LG = SIZE_THRESHOLDS
    result[areas < SM] = ObjectSizeCategory.SMALL.value
    result[(areas >= SM) & (areas < LG)] = ObjectSizeCategory.MEDIUM.value
    result[areas >= LG] = ObjectSizeCategory.LARGE.value
    return result

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Reshape to (N, 4, 2): corners.reshape(N, 4, 2)
  2. Convert axis-aligned xyxy to corners: [[x1,y1],[x2,y1],[x2,y2],[x1,y2]] per box
  3. Ensure OBB model connectors store the (N,4,2) array in detections.data[ORIENTED_BOX_COORDINATES]

Example fix

# before
obb = np.array([[0, 0, 10, 10]])       # xyxy, wrong format
get_obb_size_category(obb)

# after
x1, y1, x2, y2 = 0, 0, 10, 10
obb = np.array([[[x1, y1], [x2, y1], [x2, y2], [x1, y2]]])  # (1, 4, 2)
get_obb_size_category(obb)
Defensive patterns

Strategy: validation

Validate before calling

obb = np.asarray(obb)
if obb.shape[-2:] != (4, 2):
    obb = obb.reshape(-1, 4, 2)
cats = get_obb_size_category(obb)

Type guard

import numpy as np

def is_obb_corners(arr: np.ndarray) -> bool:
    """True when arr is (N, 4, 2) oriented box corners."""
    return arr.ndim == 3 and arr.shape[1] == 4 and arr.shape[2] == 2

Try / catch

try:
    cats = get_obb_size_category(obb)
except ValueError as e:
    if '(N, 4, 2)' in str(e):
        cats = get_obb_size_category(obb.reshape(-1, 4, 2))
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/107caaea7426af37. Report an issue: GitHub.