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
- Wrap a single box in a batch axis: corners = corners[np.newaxis, :] so the shape becomes (1, 4, 2).
- If corners are transposed (N, 2, 4), transpose before calling: corners.transpose(0, 2, 1).
- 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
- Keep a single project-wide helper that coerces OBB arrays to (N, 4, 2) before any oriented-box API.
- Reshape flattened 8-value OBB outputs with .reshape(-1, 4, 2) at the model boundary.
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
- xyxyxyxy must have shape (N, 4, 2); got {xyxyxyxy.shape}
- xyxyxyxy must have shape (N, 4, 2); got {corners.shape}
- `{name}` has shape {arr.shape}; expected (N, 4, 2) — each bo
- `{name}` has shape {arr.shape}; expected (N, 8) for flat YOL
- `{name}` has shape {arr.shape}; expected (N, 5) or (N, 6).
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/712557aca8bac476.
Report an issue: GitHub.