Repository navigation
v0.31.1 β Recall that matches COCO, boxes that don't overflow
A bug-fix release: recall scores now agree with COCO, and half-precision boxes stop overflowing.
MeanAverageRecallskips crowd regions and matches predictions in confidence order, likepycocotools.- COCO segmentations loaded without an
areafield no longer make mAP return-1. float16boxes keep finite areas, and mAP andwith_nmmstop overflowing on narrow coordinate types.- Mask and halo annotators draw on grayscale scenes, and vertex annotators accept
(x, y, z)points. - Without OpenCV, ellipses and thick circles render like OpenCV 5, and grayscale images save correctly.
Drop-in upgrade, no code changes. mAR values can move: up on COCO data with crowd annotations, and in either direction where confidence order now decides which prediction claims a target.
β¨ Spotlights / highlights
Recall that matches COCO
sv.metrics.MeanAverageRecall used to count COCO crowd regions as missed objects and to pair predictions with the highest-IoU target first. It now leaves out targets with data["iscrowd"] or data["ignore"] set, the same rule MeanAveragePrecision uses. It also matches predictions in descending confidence order with COCO's tie rule, and counts an oriented-box IoU of exactly 0.55, 0.6, 0.8 or 0.85 as a match at that threshold. One target, one crowd target and a perfect prediction now score 1.0 instead of 0.5. (#2750, #2758, #2752)
import numpy as np
import supervision as sv
from supervision.metrics import MeanAverageRecall
targets = sv.Detections(
xyxy=np.array([[0, 0, 10, 10], [20, 20, 30, 30]], dtype=float),
class_id=np.array([0, 0]),
data={"iscrowd": np.array([0, 1])},
)
predictions = sv.Detections(
xyxy=np.array([[0, 0, 10, 10]], dtype=float),
class_id=np.array([0]),
confidence=np.array([0.9]),
)
MeanAverageRecall().update(predictions, targets).compute().mAR_at_100 # 1.0Half-precision boxes that stay finite
A 256Γ256 box in float16 has an area of 65,536, which is past float16's maximum, so Detections.box_area returned inf and area filters dropped it. Box areas of float16 detections are now computed and returned in float32, and MeanAveragePrecision and with_nmm no longer overflow on float16 or narrow integer coordinates either. COCO segmentations loaded with masks but without an area field now get it from the decoded mask, so those targets stay in their size bucket instead of turning mAP into -1. (#2764, #2743, #2753, #2763)
import numpy as np
import supervision as sv
detections = sv.Detections(
xyxy=np.array([[0, 0, 256, 256], [0, 0, 0.01, 0.01]], dtype=np.float16)
)
detections.box_area # array([6.5536000e+04, 1.0004273e-04], dtype=float32)Grayscale scenes and 3D keypoints in annotators
sv.MaskAnnotator and sv.HaloAnnotator raised ValueError on single-channel images. They now accept (H, W), (H, W, 1) and Pillow "L" scenes, painting the gray value OpenCV would write for the same color. VertexAnnotator and the vertex-ellipse annotators draw (x, y, z) keypoints from their x and y, where they used to fail on tuple unpacking. (#2755, #2759)
import numpy as np
import supervision as sv
scene = np.zeros((100, 100), dtype=np.uint8)
mask = np.zeros((1, 100, 100), dtype=bool)
mask[0, 20:60, 20:60] = True
detections = sv.Detections(
xyxy=np.array([[20, 20, 60, 60]], dtype=float), mask=mask, class_id=np.array([0])
)
sv.MaskAnnotator().annotate(scene.copy(), detections).shape # (100, 100)
key_points = sv.KeyPoints(xy=np.array([[[10, 10, 0.5], [50, 50, 1.0]]], dtype=np.float32))
sv.VertexAnnotator().annotate(np.zeros((64, 64, 3), dtype=np.uint8), key_points)Drawing without OpenCV, closer to OpenCV
The NumPy fallback used when OpenCV is not installed now ports OpenCV's ellipse rasterization, and thick circle outlines are centred on the radius instead of shrinking inward by half their thickness. Both match OpenCV 5.0 pixel for pixel in the reference tests. Without OpenCV, this changes the pixels drawn by EllipseAnnotator, RoundBoxAnnotator, the vertex-ellipse keypoint annotators, CircleAnnotator and DotAnnotator outlines. Image writing now accepts (H, W, 1) grayscale arrays and saves BGRA images as JPEG, and video reading handles files whose audio stream comes before the video stream. (#2740, #2765, #2754, #2746)
π Migration guide
No migration required for this release.
π Notable changes
π§ Fixed
MeanAverageRecall and COCO
sv.metrics.MeanAverageRecallcounted COCO crowd and ignored targets as missed objects and paired predictions by highest IoU first; it now skips those targets and matches in descending confidence order with COCO's last-target tie rule, as COCO does. (#2750, #2758)- Oriented-box
MeanAverageRecall,Precision,RecallandF1Scoremissed matches whose IoU was exactly 0.55, 0.6, 0.8 or 0.85, because the IoU wasfloat64and the thresholdsfloat32. (#2752)
Overflow-safe boxes
Detections.box_areaand box-basedDetections.areaoverflowed to infinity for ordinaryfloat16boxes; they now compute and returnfloat32. (#2764)sv.metrics.MeanAveragePrecisionoverflowed box extents and areas forfloat16or narrow integer coordinates, so perfect large boxes scored-1or landed in the wrong size bucket. (#2743)sv.Detections.with_nmmoverflowed its area-weighted confidence forfloat16boxes and, at extreme coordinates, for integer andfloat32boxes. (#2753)- COCO loading with masks left segmented annotations without an
areafield with aNaNarea, which pushed them out of every mAP size bucket; the area now comes from the decoded mask. (#2763)
Masks and polygons
resize_masksreturned an empty array when downscaling very narrow masks; it now keeps at least one pixel per axis. (#2762)sv.filter_polygons_by_areaandsv.polygon_to_xyxyraisedValueErroron empty polygons; they now treat them as zero area and an all-zero box. (#2761)
Annotators
sv.MaskAnnotatorandsv.HaloAnnotatorraisedValueErroron grayscale scenes. (#2755)VertexAnnotatorand the vertex-ellipse annotators raised a tuple-unpacking error on three-coordinate keypoints; they now draw from x and y. (#2759)sv.MaskAnnotatorwidened its blend region to the boxes of all-empty masks, includingCompactMask, copying and blending outside the foreground. (#2741)
Without OpenCV
- The fallback
ellipsepainted different pixels from OpenCV for thick strokes, fills and arcs; it now ports OpenCV's rasterization. (#2740) - The fallback
circlegrew thick outlines inward from the bounding box, shrinking them by half their thickness; they are now centred on the radius. (#2765) - Image writing rejected
(H, W, 1)grayscale arrays and lost BGRA images saved as JPEG. (#2754) - Video reading failed on files whose audio stream comes before the first video stream. (#2746)
π Contributors
Welcome to our first-time contributors, Ghanashyam V Narayan and jorge!
- NIKHIL (@Nikhi00718) β fixed overflow in box areas, mAP and
with_nmm, derived missing COCO areas, and fixed image writing and video reading without OpenCV. - Kaushik Reddy Lingireddy (@Lingikaushikreddy) β made
MeanAverageRecallskip crowd targets and match by confidence, and fixed oriented-box threshold matching. - peng xiang (@px12811) β ported OpenCV's ellipse rasterization to the fallback and fixed mAR tie-breaking.
- A Aswanth Raj (@aswanth-07) β fixed three-coordinate keypoint drawing and narrow-mask resizing.
- Mohammad Hijjawi (@MohammadHijjawi97) β made
MaskAnnotatorandHaloAnnotatorwork on grayscale scenes. - kevin (@kevin9327) β centred thick fallback circles on their radius.
- Ghanashyam V Narayan (@ghanashyam03) β made the polygon helpers accept empty polygons.
- jorge (@jorge-asenjo) β kept empty compact masks out of the mask blend region.
- Jirka Borovec (@Borda) β prepared the release.
Full changelog: 0.31.0...0.31.1