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
- 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]
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
- 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
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
- Bounding boxes must be shaped (N, 4)
- Areas must be shaped (N,)
- Masks must be shaped (N, H, W)
- Detections oriented bounding boxes are not available
- Value must be a np.ndarray or a list
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/107caaea7426af37.
Report an issue: GitHub.