Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions supervision/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
from supervision.detection.tools.polygon_zone import PolygonZone, PolygonZoneAnnotator
from supervision.detection.tools.smoother import DetectionsSmoother
from supervision.detection.utils.boxes import (
box_aspect_ratio,
clip_boxes,
denormalize_boxes,
move_boxes,
Expand Down Expand Up @@ -200,7 +199,6 @@
"VideoInfo",
"VideoSink",
"approximate_polygon",
"box_aspect_ratio",
"box_iou",
"box_iou_batch",
"box_iou_batch_with_jaccard",
Expand Down
37 changes: 37 additions & 0 deletions supervision/detection/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2088,6 +2088,43 @@ def box_area(self) -> np.ndarray:
"""
return (self.xyxy[:, 3] - self.xyxy[:, 1]) * (self.xyxy[:, 2] - self.xyxy[:, 0])

@property
def box_aspect_ratio(self) -> np.ndarray:
"""
Compute the aspect ratio (width divided by height) for each bounding box.

Returns:
np.ndarray: Array of shape `(N,)` containing aspect ratios, where `N` is the
number of boxes (width / height for each box).

Examples:
```python
import numpy as np
import supervision as sv

xyxy = np.array([
[10, 10, 50, 50],
[60, 10, 180, 50],
[10, 60, 50, 180],
])

detections = sv.Detections(xyxy=xyxy)

detections.box_aspect_ratio
# array([1.0, 3.0, 0.33333333])

ar = detections.box_aspect_ratio
detections[(ar < 2.0) & (ar > 0.5)].xyxy
# array([[10., 10., 50., 50.]])
```
"""
widths = self.xyxy[:, 2] - self.xyxy[:, 0]
heights = self.xyxy[:, 3] - self.xyxy[:, 1]

aspect_ratios = np.full_like(widths, np.nan, dtype=np.float64)
np.divide(widths, heights, out=aspect_ratios, where=heights != 0)
return aspect_ratios

def with_nms(
self,
threshold: float = 0.5,
Expand Down
51 changes: 0 additions & 51 deletions supervision/detection/utils/boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,6 @@
from supervision.detection.utils.iou_and_nms import box_iou_batch


def box_aspect_ratio(xyxy: np.ndarray) -> np.ndarray:
"""
Calculate aspect ratios of bounding boxes given in xyxy format.

Computes the width divided by height for each bounding box. Returns NaN
for boxes with zero height to avoid division errors.

Args:
xyxy (`numpy.ndarray`): Array of bounding boxes in
`(x_min, y_min, x_max, y_max)` format with shape `(N, 4)`.

Returns:
`numpy.ndarray`: Array of aspect ratios with shape `(N,)`, where each element is
the width divided by height of a box. Elements are NaN if height is zero.

Examples:
```python
import numpy as np
import supervision as sv

xyxy = np.array([
[10, 20, 30, 50],
[0, 0, 40, 10],
])

sv.box_aspect_ratio(xyxy)
# array([0.66666667, 4. ])

xyxy = np.array([
[10, 10, 30, 10],
[5, 5, 25, 25],
])

sv.box_aspect_ratio(xyxy)
# array([ nan, 1. ])
```
"""
widths = xyxy[:, 2] - xyxy[:, 0]
heights = xyxy[:, 3] - xyxy[:, 1]

aspect_ratios = np.full_like(widths, np.nan, dtype=np.float64)
np.divide(
widths,
heights,
out=aspect_ratios,
where=heights != 0,
)

return aspect_ratios


def clip_boxes(xyxy: np.ndarray, resolution_wh: tuple[int, int]) -> np.ndarray:
"""
Clips bounding boxes coordinates to fit within the frame resolution.
Expand Down
1 change: 1 addition & 0 deletions test/utils/test_internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def __private_property(self):
"metadata",
"area",
"box_area",
"box_aspect_ratio",
},
DoesNotRaise(),
),
Expand Down
Loading