Skip to content

releasing 0.31.0 [squash & merge] - #2742

Merged
Borda merged 1 commit into
developfrom
releasing/0.31.0
Oct 16, 2026
Merged

Borda merged 1 commit into
developfrom
releasing/0.31.0

Conversation

@Borda

@Borda Borda commented Oct 16, 2026

Copy link
Copy Markdown
Member

v0.31.0 — Depth, moving cameras and pose mAP

📋 Summary

supervision now sees depth: load depth maps from your model or stereo rig, measure how far each object is, and draw the map.

  • sv.DepthMap measures the distance to every detection and colours depth over any image, no OpenCV needed.
  • PolygonZone and LineZone keep counting in the right place while the camera pans.
  • KeyPointMeanAveragePrecision scores pose models the way pycocotools does.
  • Kosmos-2, Gemini 3.6/3.7 and MediaPipe hands now load straight into Detections and KeyPoints.
  • MeanAveragePrecision runs far faster on crowded images and lets you raise the detection cap.

It's a drop-in upgrade if 0.30.x showed you no deprecation warnings, apart from four output changes. sv.ByteTrack with the supervision.tracker package, supervision.keypoint, sv.LMM, the legacy sv.MeanAveragePrecision and a few helpers are gone; the Migration guide has the swaps.

✨ Spotlights / highlights

Depth maps: load, measure and draw

sv.DepthMap holds metric depth, stereo disparity or relative depth for one frame, and keeps track of which one it is. sv.DepthCamera converts disparity to metres, measure_detections writes the median depth under each object to detections.data ("depth_m" when the map can give metres), and sv.DepthAnnotator colours the map over an image without OpenCV. sv.DepthClipRange keeps one colour scale across a whole video, so colours don't flicker between frames. Loaders read Roboflow Inference, Ultralytics, Transformers, and 16-bit PNG and PFM dataset files such as KITTI and Middlebury. (#2691, #2692, #2693, #2694)

import numpy as np
import supervision as sv

depth = np.full((100, 100), 20.0, dtype=np.float32)
depth[20:40, 20:40] = 4.0
depth_map = sv.DepthMap(depth, kind="depth_m")

detections = sv.Detections(xyxy=np.array([[20, 20, 40, 40], [60, 60, 90, 90]], dtype=float))
detections = depth_map.measure_detections(detections)
detections.data["depth_m"]  # array([ 4., 20.], dtype=float32)

annotated = sv.DepthAnnotator().annotate(np.zeros((100, 100, 3), np.uint8), depth_map)

Zones that follow the camera

Zones used to assume a fixed camera; when it panned, the scene slid out from under the zone. PolygonZone.trigger and LineZone.trigger now take an optional per-frame coord_transform that maps detection anchors back into the frame the zone was drawn on. Any object with abs_to_rel and rel_to_abs works, as described by the new sv.CoordinatesTransformation protocol, including the transformations from the trackers motion estimator. Drawing is unchanged, and coord_transform=None keeps current results. (#2657)

import numpy as np
import supervision as sv

class CameraShift:
    def abs_to_rel(self, points): return points + [50, 0]
    def rel_to_abs(self, points): return points - [50, 0]

zone = sv.PolygonZone(polygon=np.array([[0, 0], [100, 0], [100, 100], [0, 100]]))
car = sv.Detections(xyxy=np.array([[120.0, 40.0, 140.0, 60.0]]))
zone.trigger(car)                                 # array([False])
zone.trigger(car, coord_transform=CameraShift())  # array([ True])

COCO keypoint mAP for pose models

sv.metrics.KeyPointMeanAveragePrecision scores sv.KeyPoints predictions by Object Keypoint Similarity at ten thresholds from 0.50 to 0.95, and its scores agree with pycocotools COCOeval(..., "keypoints"). COCO greedy matching is now vectorized for box and keypoint mAP. In the benchmark reported with that change, one image with 1000 predictions and a 1000-detection cap dropped from 35.9 s to 0.5 s. MeanAveragePrecision also takes max_detection_thresholds for scenes with more than 100 objects. (#2687, #2733, #2716)

import numpy as np
import supervision as sv
from supervision.metrics import KeyPointMeanAveragePrecision

targets = sv.KeyPoints(
    xy=np.array([[[10, 10], [60, 10], [35, 80]]], dtype=np.float32),
    class_id=np.array([0]),
    data={"area": np.array([4000.0])},
)
predictions = sv.KeyPoints(
    xy=np.array([[[11, 10], [60, 12], [35, 79]]], dtype=np.float32),
    class_id=np.array([0]),
    detection_confidence=np.array([0.9]),
)
metric = KeyPointMeanAveragePrecision(sigmas=[0.25, 0.25, 0.25])
metric.update(predictions, targets).compute().map50  # 1.0

More models, and the matcher behind the metrics

sv.Detections.from_vlm parses Kosmos-2 grounding results (sv.VLM.KOSMOS_2) and Gemini 3.6 and 3.7 structured boxes and polygon masks. sv.KeyPoints.from_mediapipe loads MediaPipe hand landmarks, with class_id 0 for a left hand and 1 for a right hand. sv.match_detections exposes the one-to-one greedy IoU matcher the metrics use, for comparing two models or auditing labels against predictions. (#1903, #2504, #2283, #2557)

import supervision as sv

caption = "a snowman next to a fire"
entities = [("a snowman", (0, 9), [(0.1, 0.2, 0.4, 0.9)]), ("a fire", (19, 25), [(0.5, 0.6, 0.8, 0.95)])]
detections = sv.Detections.from_vlm(sv.VLM.KOSMOS_2, (caption, entities), resolution_wh=(640, 480))

pairs, unmatched_a, unmatched_b = sv.match_detections(detections_a, detections_b)

🔄 Migration guide

No breaking changes beyond the APIs deprecated in 0.26–0.28 and scheduled for removal in 0.31.0. If 0.30.x printed no deprecation warnings for your code, only the four output changes at the end of this section can affect it.

Removed Use instead
sv.ByteTrack and the supervision.tracker package ByteTrackTracker from the trackers package (pip install trackers); call update() instead of update_with_detections()
supervision.keypoint supervision.key_points
sv.LMM, Detections.from_lmm sv.VLM, Detections.from_vlm
legacy sv.MeanAveragePrecision (supervision.metrics.detection) sv.metrics.MeanAveragePrecision
sv.denormalize_boxes(normalized_xyxy=...) sv.denormalize_boxes(xyxy=...)
supervision.dataset.utils.mask_to_rle / rle_to_mask sv.mask_to_rle / sv.rle_to_mask
ensure_cv2_image_for_annotation ensure_cv2_image_for_class_method (supervision.utils.conversion)
ensure_pil_image_for_annotation ensure_pil_image_for_class_method (supervision.utils.conversion)
ensure_cv2_image_for_processing ensure_cv2_image_for_standalone_function (supervision.utils.conversion)
create_tiles, overlay_image (also sv.overlay_image), validate_keypoint_confidence, validate_keypoints_fields no direct replacement
# before
tracker = sv.ByteTrack()
detections = tracker.update_with_detections(detections)
map_result = sv.MeanAveragePrecision.from_detections(predictions=predictions, targets=targets)

# after
from trackers import ByteTrackTracker
from supervision.metrics import MeanAveragePrecision

detections = ByteTrackTracker().update(detections)
map_result = MeanAveragePrecision().update(predictions, targets).compute()

Four behaviour changes can alter output: sv.Detections raises on non-finite boxes, sv.CSVSink writes arrays as JSON lists, ConfusionMatrix.from_detections rejects lists of different length, and multi-class mAR @ K scores follow COCO. Details under Changed and Fixed.

📝 Notable changes

🚀 Added

🌱 Changed

❌ Removed

  • APIs deprecated since 0.26.0–0.28.0 and scheduled for 0.31.0: sv.ByteTrack and the supervision.tracker package (use trackers.ByteTrackTracker), the supervision.keypoint module (use supervision.key_points), sv.LMM and Detections.from_lmm (use sv.VLM and from_vlm), the legacy sv.MeanAveragePrecision (use sv.metrics.MeanAveragePrecision), create_tiles, overlay_image, ensure_cv2_image_for_annotation, ensure_pil_image_for_annotation and ensure_cv2_image_for_processing (use the ensure_*_for_class_method / ensure_cv2_image_for_standalone_function decorators), validate_keypoint_confidence, validate_keypoints_fields, the normalized_xyxy argument of sv.denormalize_boxes (use xyxy), and the supervision.dataset.utils import path for mask_to_rle / rle_to_mask. (chore(deprecation): remove scheduled for removal in 0.31.0 [rebase&merge] #2582)

🔧 Fixed


🏆 Contributors

  • JANG BYUNGKUN (@8rulerstar) — added KeyPointMeanAveragePrecision and fixed perfect-prediction mAP scoring.
  • Caio Viotti (@cfviotti, LinkedIn) — added depth support: DepthMap, DepthAnnotator, DepthClipRange, DepthCamera and model loaders.
  • Kari Pikkarainen (@kari-pikkarainen, LinkedIn) — made zones follow camera motion with coord_transform.
  • Christoph Deil (@cdeil, LinkedIn) — added max_detection_thresholds to MeanAveragePrecision.
  • Raghav Rathi (@raghav-rathi, LinkedIn) — added mask targets to ConfusionMatrix.
  • shao (@shaoming11, LinkedIn) — added metric-result aggregation and sped up ComparisonAnnotator with compact masks.
  • David (@David-rn) — co-authored metric-result aggregation from the original proposal.
  • Jabrail (@jabrailkhalil) — added sv.match_detections.
  • Soumik Rakshit (@soumik12345, LinkedIn) — added Kosmos-2 support in from_vlm.
  • @Xayar145 — added Gemini 3.6 and 3.7 support in from_vlm.
  • @tarunbommawar27 — added MediaPipe hand landmarks to KeyPoints.from_mediapipe.
  • Advait Shukla (@AdvaitS) — made Detections reject non-finite or non-numeric boxes.
  • Avanish Garg (@avanish-garg, LinkedIn) — fixed CSVSink array output, CompactMask.resize and mask holes in dataset export.
  • Iuri de Silvio (@iurisilvio) — sped up Detections.from_inference with compact masks.
  • @trueoneplusone — sped up with_nmm for compact masks.
  • max (@quotentiroler) — vectorized COCO greedy matching in mAP.
  • A Aswanth Raj (@aswanth-07, LinkedIn) — fixed box_aspect_ratio overflow, CompactMask conversion and resize, single-point KeyPoints selection and NumPy-backed Ultralytics results.
  • Mohammad Hijjawi (@MohammadHijjawi97, LinkedIn) — fixed boolean-list Detections indexing and smart_position label overlap.
  • NIKHIL (@Nikhi00718) — fixed Ultralytics letterbox masks, grayscale blur and pixelate, process_video cleanup and box-area overflow in metrics.
  • kevin (@kevin9327) — fixed thick-line drawing without OpenCV and Gemini mask binarization, and typed the test suite.
  • Kaushik Reddy Lingireddy (@Lingikaushikreddy, LinkedIn) — fixed nearest-neighbour resize sampling without OpenCV.
  • peng xiang (@px12811) — fixed fillPoly rasterization without OpenCV.
  • Devulapalli Naga Sri Vaishnavi (@Vaishnavi220506) — fixed integer wrap in box translation and oriented-box mAP precision.
  • Muhammad Talha (@Talhax55z) — fixed per-class MeanAverageRecall scoring.
  • FootysHands (@ayo0la) — converted documentation examples to doctests.
  • Eesha (@eesha5) — fixed imports in docstring examples.
  • Jirka Borovec (@Borda, LinkedIn) — removed deprecated APIs, fixed from_vlm class_id dtype, followed up on with_nmm performance, and maintained docs, CI and release infrastructure.

Automated contributions: @dependabot, @pre-commit-ci, @copilot


Full changelog: 0.30.0...0.31.0

@Borda
Borda requested a balanced review from Copilot October 16, 2026 13:56
@Borda
Borda requested a review from SkalskiP as a code owner October 16, 2026 13:56
@Borda Borda added the enhancement New feature or request label Oct 16, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes are limited to consistent release metadata and documentation, with no unresolved blocking findings.

0 open findings

What changed in this PR

🟢 Approve — prepares Supervision 0.31.0 for release through version metadata and documentation updates, without changing library runtime logic.

Changes:

  • Finalizes the package version and release changelog.
  • Corrects RF-DETR examples for color order, video annotation, and benchmarking.
  • Documents Gemini formats, MediaPipe support, and compact-mask cropping.

No actionable issues remain. Coverage includes release consistency, examples, and documentation accuracy; tests were not rerun.

Quality: code 5/5 (focused changes), testing 3/5 (execution unverified), documentation 5/5 (clearer guidance). Overall risk: 1/5.

File Description
uv.lock Updates lock revision and release version.
src/​supervision/​utils/​video.py Corrects the RF-DETR video callback example.
src/​supervision/​key_points/​core.py Adds RGB conversion to RF-DETR examples.
src/​supervision/​detection/​tools/​inference_slicer.py Corrects tile color order in the example.
src/​supervision/​detection/​core.py Adds a Gemini structured-output example.
pyproject.toml Sets version to 0.31.0.
docs/​how_to/​use_compact_masks.md Clarifies cropping by mask encoding.
docs/​how_to/​benchmark_a_model.md Retains low-confidence predictions for evaluation.
docs/​faq.md Expands documented model support.
docs/​changelog.md Finalizes and organizes release notes.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94%. Comparing base (6ecb279) to head (4ee7f81).

Additional details and impacted files
@@           Coverage Diff           @@
##           develop   #2742   +/-   ##
=======================================
  Coverage       94%     94%           
=======================================
  Files           83      83           
  Lines        13489   13489           
=======================================
  Hits         12672   12672           
  Misses         817     817           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Borda
Borda merged commit 927dfeb into develop Oct 16, 2026
39 checks passed
@Borda
Borda deleted the releasing/0.31.0 branch October 16, 2026 18:22
@jabrailkhalil

Copy link
Copy Markdown
Contributor

Thanks for including match_detections and the release notes credit!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants