Re-verify remaining supervision review backlog against develop HEAD; most items were already resolved by an intervening commit, only genuinely-open gaps got new fixes.
Fix float32 precision loss in box_iou_batch for large coordinates (GeoTIFF-scale) by accumulating in float64.
Raise ValueError instead of a strippable assert in EvaluationDataset.load_predictions for unknown image ids.
Add HeatMapAnnotator.reset() to clear accumulated heat for annotator reuse.
Add missing coverage: labelme export basename collisions, _greedy_match matcher, metrics.core ABC/enum contracts, metrics.utils.utils pandas guard; remove a global RNG-seed pollution site in a metrics test.
Document the last two undocumented public exports (calculate_masks_centroids, is_compressed_rle) and add usage examples to 17 previously-example-less public functions/classes (NMS/NMM helpers, draw utils, PolygonZoneAnnotator, mask/polygon converters).
* tests: load_predictions ValueError branch + empty-dataset coverage
* fix: box_iou_batch int-dtype overflow, narrow float32 precision claim
* feat: add reset() to TraceAnnotator/DetectionsSmoother, fix docstrings
* docs: fix temp file leak in coco.py docstring, rename misnamed test
---------
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
- Added `sv.mask_to_roi` as an explicit migration path for exclusive mask bounds
- Fixed COCO, CreateML, and Pascal VOC export validation to reject ambiguous or colliding dataset paths before writing
- Fixed in-memory `DetectionDataset` split and merge behavior
- Fixed `supervision` imports to avoid loading ByteTrack until it is used
- Fixed detection conversion helpers to support coordinate-convention migration while preserving legacy inclusive defaults
- Fixed Azure tag mapping, anchor rounding, and line-zone smoothing to avoid incorrect or ghost detections
- Fixed video processing shutdown handling for timeout and full-queue cases
- Improved downloader, validator, documentation, and regression coverage for the shipped dataset, detection, annotator, image, and video behavior
---------
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- 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>
InferenceSlicer can now accept an open rasterio-style dataset and read each tile via a windowed read instead of loading the whole image into memory, enabling tiled inference on multi-GB aerial/drone GeoTIFFs. Detection is duck-typed so rasterio stays an optional dependency (supervision[geotiff]) and the library imports no rasterio symbols. Adds CRS projected validation and tests. Closes#2027.
- Add threading.Lock around raster.read() in _run_callback to prevent
data race when thread_workers > 1 shares a DatasetReader (GDAL releases
GIL inside GDALRasterIO — reads are genuinely concurrent C code)
- Return TypeGuard[WindowedRasterDataset] from _is_windowed_raster;
TYPE_CHECKING guard imports typing_extensions for Python 3.9 compat
- Add @runtime_checkable to WindowedRasterDataset Protocol; crs typed
as object|None; guard .is_projected via getattr(..., True)
- Extract _get_resolution_wh and _apply_overlap_filter helpers from
__call__ to bring cyclomatic complexity under PLR0912 limit (16 → ~4)
- Widen callback type to Callable[[NDArray[Any]], Detections] to accept
any dtype (uint16 raster tiles are not NDArray[uint8])
- Add Raises section to __call__ docstring for geographic CRS ValueError
- Add one-line summary to move_detections docstring
- Export WindowedRasterDataset from sv.__init__
- Move changelog entry from 0.29.1 (released) to UnReleased
- Add comment explaining rasterio>=1.3 lower bound in pyproject.toml
- Restructure tests: class grouping, parametrize CRS cases, add
docstrings; add compact_masks, thread_workers>1, single-band,
single-tile test cases
---------
Co-authored-by: madhavcodez <madhavcodez@users.noreply.github.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* fix(detection): OBB NMM now computes geometric union via min-area rotated rect
Previously with_nmm for OBB detections kept the winner's OBB geometry unchanged
(only confidence was merged), making it inconsistent with AABB NMM which expands
to the union envelope. Now computes cv2.minAreaRect over all N×4 corners from
the merge group — the MARC degenerates to the axis-aligned union for zero-rotation
OBBs, preserving full consistency with AABB NMM.
- Replace winner-OBB xyxy patch with MARC of all merged corners
- Update ORIENTED_BOX_COORDINATES in data to reflect merged geometry
- Rename test to reflect new expected behaviour (union, not winner AABB)
- Add consistency test asserting axis-aligned OBB NMM == AABB NMM xyxy
---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* code(detection): defensive reshape + clarify xyxy-override intent in OBB NMM
- Add .reshape(4, 2) to OBB corner extraction loop so flat-adjacent shapes are normalised before cv2.minAreaRect
- Add inline comment at xyxy override: OBB groups intentionally discard AABB-union xyxy from reduce() to stay consistent with MARC corners
---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* test(detection): expand OBB NMM coverage — rotated, 3-group, passthrough, class-agnostic, IOS, flat-format
- Add test_rotated_obb_merge_produces_marc: two 45-degree OBBs, assert MARC encompasses all corners
- Add test_three_detection_group_merge: three overlapping OBBs, assert merged len==1 and envelope spans all inputs
- Add test_single_detection_passthrough_preserves_obb: non-overlapping OBB passes through unchanged
- Add test_class_agnostic_obb_merge: class_agnostic=True merges cross-class OBBs
- Add test_overlap_metric_ios_obb_merge: IOS metric merges contained OBBs
- Add test_flat_n8_obb_format_raises_value_error: documents that (N,8) flat format is unsupported (canonical is (N,4,2))
- Import OverlapMetric for IOS test
---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* docs(detection): document OBB NMM MARC semantics in with_nmm + changelog entry
- Add Note section to with_nmm docstring explaining MARC behavior: union for zero-rotation OBBs, MARC for rotated OBBs, single-group passthrough
- Add changelog UnReleased entry for #2312 behavioral change
---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* fix(detection): OBB NMM uses winner's angle instead of free MARC to avoid overshoot
cv2.minAreaRect picks a 45-degree rect for diagonal staircase arrangements of
axis-aligned boxes, producing an AABB like [-10,-10,54,54] that extends outside
every input. Fix: lock merged OBB to winner's angle by projecting all corners
onto the winner's principal axes (from first edge vector), computing AABB there,
and back-rotating — for zero-rotation inputs this gives exactly the axis-aligned
union; for same-angle groups the result equals the prior MARC.
- Remove cv2 dependency from the OBB merge block (pure numpy now)
- Add test_diagonal_staircase_obb_merge_stays_within_union regression test
- Rename test to reflect winner-angle semantics
---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* fix(detection): fix changelog wording + add explicit OBB shape guard in NMM
- docs/changelog.md: replace stale MARC/cv2.minAreaRect wording with
winner's-angle description matching the actual implementation
- core.py: validate ORIENTED_BOX_COORDINATES shape is (N, 4, 2) at the
start of the OBB merge block; raises ValueError("corners must have
shape (N, 4, 2)") for flat (N, 8) input instead of silently mis-reshaping
---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
* refactor: parametrize OBB NMM tests in TestDetectionsWithNmm Consolidate 7 individual OBB NMM test methods into a single parametrized test_obb_nmm_merge with explicit expected_confidence and expected_corners assertions. Add cases for mixed-angle merges, multiple merge groups, and degenerate collinear OBBs. Add standalone test_obb_nmm_empty_detections for empty inputs.
* refactor(tests): simplify OBB NMM test cases by replacing `np.array` usage with nested lists
- Update test parameters to use plain Python lists instead of `numpy` arrays for corner definitions.
- Adjust the `_make_obb_detections` setup to preprocess corners into `numpy` arrays.
- Add explicit conversion of `expected_corners` to `numpy` arrays in the assertions.
* feat: add xyxyxyxy_to_xyxy utility for OBB-to-AABB conversion Vectorized conversion of oriented bounding box corners (N, 4, 2) to axis-aligned bounding boxes (N, 4). Used internally in with_nmm and exposed via top-level import.
* deprecate: mark merge_inner_detections_objects for removal in 0.34.0 Function is unused dead code with no external callers. Decorator emits FutureWarning while preserving existing behavior.
* refactor: extract _merge_obb_corners and _merge_detection_group from with_nmm Replace inline OBB post-processing and reduce-based merging with two private helpers using single-pass area-weighted confidence. Deprecate merge_inner_detection_object_pair and merge_inner_detections_objects_without_iou (0.29.0 -> 0.34.0). Rename TestDetectionsWithNmm -> TestDetectionsWithNMM and expand TestMergeDetectionGroup to assert all output fields via expected_detections.
---------
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: SkalskiP <piotr.skalski92@gmail.com>
* Detections.from_inference works on RLE-encoded masks
* Apply suggestions from code review
* fix: harden RLE handling in from_inference and decoder
* lint: fix cv2.fillPoly color type in polygon_to_mask
* fix: resize RLE mask to image dims when size mismatches
* fix: pass RLE counts directly in coco_annotations_to_masks
* test: document mixed RLE + box-only batch misalignment
* test: add compressed RLE iscrowd case to coco_annotations_to_detections
* fix: cast polygon mask to bool in process_roboflow_result
* fix: log warning when RLE decode fails in process_roboflow_result
* fix: replace assert with ValueError in rle_to_mask
* test: add bytes invalid UTF-8 case to rle_to_mask tests
* docs: note rle_to_mask dtype change from uint8 to bool in changelog
* refactor: tighten rle_to_mask NDArray input type to np.integer[Any]
* refactor: drop mask_to_rle overloads; cast at call site
* docs: clarify COCO column-major RLE order in rle_to_mask/mask_to_rle
* refactor: update @deprecated annotations and docstrings for mask_to_rle/rle_to_mask; add pydeprecate dependency
* refactor: replace mask_to_rle body with `void` function to suppress unused argument warnings
---------
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Wrap all placeholder paths in quotes across documentation and code examples for consistency
* Update pre-commit config to exclude `docs/deprecated.md` from mdformat check
* Chore CI by adding checks for links and references
* Potential fix for code scanning alert no. 6: Workflow does not contain permissions
* Fix markdown image formatting in metrics documentation
* Update all `docs` links to use absolute URLs and fix broken references in documentation and workflows.
* Fix broken `albumentations` links in dataset processing documentation
* lycheeVersion: v0.22.0
* Refactor CI link check workflow to use lychee config file for cleaner argument management
* add TODOs for future file type support
* Fix header formatting for example plots across metric files
---------
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Up to 20 tabs can be made at once. This is likely a bug relating to the underlying mkdocs plugin, but a quick check for hardcoded values yielded nothing.