roboflow/supervision · error · ValueError

corners must have shape (N, 4, 2); got {corners.shape}

Error message

corners must have shape (N, 4, 2); got {corners.shape}

What it means

Raised by obb_polygon_area when the corners array is not shaped (N, 4, 2): N oriented boxes, each with exactly 4 corner points, each point with x and y. The shoelace-area computation indexes the last two axes directly, so any other shape would compute garbage or broadcast incorrectly, hence the strict check.

Source

Thrown at src/supervision/detection/utils/boxes.py:272

    Returns:
        Area of each box as a 1-D float64 array of shape `(N,)`.

    Raises:
        ValueError: If `corners` does not have shape `(N, 4, 2)`.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> from supervision.detection.utils.boxes import obb_polygon_area
        >>> corners = np.array([[[0, 5], [5, 10], [10, 5], [5, 0]]], dtype=np.float32)
        >>> obb_polygon_area(corners)
        array([50.])

        ```
    """
    corners = cast(npt.NDArray[np.number], np.asarray(corners))
    if corners.ndim != 3 or corners.shape[-2:] != (4, 2):
        raise ValueError(f"corners must have shape (N, 4, 2); got {corners.shape}")
    x = corners[..., 0].astype(np.float64, copy=False)
    y = corners[..., 1].astype(np.float64, copy=False)
    cross = x * np.roll(y, -1, axis=-1) - y * np.roll(x, -1, axis=-1)
    return cast(npt.NDArray[np.float64], 0.5 * np.abs(np.sum(cross, axis=-1)))


def xyxyxyxy_to_xyxy(
    xyxyxyxy: npt.NDArray[np.number],
) -> npt.NDArray[np.number]:
    """Convert oriented bounding box corners to axis-aligned bounding boxes.

    Args:
        xyxyxyxy: OBB corner coordinates with shape `(N, 4, 2)` where each
            box is represented as `[[x1, y1], [x2, y2], [x3, y3], [x4, y4]]`.

    Returns:
        Axis-aligned bounding boxes as an array of shape `(N, 4)`
            in `(x_min, y_min, x_max, y_max)` format.

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Wrap a single box in a batch axis: corners = corners[np.newaxis, :] so the shape becomes (1, 4, 2).
  2. If corners are transposed (N, 2, 4), transpose before calling: corners.transpose(0, 2, 1).
  3. Ensure each of the N entries has exactly 4 (x, y) points; re-serialize the source data if some boxes have a different corner count.

Example fix

# before
corners = np.array([[0, 5], [5, 10], [10, 5], [5, 0]], dtype=np.float32)
obb_polygon_area(corners)  # ValueError: shape is (4, 2)

# after
corners = np.array([[[0, 5], [5, 10], [10, 5], [5, 0]]], dtype=np.float32)
obb_polygon_area(corners)  # array([50.])
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np

def as_obb_corners(a) -> np.ndarray:
    a = np.asarray(a, dtype=np.float64)
    if a.ndim == 2 and a.shape == (4, 2):
        a = a[np.newaxis]
    assert a.ndim == 3 and a.shape[-2:] == (4, 2), f'bad corners shape {a.shape}'
    return a

area = obb_polygon_area(as_obb_corners(corners))

Type guard

def is_obb_corners(a) -> bool:
    a = np.asarray(a)
    return a.ndim == 3 and a.shape[-2:] == (4, 2)

Prevention

When it happens

Trigger: Calling obb_polygon_area with a single box of shape (4, 2) (missing the batch axis), a list that assembles to (N, 4) or (N, 2, 4), a ragged list of corners, or a 2-D axis-aligned xyxy array of shape (N, 4).

Common situations: Forgetting np.array([corners]) around a single box; transposed corner arrays coming out of a custom OBB decoder; feeding xyxy boxes into an oriented-box helper by mistake.

Related errors


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