fix(docs): resolve review deprecation follow-ups (#2415)
- Extend active deprecation removals to 0.31.0 and align deprecated API docs, changelog, and warnings. - Add missing reference docs for VLM, conversion helpers, geometry, metrics extras, and tracker deprecation notices. - Raise when ImageSink cannot write an image and cover the failure path with a regression test. - Correct conversion and deprecated docs to match exported names and restore KeyPoints.confidence. - Add regression coverage for SUPERVISION_DEPRECATION_WARNING precedence and document ImageSink.save_image() failure behavior. * test: add validation and behavior tests for Color, Position, and polygon approximation adjustments --------- Co-authored-by: Codex <codex@openai.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
072f78471c
commit
23a2227ae7
|
|
@ -75,7 +75,7 @@ For branching, commit, code style, and API design conventions see [CONTRIBUTING.
|
|||
|
||||
## 4. Deprecated Module Aliases
|
||||
|
||||
`supervision.keypoint` deprecated since `0.27.0`, removed in `0.30.0`. Always import from `supervision.key_points`, not `supervision.keypoint`.
|
||||
`supervision.keypoint` deprecated since `0.27.0`, removed in `0.31.0`. Always import from `supervision.key_points`, not `supervision.keypoint`.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,16 @@ date_modified: 2026-07-06
|
|||
- `sv.mask_non_max_merge` now computes exact mask overlap at the original mask resolution and ignores the deprecated `mask_dimension` parameter. Code that relied on downscaled mask overlap should recalibrate thresholds; passing `mask_dimension` positionally now emits a deprecation warning, and the parameter is scheduled for removal in `0.33.0` ([#2400](https://github.com/roboflow/supervision/pull/2400)).
|
||||
|
||||
### Fixed
|
||||
- Fixed: `sv.Color(...)` now validates direct RGBA channel values and raises `ValueError` when any channel falls outside the 0-255 byte range.
|
||||
- Fixed: `approximate_mask_with_polygons` now defaults to no polygon simplification, matching the public dataset export methods.
|
||||
- Fixed: `ImageSink.save_image()` now raises `OSError` when `cv2.imwrite()` fails, and deprecation-warning control accepts the correct `SUPERVISION_DEPRECATION_WARNING` environment variable while still honoring the legacy misspelled alias.
|
||||
- `sv.Classifications.from_timm` now softmaxes model logits before exposing confidence scores, matching `sv.Classifications.from_clip` and keeping timm confidences on a normalized probability scale. Thresholds calibrated against raw logits may need retuning.
|
||||
- `sv.download_assets` now verifies MD5 hashes after fresh downloads and retries once when the downloaded payload is corrupted instead of accepting a bad file.
|
||||
- Fixed metrics scoring edge cases: legacy `sv.MeanAveragePrecision` now uses COCO 101-point AP averaging, `sv.ConfusionMatrix` rejects invalid class ids instead of wrapping them through `int16`/negative indexing, `sv.MeanAveragePrecision` preserves user-provided target `ignore` flags, and `sv.MeanAverageRecallResult.recall_per_class` now exposes per-class recall for each max-detection cutoff.
|
||||
- Fixed [#2408](https://github.com/roboflow/supervision/pull/2408): `sv.Precision`, `sv.Recall`, `sv.F1Score`, and `sv.MeanAverageRecall` now score size buckets by filtering targets only while leaving predictions eligible to match bucket targets. This preserves bucket matches that would otherwise be stolen by out-of-bucket filtering and keeps mAR top-K ranking intact.
|
||||
- `sv.ByteTrack` no longer mutates input `Detections` while assigning tracker IDs. It now keeps detections at the activation-threshold boundary eligible for matching, avoids impossible new-track thresholds above score `1.0`, ignores invalid zero-area/non-finite tensor boxes before Kalman updates, and does not emit unconfirmed `-1` IDs from first-frame tensor updates.
|
||||
- Fixed [#2402](https://github.com/roboflow/supervision/pull/2402): `sv.KeyPoints.as_detections` now accepts NumPy arrays, tuples, and generators in `selected_keypoint_indices` without ambiguous truth-value errors; empty index iterables select all keypoints. Valid zero-area skeletons are preserved, while all-zero and non-finite-only skeletons are filtered out.
|
||||
- Changed: delayed `sv.ByteTrack`, `supervision.keypoint`, `normalized_xyxy` for `sv.denormalize_boxes`, and `supervision.dataset.utils` RLE compatibility removals from `supervision-0.30.0` to `supervision-0.31.0` so the deprecated APIs keep a full transition window.
|
||||
- Fixed [#2407](https://github.com/roboflow/supervision/pull/2407): `sv.ColorPalette.by_idx()` now raises a clear `ValueError` when called on an empty palette instead of leaking a `ZeroDivisionError`. Non-empty palettes keep the existing index-wrapping behavior.
|
||||
- Fixed [#2393](https://github.com/roboflow/supervision/pull/2393): `sv.CropAnnotator.annotate` no longer raises `cv2.error` when detections extend outside the scene; out-of-bounds boxes are clipped to scene bounds and zero-area results are skipped silently.
|
||||
- Fixed [#2393](https://github.com/roboflow/supervision/pull/2393): `sv.HeatMapAnnotator.annotate` no longer blanks the hottest region when the per-pixel hit count exceeds 255; the heat mask is now derived from the float32 accumulator directly, avoiding uint8 wrap-around.
|
||||
|
|
@ -202,11 +206,11 @@ date_modified: 2026-07-06
|
|||
|
||||
- Fixed [#1086](https://github.com/roboflow/supervision/pull/1086), [#265](https://github.com/roboflow/supervision/pull/265): COCO export and `force_masks` behaviour are now consistent across dataset formats. Empty polygons no longer raise during `as_coco`, and `force_masks=True` produces masks regardless of source format.
|
||||
|
||||
- Deprecated [#2215](https://github.com/roboflow/supervision/pull/2215): [`sv.ByteTrack`](https://supervision.roboflow.com/latest/trackers/#supervision.tracker.byte_tracker.core.ByteTrack) is deprecated in favour of `ByteTrackTracker` from the external [`trackers`](https://pypi.org/project/trackers/) package (`pip install trackers`). The update method is renamed from `update_with_detections()` to `update()`. Removal planned for `supervision-0.30.0`.
|
||||
- Deprecated [#2215](https://github.com/roboflow/supervision/pull/2215): [`sv.ByteTrack`](https://supervision.roboflow.com/latest/trackers/#supervision.tracker.byte_tracker.core.ByteTrack) is deprecated in favour of `ByteTrackTracker` from the external [`trackers`](https://pypi.org/project/trackers/) package (`pip install trackers`). The update method is renamed from `update_with_detections()` to `update()`. Removal is now planned for `supervision-0.31.0`.
|
||||
|
||||
- Deprecated [#2214](https://github.com/roboflow/supervision/pull/2214): `supervision.keypoint` module is deprecated; use `supervision.key_points` instead. `create_tiles` in `supervision.utils.image`, `ensure_cv2_image_for_processing` in `supervision.utils.conversion`, and keypoint validation utilities in `supervision.validators` are deprecated. The `LMM` enum (use `VLM`) and `from_lmm` method (use `from_vlm`) were deprecated in 0.26.0; this release migrates their deprecation mechanism to `pydeprecate`.
|
||||
|
||||
- Deprecated: `normalized_xyxy` argument in [`sv.denormalize_boxes`](https://supervision.roboflow.com/latest/detection/utils/boxes/#supervision.detection.utils.boxes.denormalize_boxes) renamed to `xyxy`. Passing `normalized_xyxy=` now emits a `FutureWarning`; support will be removed in `supervision-0.30.0`.
|
||||
- Deprecated: `normalized_xyxy` argument in [`sv.denormalize_boxes`](https://supervision.roboflow.com/latest/detection/utils/boxes/#supervision.detection.utils.boxes.denormalize_boxes) renamed to `xyxy`. Passing `normalized_xyxy=` now emits a `FutureWarning`; support will be removed in `supervision-0.31.0`.
|
||||
|
||||
### 0.27.0 <small>Nov 16, 2025</small>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,16 +7,17 @@ status: deprecated
|
|||
|
||||
These features are phased out due to better alternatives or potential issues in future versions. Deprecated functionalities are typically supported for multiple subsequent releases, providing time for users to transition to updated methods.
|
||||
|
||||
- [`sv.ByteTrack`](https://supervision.roboflow.com/latest/trackers/#supervision.tracker.byte_tracker.core.ByteTrack) is deprecated in favour of `ByteTrackTracker` from the external [`trackers`](https://pypi.org/project/trackers/) package (`pip install trackers`). The update method is renamed from `update_with_detections()` to `update()`. Removal planned for `supervision-0.30.0`.
|
||||
- `supervision.keypoint` module is deprecated; use `supervision.key_points` instead. Will be removed in `supervision-0.30.0`.
|
||||
- `create_tiles` in `supervision.utils.image` is deprecated. Will be removed in `supervision-0.31.0`.
|
||||
- `ensure_cv2_image_for_processing` in `supervision.utils.conversion` is deprecated. Will be removed in `supervision-0.31.0`.
|
||||
- Keypoint validation utilities in `supervision.validators` are deprecated. Will be removed in `supervision-0.31.0`.
|
||||
- `normalized_xyxy` argument in [`sv.denormalize_boxes`](https://supervision.roboflow.com/latest/detection/utils/boxes/#supervision.detection.utils.boxes.denormalize_boxes) is renamed to `xyxy`. Passing `normalized_xyxy=` emits a `FutureWarning`; support will be removed in `supervision-0.30.0`.
|
||||
- `supervision.dataset.utils` import path for [`sv.rle_to_mask`](https://supervision.roboflow.com/latest/detection/utils/converters/#supervision.detection.utils.converters.rle_to_mask) and [`sv.mask_to_rle`](https://supervision.roboflow.com/latest/detection/utils/converters/#supervision.detection.utils.converters.mask_to_rle) is deprecated. These functions moved to `supervision.detection.utils.converters`. Will be removed in `supervision-0.30.0`.
|
||||
- `sv.LMM` enum is deprecated and will be removed in `supervision-0.31.0`. Use `sv.VLM` instead.
|
||||
- [`sv.Detections.from_lmm`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_lmm) property is deprecated and will be removed in `supervision-0.31.0`. Use [`sv.Detections.from_vlm`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_vlm) instead.
|
||||
- Public `validate_*` helper functions are deprecated and will be removed in `supervision-0.31.0`. Supervision internals now use private `_validate_*` helpers.
|
||||
- [`sv.ByteTrack`](https://supervision.roboflow.com/latest/trackers/#supervision.tracker.byte_tracker.core.ByteTrack) is deprecated in `supervision-0.28.0` in favour of `ByteTrackTracker` from the external [`trackers`](https://pypi.org/project/trackers/) package (`pip install trackers`). The update method is renamed from `update_with_detections()` to `update()`. Removal is planned for `supervision-0.31.0`.
|
||||
- `supervision.keypoint` module is deprecated in `supervision-0.27.0`; use `supervision.key_points` instead. It will be removed in `supervision-0.31.0`.
|
||||
- `create_tiles` in `supervision.utils.image` is deprecated in `supervision-0.27.0`. It will be removed in `supervision-0.31.0`.
|
||||
- `ensure_cv2_image_for_processing` in `supervision.utils.conversion` is deprecated in `supervision-0.27.0`. It will be removed in `supervision-0.31.0`.
|
||||
- Keypoint validation utilities in `supervision.validators` are deprecated in `supervision-0.27.0`. They will be removed in `supervision-0.31.0`.
|
||||
- `normalized_xyxy` argument in [`sv.denormalize_boxes`](https://supervision.roboflow.com/latest/detection/utils/boxes/#supervision.detection.utils.boxes.denormalize_boxes) is deprecated in `supervision-0.27.0` and renamed to `xyxy`. Passing `normalized_xyxy=` emits a `FutureWarning`; support will be removed in `supervision-0.31.0`.
|
||||
- `supervision.dataset.utils` import path for [`sv.rle_to_mask`](https://supervision.roboflow.com/latest/detection/utils/converters/#supervision.detection.utils.converters.rle_to_mask) and [`sv.mask_to_rle`](https://supervision.roboflow.com/latest/detection/utils/converters/#supervision.detection.utils.converters.mask_to_rle) is deprecated in `supervision-0.28.0`. These functions moved to `supervision.detection.utils.converters` and will be removed from `supervision.dataset.utils` in `supervision-0.31.0`.
|
||||
- `sv.LMM` enum is deprecated in `supervision-0.27.0` and will be removed in `supervision-0.31.0`. Use `sv.VLM` instead.
|
||||
- [`sv.Detections.from_lmm`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_lmm) classmethod is deprecated in `supervision-0.26.0` and will be removed in `supervision-0.31.0`. Use [`sv.Detections.from_vlm`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_vlm) instead.
|
||||
- `KeyPoints.confidence` is deprecated in `supervision-0.29.0`. Use `KeyPoints.keypoint_confidence` instead. It will be removed in `supervision-0.32.0`.
|
||||
- Public `validate_*` helper functions are deprecated in `supervision-0.29.0` and will be removed in `supervision-0.32.0`. Supervision internals now use private `_validate_*` helpers.
|
||||
|
||||
# Removed
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@ comments: true
|
|||
|
||||
Starting with `0.23.0`, a new metrics module is being introduced to supervision. Metrics here are part of the legacy evaluation API and will be deprecated in the future.
|
||||
|
||||
Install the metrics extra before using this page's APIs:
|
||||
|
||||
```bash
|
||||
pip install "supervision[metrics]"
|
||||
```
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.metrics.detection.ConfusionMatrix">ConfusionMatrix</a></h2>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -45,4 +45,10 @@ print(len(detections))
|
|||
|
||||
GeoTIFF inputs must use a projected coordinate reference system. Reproject geographic rasters before passing them to `InferenceSlicer`.
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.detection.tools.inference_slicer.WindowedRasterDataset">WindowedRasterDataset</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.detection.tools.inference_slicer.WindowedRasterDataset
|
||||
|
||||
:::supervision.detection.tools.inference_slicer.InferenceSlicer
|
||||
|
|
|
|||
|
|
@ -3,7 +3,25 @@ comments: true
|
|||
status: new
|
||||
---
|
||||
|
||||
# VLMs Utils
|
||||
# VLM Utils
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.detection.vlm.VLM">VLM</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.detection.vlm.VLM
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.detection.vlm.LMM">LMM</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.detection.vlm.LMM
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.detection.vlm.validate_vlm_parameters">validate_vlm_parameters</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.detection.vlm.validate_vlm_parameters
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.detection.utils.vlms.edit_distance">edit_distance</a></h2>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ You can annotate images and video, filter detections, track objects, count objec
|
|||
|
||||
## How do I track objects across video frames?
|
||||
|
||||
Assign persistent tracker IDs before visualization. The built-in `sv.ByteTrack` wrapper accepts `Detections` through `update_with_detections()`. After tracking, combine the output with annotators such as `sv.TraceAnnotator`, `sv.BoxAnnotator`, and `sv.LabelAnnotator`.
|
||||
Assign persistent tracker IDs before visualization. The built-in `sv.ByteTrack` wrapper accepts `Detections` through `update_with_detections()`, but it is deprecated in favor of `ByteTrackTracker` from the external `trackers` package. After tracking, combine the output with annotators such as `sv.TraceAnnotator`, `sv.BoxAnnotator`, and `sv.LabelAnnotator`.
|
||||
|
||||
## What dataset formats does Supervision support?
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ Use `sv.PolygonZone` for arbitrary polygon regions and `sv.LineZone` for line-cr
|
|||
|
||||
## How do I benchmark a model?
|
||||
|
||||
Use `supervision.metrics.mean_average_precision.MeanAveragePrecision` for mAP and `sv.ConfusionMatrix` for confusion matrices. Accumulate predictions and ground-truth `Detections`, then call `compute()` to calculate metrics.
|
||||
Install `supervision[metrics]`, then use `supervision.metrics.mean_average_precision.MeanAveragePrecision` for mAP and `sv.ConfusionMatrix` for confusion matrices. Accumulate predictions and ground-truth `Detections`, then call `compute()` to calculate metrics.
|
||||
|
||||
## Is Supervision free to use?
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,10 @@ We will define a `callback` function, which will process each frame of the video
|
|||
|
||||
After running inference and obtaining predictions, the next step is to track the detected objects throughout the video. Utilizing Supervision’s [`sv.ByteTrack`](https://supervision.roboflow.com/latest/trackers/#supervision.tracker.byte_tracker.core.ByteTrack) functionality, each detected object is assigned a unique tracker ID, enabling the continuous following of the object's motion path across different frames.
|
||||
|
||||
!!! warning "Deprecated tracker wrapper"
|
||||
|
||||
`sv.ByteTrack` is deprecated in favor of `ByteTrackTracker` from the external `trackers` package. The external tracker uses `update()` instead of `update_with_detections()`.
|
||||
|
||||
=== "Ultralytics"
|
||||
|
||||
```{ .py hl_lines="6 12" }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@ comments: true
|
|||
|
||||
This page contains supplementary values, types and enums that metrics use.
|
||||
|
||||
Install the metrics extra before using metrics APIs:
|
||||
|
||||
```bash
|
||||
pip install "supervision[metrics]"
|
||||
```
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.metrics.core.MetricTarget">MetricTarget</a></h2>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,12 @@ comments: true
|
|||
|
||||
# F1 Score
|
||||
|
||||
Install the metrics extra before using this API:
|
||||
|
||||
```bash
|
||||
pip install "supervision[metrics]"
|
||||
```
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.metrics.f1_score.F1Score">F1Score</a></h2>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
---
|
||||
comments: true
|
||||
description: API reference for MeanAveragePrecision — compute mAP for object detection benchmarking with bounding boxes.
|
||||
description: API reference for MeanAveragePrecision — compute mAP for object detection benchmarking with boxes, masks, and oriented boxes.
|
||||
---
|
||||
|
||||
# Mean Average Precision
|
||||
|
||||
Install the metrics extra before using this API:
|
||||
|
||||
```bash
|
||||
pip install "supervision[metrics]"
|
||||
```
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.metrics.mean_average_precision.MeanAveragePrecision">MeanAveragePrecision</a></h2>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,12 @@ comments: true
|
|||
|
||||
# Mean Average Recall
|
||||
|
||||
Install the metrics extra before using this API:
|
||||
|
||||
```bash
|
||||
pip install "supervision[metrics]"
|
||||
```
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.metrics.mean_average_recall.MeanAverageRecall">MeanAverageRecall</a></h2>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,12 @@ comments: true
|
|||
|
||||
# Precision
|
||||
|
||||
Install the metrics extra before using this API:
|
||||
|
||||
```bash
|
||||
pip install "supervision[metrics]"
|
||||
```
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.metrics.precision.Precision">Precision</a></h2>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,12 @@ comments: true
|
|||
|
||||
# Recall
|
||||
|
||||
Install the metrics extra before using this API:
|
||||
|
||||
```bash
|
||||
pip install "supervision[metrics]"
|
||||
```
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.metrics.recall.Recall">Recall</a></h2>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
---
|
||||
comments: true
|
||||
description: API reference for supervision's object trackers — ByteTrack and SORT implementations that assign persistent IDs across video frames.
|
||||
description: API reference for supervision's deprecated ByteTrack tracker wrapper.
|
||||
---
|
||||
|
||||
# ByteTrack
|
||||
|
||||
!!! warning "Deprecated"
|
||||
|
||||
`sv.ByteTrack` is deprecated in `supervision-0.28.0` and will be removed in `supervision-0.31.0`. Install `trackers` and use `ByteTrackTracker` instead.
|
||||
|
||||
:::supervision.tracker.byte_tracker.core.ByteTrack
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
comments: true
|
||||
status: new
|
||||
---
|
||||
|
||||
# Conversion Utils
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.utils.conversion.cv2_to_pillow">cv2_to_pillow</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.utils.conversion.cv2_to_pillow
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.utils.conversion.pillow_to_cv2">pillow_to_cv2</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.utils.conversion.pillow_to_cv2
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.utils.conversion.ensure_cv2_image_for_annotation">ensure_cv2_image_for_annotation</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.utils.conversion.ensure_cv2_image_for_annotation
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.utils.conversion.ensure_pil_image_for_annotation">ensure_pil_image_for_annotation</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.utils.conversion.ensure_pil_image_for_annotation
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.utils.conversion.images_to_cv2">images_to_cv2</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.utils.conversion.images_to_cv2
|
||||
|
|
@ -13,3 +13,21 @@ comments: true
|
|||
</div>
|
||||
|
||||
:::supervision.geometry.core.Position
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.geometry.core.Point">Point</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.geometry.core.Point
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.geometry.core.Rect">Rect</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.geometry.core.Rect
|
||||
|
||||
<div class="md-typeset">
|
||||
<h2><a href="#supervision.geometry.core.Vector">Vector</a></h2>
|
||||
</div>
|
||||
|
||||
:::supervision.geometry.core.Vector
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ nav:
|
|||
- Boxes: detection/utils/boxes.md
|
||||
- Masks: detection/utils/masks.md
|
||||
- Polygons: detection/utils/polygons.md
|
||||
- VLMs: detection/utils/vlms.md
|
||||
- VLM Utils: detection/utils/vlms.md
|
||||
- Keypoint Detection:
|
||||
- Core: keypoint/core.md
|
||||
- Annotators: keypoint/annotators.md
|
||||
|
|
@ -77,6 +77,7 @@ nav:
|
|||
- Common Values: metrics/common_values.md
|
||||
- Legacy Metrics: detection/metrics.md
|
||||
- Utils:
|
||||
- Conversion: utils/conversion.md
|
||||
- Video: utils/video.md
|
||||
- Image: utils/image.md
|
||||
- Iterables: utils/iterables.md
|
||||
|
|
@ -86,6 +87,9 @@ nav:
|
|||
- Geometry: utils/geometry.md
|
||||
- Assets: assets.md
|
||||
- Cookbooks: cookbooks.md
|
||||
- Contributing: contributing.md
|
||||
- Code of Conduct: code_of_conduct.md
|
||||
- License: license.md
|
||||
- Changelog:
|
||||
- Changelog: changelog.md
|
||||
- Deprecated: deprecated.md
|
||||
|
|
|
|||
|
|
@ -30,20 +30,26 @@ from supervision.detection.utils.polygons import (
|
|||
)
|
||||
|
||||
|
||||
@deprecated(target=_mask_to_rle, deprecated_in="0.28.0", remove_in="0.30.0") # type: ignore[untyped-decorator]
|
||||
@deprecated(target=_mask_to_rle, deprecated_in="0.28.0", remove_in="0.31.0") # type: ignore[untyped-decorator]
|
||||
def mask_to_rle(
|
||||
mask: npt.NDArray[np.bool_], compressed: bool = False
|
||||
) -> list[int] | str:
|
||||
"""Deprecated. Use `supervision.detection.utils.converters.mask_to_rle`."""
|
||||
"""Deprecated since 0.28.0.
|
||||
|
||||
Use `supervision.detection.utils.converters.mask_to_rle`.
|
||||
"""
|
||||
return cast(list[int] | str, void(mask, compressed))
|
||||
|
||||
|
||||
@deprecated(target=_rle_to_mask, deprecated_in="0.28.0", remove_in="0.30.0") # type: ignore[untyped-decorator]
|
||||
@deprecated(target=_rle_to_mask, deprecated_in="0.28.0", remove_in="0.31.0") # type: ignore[untyped-decorator]
|
||||
def rle_to_mask(
|
||||
rle: npt.NDArray[np.integer] | list[int] | str | bytes,
|
||||
resolution_wh: tuple[int, int],
|
||||
) -> npt.NDArray[np.bool_]:
|
||||
"""Deprecated. Use `supervision.detection.utils.converters.rle_to_mask`."""
|
||||
"""Deprecated since 0.28.0.
|
||||
|
||||
Use `supervision.detection.utils.converters.rle_to_mask`.
|
||||
"""
|
||||
return cast(npt.NDArray[np.bool_], void(rle, resolution_wh))
|
||||
|
||||
|
||||
|
|
@ -57,8 +63,13 @@ def approximate_mask_with_polygons(
|
|||
mask: npt.NDArray[np.bool_],
|
||||
min_image_area_percentage: float = 0.0,
|
||||
max_image_area_percentage: float = 1.0,
|
||||
approximation_percentage: float = 0.75,
|
||||
approximation_percentage: float = 0.0,
|
||||
) -> list[npt.NDArray[np.number]]:
|
||||
"""Filter mask polygons by area and optionally simplify them.
|
||||
|
||||
The default `approximation_percentage=0.0` preserves the original contour
|
||||
unless callers explicitly ask for simplification.
|
||||
"""
|
||||
height, width = mask.shape
|
||||
image_area = height * width
|
||||
minimum_detection_area = min_image_area_percentage * image_area
|
||||
|
|
|
|||
|
|
@ -351,6 +351,13 @@ class LineZone:
|
|||
|
||||
|
||||
class LineZoneAnnotator:
|
||||
"""
|
||||
Draw a `LineZone` and its in/out counts on a video frame.
|
||||
|
||||
Use this annotator after calling `LineZone.trigger` so the rendered counts
|
||||
reflect the latest tracked detections.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
thickness: int = 2,
|
||||
|
|
@ -740,6 +747,13 @@ class LineZoneAnnotator:
|
|||
|
||||
|
||||
class LineZoneAnnotatorMulticlass:
|
||||
"""
|
||||
Draw per-class crossing counts for one or more `LineZone` instances.
|
||||
|
||||
The annotator renders a table with one row per line zone and one column per
|
||||
class observed by the zones.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ def pad_boxes(
|
|||
@deprecated( # type: ignore[untyped-decorator]
|
||||
target=TargetMode.ARGS_REMAP,
|
||||
deprecated_in="0.27.0",
|
||||
remove_in="0.30.0",
|
||||
remove_in="0.31.0",
|
||||
args_mapping={"normalized_xyxy": "xyxy"},
|
||||
)
|
||||
def denormalize_boxes(
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ class LMM(Enum):
|
|||
"""
|
||||
Enum specifying supported Large Multimodal Models (LMMs).
|
||||
|
||||
.. deprecated:: 0.27.0
|
||||
!!! deprecated "Deprecated"
|
||||
|
||||
`LMM` is deprecated and will be removed in `supervision-0.31.0`.
|
||||
Use `VLM` instead.
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,19 @@ class Color:
|
|||
b: int
|
||||
a: int = 255
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Validate that direct Color construction uses byte-sized channels."""
|
||||
if not (
|
||||
0 <= self.r <= 255
|
||||
and 0 <= self.g <= 255
|
||||
and 0 <= self.b <= 255
|
||||
and 0 <= self.a <= 255
|
||||
):
|
||||
raise ValueError(
|
||||
"Color values must be in range 0-255, "
|
||||
f"got ({self.r}, {self.g}, {self.b}, {self.a})"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_hex(cls, color_hex: str) -> Color:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ class Position(Enum):
|
|||
|
||||
@classmethod
|
||||
def list(cls) -> list[str]:
|
||||
return list(map(lambda c: c.value, cls))
|
||||
"""Return all position values in their definition order."""
|
||||
return [position.value for position in cls]
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -174,18 +175,22 @@ class Rect:
|
|||
|
||||
@classmethod
|
||||
def from_xyxy(cls, xyxy: tuple[float, float, float, float]) -> Rect:
|
||||
"""Create a rectangle from `(x_min, y_min, x_max, y_max)` coordinates."""
|
||||
x1, y1, x2, y2 = xyxy
|
||||
return cls(x=x1, y=y1, width=x2 - x1, height=y2 - y1)
|
||||
|
||||
@property
|
||||
def top_left(self) -> Point:
|
||||
"""Return the top-left corner as a `Point`."""
|
||||
return Point(x=self.x, y=self.y)
|
||||
|
||||
@property
|
||||
def bottom_right(self) -> Point:
|
||||
"""Return the bottom-right corner as a `Point`."""
|
||||
return Point(x=self.x + self.width, y=self.y + self.height)
|
||||
|
||||
def pad(self, padding: int) -> Rect:
|
||||
"""Return a rectangle expanded by `padding` pixels on every side."""
|
||||
return Rect(
|
||||
x=self.x - padding,
|
||||
y=self.y - padding,
|
||||
|
|
@ -194,6 +199,7 @@ class Rect:
|
|||
)
|
||||
|
||||
def as_xyxy_int_tuple(self) -> tuple[int, int, int, int]:
|
||||
"""Return `(x_min, y_min, x_max, y_max)` coordinates as integers."""
|
||||
return (
|
||||
int(self.x),
|
||||
int(self.y),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from supervision.utils.internal import warn_deprecated
|
|||
|
||||
warn_deprecated(
|
||||
"The 'supervision.keypoint' module is deprecated in `0.27.0` and will be removed "
|
||||
"in `0.30.0`. Please use 'supervision.key_points' instead."
|
||||
"in `0.31.0`. Please use 'supervision.key_points' instead."
|
||||
)
|
||||
|
||||
from supervision.key_points.annotators import (
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from supervision.utils.internal import warn_deprecated
|
|||
|
||||
warn_deprecated(
|
||||
"The 'supervision.keypoint' module is deprecated in `0.27.0` and will be removed "
|
||||
"in `0.30.0`. Please use 'supervision.key_points' instead."
|
||||
"in `0.31.0`. Please use 'supervision.key_points' instead."
|
||||
)
|
||||
|
||||
from supervision.key_points.annotators import ( # noqa: E402, F401
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from supervision.utils.internal import warn_deprecated
|
|||
|
||||
warn_deprecated(
|
||||
"The 'supervision.keypoint' module is deprecated in `0.27.0` and will be removed "
|
||||
"in `0.30.0`. Please use 'supervision.key_points' instead."
|
||||
"in `0.31.0`. Please use 'supervision.key_points' instead."
|
||||
)
|
||||
|
||||
from supervision.key_points.core import KeyPoints # noqa: E402, F401
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class MeanAveragePrecisionResult:
|
|||
"""
|
||||
The result of the Mean Average Precision calculation.
|
||||
|
||||
Defaults to `0` when no detections or targets are present.
|
||||
Returns `-1` sentinel scores when no detections or targets are present.
|
||||
|
||||
Attributes:
|
||||
metric_target: the type of data used for the metric -
|
||||
|
|
|
|||
|
|
@ -26,15 +26,16 @@ def _valid_tracking_tensors(
|
|||
@deprecated_class(
|
||||
target=TargetMode.NOTIFY,
|
||||
deprecated_in="0.28.0",
|
||||
remove_in="0.30.0",
|
||||
remove_in="0.31.0",
|
||||
)
|
||||
class ByteTrack:
|
||||
"""
|
||||
Initialize the ByteTrack object.
|
||||
|
||||
.. deprecated:: 0.28.0
|
||||
!!! deprecated "Deprecated"
|
||||
|
||||
`ByteTrack` is deprecated since `supervision-0.28.0` and will be removed in
|
||||
`supervision-0.30.0`. Use `ByteTrackTracker` from the `trackers` package
|
||||
`supervision-0.31.0`. Use `ByteTrackTracker` from the `trackers` package
|
||||
instead (`pip install trackers`). Note: the update method is renamed from
|
||||
`update_with_detections()` to `update()`.
|
||||
|
||||
|
|
|
|||
|
|
@ -521,6 +521,13 @@ def get_image_resolution_wh(image: ImageType) -> tuple[int, int]:
|
|||
|
||||
|
||||
class ImageSink:
|
||||
"""
|
||||
Save sequential images into a directory through a context manager.
|
||||
|
||||
`ImageSink` creates the target directory on entry and writes each image
|
||||
using `save_image`, incrementing the image name pattern after every save.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
target_dir_path: str,
|
||||
|
|
@ -582,12 +589,16 @@ class ImageSink:
|
|||
image_name: Custom filename for saved image. If
|
||||
`None`, generates name using `image_name_pattern`. Defaults to
|
||||
`None`.
|
||||
|
||||
Raises:
|
||||
OSError: If `cv2.imwrite` cannot write the image to disk.
|
||||
"""
|
||||
if image_name is None:
|
||||
image_name = self.image_name_pattern.format(self.image_count)
|
||||
|
||||
image_path = os.path.join(self.target_dir_path, image_name)
|
||||
cv2.imwrite(image_path, image)
|
||||
if not cv2.imwrite(image_path, image):
|
||||
raise OSError(f"Failed to save image to path: {image_path}")
|
||||
self.image_count += 1
|
||||
|
||||
def __exit__(
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ from typing import Any, Generic, TypeVar
|
|||
class SupervisionWarnings(Warning):
|
||||
"""Supervision warning category.
|
||||
Set the deprecation warnings visibility for Supervision library.
|
||||
You can set the environment variable SUPERVISON_DEPRECATION_WARNING to '0' to
|
||||
disable the deprecation warnings.
|
||||
You can set the environment variable SUPERVISION_DEPRECATION_WARNING to '0'
|
||||
to disable the deprecation warnings. The legacy misspelled
|
||||
SUPERVISON_DEPRECATION_WARNING variable is still accepted.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
|
@ -30,7 +31,11 @@ def format_warning(
|
|||
return f"{category.__name__}: {message}\n"
|
||||
|
||||
|
||||
if os.getenv("SUPERVISON_DEPRECATION_WARNING") == "0":
|
||||
deprecation_warning_env = os.getenv(
|
||||
"SUPERVISION_DEPRECATION_WARNING",
|
||||
os.getenv("SUPERVISON_DEPRECATION_WARNING"),
|
||||
)
|
||||
if deprecation_warning_env == "0":
|
||||
warnings.simplefilter("ignore", SupervisionWarnings)
|
||||
else:
|
||||
warnings.simplefilter("always", SupervisionWarnings)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@ from contextlib import ExitStack as DoesNotRaise
|
|||
from pathlib import Path
|
||||
from typing import TypeVar
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import supervision.dataset.utils as dataset_utils
|
||||
from supervision import Detections
|
||||
from supervision.dataset.utils import (
|
||||
approximate_mask_with_polygons,
|
||||
build_class_index_mapping,
|
||||
check_no_basename_collisions,
|
||||
map_detections_class_id,
|
||||
|
|
@ -90,6 +93,24 @@ def test_train_test_split(
|
|||
assert result == expected_result
|
||||
|
||||
|
||||
def test_approximate_mask_with_polygons_default_preserves_polygon(
|
||||
monkeypatch,
|
||||
) -> None:
|
||||
"""Default mask polygon conversion forwards zero simplification."""
|
||||
percentages: list[float] = []
|
||||
|
||||
def fake_approximate_polygon(polygon: np.ndarray, percentage: float) -> np.ndarray:
|
||||
"""Capture simplification percentage while preserving the polygon."""
|
||||
percentages.append(percentage)
|
||||
return polygon
|
||||
|
||||
monkeypatch.setattr(dataset_utils, "approximate_polygon", fake_approximate_polygon)
|
||||
|
||||
approximate_mask_with_polygons(np.ones((3, 3), dtype=bool))
|
||||
|
||||
assert percentages == [0.0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("class_lists", "expected_result", "exception"),
|
||||
[
|
||||
|
|
|
|||
|
|
@ -253,6 +253,23 @@ def test_color_from_bgra_tuple(
|
|||
assert result == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"kwargs",
|
||||
[
|
||||
pytest.param({"r": -1, "g": 0, "b": 0}, id="red-negative"),
|
||||
pytest.param({"r": 0, "g": 256, "b": 0}, id="green-too-large"),
|
||||
pytest.param({"r": 0, "g": 0, "b": 300}, id="blue-too-large"),
|
||||
pytest.param({"r": 0, "g": 0, "b": 0, "a": -1}, id="alpha-negative"),
|
||||
],
|
||||
)
|
||||
def test_color_constructor_rejects_out_of_range_channels(
|
||||
kwargs: dict[str, int],
|
||||
) -> None:
|
||||
"""Direct Color construction rejects channels outside the byte range."""
|
||||
with pytest.raises(ValueError, match="Color values must be in range"):
|
||||
Color(**kwargs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("color", "expected_result", "exception"),
|
||||
[
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
import pytest
|
||||
|
||||
from supervision.geometry.core import Point, Vector
|
||||
from supervision.geometry.core import Point, Position, Vector
|
||||
|
||||
|
||||
def test_position_list_returns_enum_values_in_definition_order() -> None:
|
||||
"""Position.list returns stable string values for public option lists."""
|
||||
assert Position.list() == [position.value for position in Position]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import warnings
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import pytest
|
||||
from PIL import Image, ImageChops
|
||||
|
||||
from supervision.utils.image import (
|
||||
ImageSink,
|
||||
_overlay_image,
|
||||
crop_image,
|
||||
get_image_resolution_wh,
|
||||
|
|
@ -271,6 +273,17 @@ def test_get_image_resolution_wh(image, expected) -> None:
|
|||
assert resolution == expected
|
||||
|
||||
|
||||
def test_image_sink_raises_when_cv2_write_fails(monkeypatch, tmp_path) -> None:
|
||||
"""ImageSink.save_image raises and keeps count stable when OpenCV write fails."""
|
||||
monkeypatch.setattr(cv2, "imwrite", lambda *_: False)
|
||||
|
||||
with ImageSink(str(tmp_path)) as sink:
|
||||
with pytest.raises(OSError, match="Failed to save image"):
|
||||
sink.save_image(np.zeros((2, 2, 3), dtype=np.uint8))
|
||||
|
||||
assert sink.image_count == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("func", "kwargs"),
|
||||
[
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import warnings
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from dataclasses import dataclass, field
|
||||
|
|
@ -78,6 +82,38 @@ class MockDataclass:
|
|||
return 2
|
||||
|
||||
|
||||
def _warning_messages_for_env(
|
||||
*, new_env: str | None, legacy_env: str | None
|
||||
) -> list[str]:
|
||||
"""Run the deprecation-warning path under a controlled environment."""
|
||||
env = os.environ.copy()
|
||||
env.pop("SUPERVISION_DEPRECATION_WARNING", None)
|
||||
env.pop("SUPERVISON_DEPRECATION_WARNING", None)
|
||||
if new_env is not None:
|
||||
env["SUPERVISION_DEPRECATION_WARNING"] = new_env
|
||||
if legacy_env is not None:
|
||||
env["SUPERVISON_DEPRECATION_WARNING"] = legacy_env
|
||||
|
||||
script = """
|
||||
import json
|
||||
import warnings
|
||||
from supervision.utils.internal import warn_deprecated
|
||||
|
||||
with warnings.catch_warnings(record=True) as recorded:
|
||||
warn_deprecated("deprecated")
|
||||
|
||||
print(json.dumps([str(item.message) for item in recorded]))
|
||||
"""
|
||||
completed = subprocess.run( # noqa: S603 - trusted fixed command in a test helper.
|
||||
[sys.executable, "-c", script],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=env,
|
||||
)
|
||||
return json.loads(completed.stdout)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("input_instance", "include_properties", "expected", "exception"),
|
||||
[
|
||||
|
|
@ -210,3 +246,19 @@ def test_supervision_warning_formatter_is_not_global() -> None:
|
|||
assert format_warning("message", SupervisionWarnings, "file.py", 1) == (
|
||||
"SupervisionWarnings: message\n"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("new_env", "legacy_env", "expected_count"),
|
||||
[
|
||||
pytest.param("0", "1", 0, id="prefer-new-env"),
|
||||
pytest.param(None, "0", 0, id="legacy-fallback"),
|
||||
pytest.param("1", "0", 1, id="new-env-enables-warning"),
|
||||
],
|
||||
)
|
||||
def test_supervision_warning_env_var_controls_deprecation_warnings(
|
||||
new_env: str | None, legacy_env: str | None, expected_count: int
|
||||
) -> None:
|
||||
"""SUPERVISION_DEPRECATION_WARNING keeps precedence over the legacy alias."""
|
||||
messages = _warning_messages_for_env(new_env=new_env, legacy_env=legacy_env)
|
||||
assert len(messages) == expected_count
|
||||
|
|
|
|||
Loading…
Reference in New Issue