Commit Graph

718 Commits

Author SHA1 Message Date
Jirka Borovec 813c4295bf
releasing `0.30.0` (#2462) 2026-08-04 16:22:04 +02:00
Arthi Arumugam 7fc91180fe
fix(metrics): track prediction-only classes in Recall (#2468)
#2331 made Precision and F1Score include classes that appear only in
predictions, and added regression tests to both. Recall was not touched, so
the line #2331 replaced is still there and the three metrics disagree about
which classes exist for identical input:

    precision.matched_classes -> [0 1]   precision_per_class (2, 10)
    recall.matched_classes    -> [0]     recall_per_class    (1, 10)
    f1.matched_classes        -> [0 1]

These read as parallel outputs, so zipping them silently truncates rather
than raising.

Recall for a class with no ground-truth instances is 0.0 rather than
undefined, which is what sklearn reports (it infers labels from the union of
y_true and y_pred) and what #2331 cited as its own standard. MICRO is
unchanged because an absent class contributes no false negatives, and
WEIGHTED is unchanged because its ground-truth support is zero. MACRO does
change, and the changelog says so.

Also of note: recall.py already carried #2331's WEIGHTED zero-support guard,
whose comment refers to 'only false-positive classes'. That state could not
arise in recall.py, because unique_classes came from ground truth alone. The
guard was propagated; the union that gives it meaning was not.

Addresses the review on #2468. Building the class union inside
_compute_recall_for_classes only covers samples that reach it, and samples with
predictions but no targets are skipped earlier in _compute. So matched_classes
could still disagree with Precision and F1Score for list inputs containing a
background image, which is the exact invariant the new test asserts.

Before, for one normal sample plus one background image predicting class 2:

    precision.matched_classes -> [0 2]
    recall.matched_classes    -> [0]

Recall now handles len(targets) == 0 and len(predictions) > 0 the way Precision
does. No recall value changes, since a background image produces no false
negatives; only the tracked class set does.

* test: cover Recall bg-image size-bucket, dup & non-contiguous ids
* docs: strengthen Recall changelog migration note
* docs+perf: Recall doctest example; dedupe-then-union micro-opt

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@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: OpenAI Codex <codex@openai.com>
2026-08-03 20:57:05 +02:00
Jirka Borovec f2efc328f7
fix(dataset): 3D empty mask for VOC background (#2469)
- `detections_from_xml_obj` now builds `np.empty((0, H, W))` for a background image under `force_masks=True` instead of letting `np.array([])` collapse to shape `(0,)`, which failed `Detections` mask validation
- document the forced `class_id` `dtype=int` with an inline comment and state the integer-dtype guarantee in the `detections_from_xml_obj` docstring Returns section
- add background-image coverage: force_masks empty 3D mask, all-background dataset, background-first ordering, and save-then-load round-trip
- add changelog entry for the `force_masks=True` background-image mask fix

---

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-08-03 18:30:24 +02:00
Shadow_Lu 1a2b9b24db
fix(dataset): keep `class_id` integral for VOC background images (#2463)
detections_from_xml_obj built class_id with np.array(...) over a list of
indices. For an annotation file with no object elements that list is empty,
so NumPy inferred float64 and DetectionDataset validation rejected the
resulting Detections, making any Pascal VOC dataset that contains an
unannotated image impossible to load.
2026-08-03 12:17:01 +02:00
Jirka Borovec 794971ba0f
feat(cv2): remove OpenCV dependency (#2443)
* feat(cv2): remove OpenCV dependency
* ci(tests): cover ambient cv2 wheels
* fix(cv2): restore fallback CI
* ci(tests): simplify pytest job name formatting
* ci(tests): refactor cv2 backend check for readability and set Python shell explicitly
* test(cv2): stabilize OpenCV parity checks
* ci(tests): fix Python 3.13 matrix typo in CI workflow
* scope OpenCV-absence check to declared deps/extras
* normalize whitespace in release-doc phrase assertions
* fix(ci): strip manifest line before comment check
* emit `UserWarning` when OpenCV is missing to alert users of fallback behavior

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-31 22:19:33 +02:00
Erik 541b0226cd
feat: add image URL loader (#2372)
- Added image loading from HTTP and HTTPS URLs with descriptive URL validation errors
- Added optional caching for image URL loads using the shared Supervision cache
- Improved URL downloads with atomic file replacement and shared download behavior across image loading and asset downloads
- Updated image decoding compatibility with Pillow fallbacks when OpenCV decoding or encoding is unavailable

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-07-28 21:24:55 +02:00
Andrew Barnes e138f6c544
Fix sink state when instances are reopened (#2459)
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-07-28 10:11:06 +02:00
pre-commit-ci[bot] 5f0654e5cc
chore(pre_commit): ⬆ pre_commit autoupdate (#2460)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/rbubley/mirrors-prettier: v3.9.5 → v3.9.6](https://github.com/rbubley/mirrors-prettier/compare/v3.9.5...v3.9.6)
- [github.com/tox-dev/pyproject-fmt: v2.25.3 → v2.26.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.25.3...v2.26.0)
- [github.com/astral-sh/ruff-pre-commit: v0.15.22 → v0.16.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.22...v0.16.0)

* test(detection): fix type hint for `expected_results` in VLM tests

* fix(pre_commit): 🎨 auto format pre-commit hooks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
2026-07-28 10:01:41 +02:00
Jirka Borovec bcbe8de1e4
chore(pre-commit): remove unnecessary exclude rule for changelog... (#2452)
* chore(pre-commit): remove unnecessary exclude rule for changelog and deprecated docs
* docs(changelog): reformat code blocks for consistency and clarity
* docs(changelog): reformat and align code blocks for consistent indentation and readability
* chore(pre-commit): update mdformat hooks to include gfm and frontmatter extensions
* chore(pre-commit): split mdformat hook into gfm and mkdocs variants
* docs(changelog): fix nested code fences breaking mdformat-mkdocs
* fix(pre_commit): 🎨 auto format pre-commit hooks

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-21 19:33:35 +02:00
Piotr Skalski 9837c17878
feat(vlm): add Gemini 3.5 Flash parsing support (#2449)
Add VLM.GOOGLE_GEMINI_3_5 enum and from_google_gemini_3_5 connector reusing the 2.5 parser, wire it into Detections.from_vlm, and salvage valid entries from partially malformed Gemini JSON arrays. Includes tests and changelog.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-07-21 16:20:05 +02:00
Mahbod b20d6eac46
feat(utils): add prefetch to `get_video_frames_generator` (#2273)
* feat(utils): add prefetch to get_video_frames_generator
* fix(utils): harden _prefetched_frames_generator threading safety
* test(utils): add prefetch combination and minimum-queue tests
* docs(utils): improve prefetch documentation, validation, and test docstrings
* fix(utils): harden prefetch reader-thread exception handling + docs
* docs(changelog): sync front-matter date_modified
* test(utils): harden and extend prefetch test coverage
* test(utils): cover buffered-frames-before-error and zero-frame prefetch cases

---------

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: OpenAI Codex <codex@openai.com>
2026-07-21 14:12:08 +02:00
Matt Van Horn 25e879ec05
refactor: centralize geometry-aware dispatch for detection_area and detection_iou (#2374)
* refactor: centralize geometry-aware dispatch for detection_area and detection_iou
* fix(detection): centralize geometry-aware merge IoU
* docs(detection): add code examples to geometry calculation docstrings
* code: reuse count_mask_pixels; relocate geometry dispatch out of utils/
* docs: fix changelog framing and filter_detections.md wording
* test: add edge-case coverage for geometry dispatch and merge chains
* fix(tests): repair syntax-broken docstrings in geometry dispatch/merge tests
* refactor(detection): make geometry dispatch module private

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-21 12:37:20 +02:00
HALLOUARD 89d49c2e93
feat: Add soft Non-Max suppression (#1624)
* feat: Add soft Non-Max suppression
* feat(nms): add vectorized Gaussian Soft-NMS box/mask primitives
* feat(core): add Detections.with_soft_nms
* feat: export soft-NMS functions from top-level supervision API
* docs: add soft-NMS entries to IoU/NMS utils page
* test: add Soft-NMS coverage for box/mask primitives and Detections API

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-21 10:25:14 +02:00
Lee Clement 60d748e57d
fix: read COCO export image sizes from headers instead of decoding pixels (#2442)
save_coco_annotations iterated the dataset, cv2-decoding every image only
to read its shape — even for labels-only exports. Sizes now come from the
in-memory array when present, else a lazy PIL header read, the same
optimization from_yolo uses (#1636).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-07-17 18:30:24 +02:00
Jirka Borovec f7b63f149a
perf(cv2): simplify fallback operations (#2441)
- Remove unused compatibility operations and use focused Pillow and NumPy paths to reduce maintained fallback code.
- Preserve numerical decisions and hot-path performance with exact regression coverage and bounded algorithms.
- Preserve INTER_LINEAR uint8 reductions within one LSB while retaining the resize performance budget and numeric RGBA handling.
- Restore repeated-endpoint contour anchors and bound cross-platform chamfer coefficient drift in regression tests.

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-17 17:31:57 +02:00
Shehzad Waseem 9aaf7fdbd6
fix(metrics): avoid division by zero RuntimeWarning in F1Score using np.divide (#2437)
* fix(metrics): avoid division by zero RuntimeWarning in F1Score using np.divide
* test+changelog: add F1Score zero-denom regression test; add changelog entry
* follow-up cleanup: mirror F1Score np.divide fix in mean_average_recall

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@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: OpenAI Codex <codex@openai.com>
2026-07-17 17:11:45 +02:00
jirka a4b9c4e097 fix(cv2): pad getTextSize height/baseline from actual stroke_width
_get_text_size approximated thickness-to-stroke padding with
thickness // 2 formulas that diverge from the thickness - 1
stroke_width _put_text actually renders with. Past thickness 2 the
padding grows too slowly, so heavy-stroke descender pixels can fall
outside the reported box, breaking the documented enclosure
guarantee. Both functions now derive stroke_width from one shared
helper.

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-17 10:29:55 +02:00
Jirka Borovec 68e63f9e39
refactor(cv2): replace Hershey text with Pillow (#2440)
Text fallback now renders through Pillow with the DejaVu Sans face
resolved via matplotlib font_manager, replacing the Hershey stroke-font
reader; getTextSize metrics derive from the same font and differ from
OpenCV within the documented visual-divergence tier.

Remove the packaged Hershey glyph data (hershey_fonts.json, provenance,
license) and its _cv2/data package-data entry.

Delete unused fallbacks: _geometry _fill_poly and _point_in_polygon
(live fillPoly is the Pillow one in _drawing) and _common _unavailable.

Replace test_hershey with Pillow-oriented test_text, drop test_common,
and point test_contours/test_geometry at _drawing._fill_poly. Document
the fallback text-backend change in the changelog.

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-17 10:22:32 +02:00
jirka bc7b9fc69e docs(changelog): document cv2 fallback fixes from resolve pass
[resolve] PR #2439 — changelog entries for items 2,3 and the
copyMakeBorder scalar-channel bugfix, per AGENTS.md changelog policy.

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-17 09:08:16 +02:00
Jirka Borovec 1efa5b8eaa
feat(cv2): complete fallback integration (#2439)
* feat(cv2): complete fallback integration
* fallback-fixes: reject invalid addWeighted dtype; O(N) approxPolyDP anchor seeding
* tests: copyMakeBorder sequence parity; drop non-empty facade-import assert; fix Windows path separator in boundary check
* fix(cv2): copyMakeBorder scalar value only fills channel 0 on multichannel images

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-17 07:50:45 +02:00
Jirka Borovec 20b7c085b7
feat(video): require PyAV during cv2 transition (#2438)
- Add the PyAV-backed file-video and audio fallback to the compatibility layer.
- Declare PyAV alongside OpenCV until the final dependency-removal integration.
- _VideoWriter now rejects is_color=False (NotImplementedError) instead of
  silently dropping it, since the PyAV fallback only encodes 3-channel frames.
- _mux_audio cleanup (container closes, temp-file removal) is now best-effort
  so a failing close/remove in finally can no longer mask the primary result
  or the original exception.
- The subprocess used to validate the cv2-free fallback had no timeout;
  a hang (import deadlock, codec probe stall) could block the whole CI
  run. Added a 60s timeout so a hang fails fast with a clear traceback
  instead of an opaque suite-wide stall.
- process_video(preserve_audio=True) docstring still described the old
  ffmpeg-based muxing; audio remuxing was reimplemented with PyAV and no
  longer requires an external ffmpeg executable.
- get_video_frames_generator's documented webcam fallback
  (`_cv2.VideoCapture(0)`) silently fails under the PyAV backend: the
  BackendUnavailableError raised for integer sources was swallowed with no
  logging, so isOpened() just returns False with zero diagnostic signal.
  Doc note now states the limitation explicitly and the capture logs a
  warning instead of failing silently.

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-16 20:13:15 +02:00
Jirka Borovec c3496134bc
feat(cv2): add Hershey text fallback (#2435)
* feat(cv2): add Hershey text fallback
* fix(cv2): sync Hershey provenance hash

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-07-16 17:10:49 +02:00
Jirka Borovec 16814acff3
feat(utils): add `TkImageWindow` to unblock switch to `opencv-python-headless` (#2320)
- Added `sv.ImageWindow`, a Tkinter/Pillow-based desktop image viewer with BGR, grayscale, and BGRA support, keyboard polling, left-click callbacks, context-manager usage, window-state checks, and clean close handling
- Added responsive image resizing with optional aspect-ratio preservation and correctly mapped mouse coordinates after scaling or letterboxing
- Updated compatible runnable examples to use `sv.ImageWindow`, while retaining OpenCV display APIs for worker-thread streaming examples that are incompatible with Tkinter
- Improved `sv.cv2_to_pillow` to support grayscale and BGRA images
- Updated webcam guidance to clarify capture ownership and explicit `VideoCapture` cleanup
- Fixed image-window event handling to prevent stale keypresses, ghost windows, close-time races, and blocked waits after the window closes

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@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>
2026-07-15 15:06:55 +02:00
Abhijith Neil Abraham 94cfb7f290
fix(metrics): ignore out-of-bucket detections in size-bucketed sco… (#2428)
* fix: ignore out-of-bucket   detections in size-bucketed scoring
* fix: honor area metadata in buckets

- Prefer stored COCO area metadata before geometry, mask, or OBB fallbacks.
- Add explicit-area, mask, and OBB regression coverage.
- Align COCO, mAP, and changelog area semantics.

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-07-15 12:48:19 +02:00
Nick Herrig d5cadf526a
Add cookbook for blurring faces with hosted api (#923)
* Add cookbook for blurring faces with hosted api
* fix: correct Colab URL and spelling errors
* fix: strip outputs and remove GPU section
* fix: improve code quality and notebook structure
* fix: align HTML card and prose style

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-11 01:41:49 +02:00
Teïlo M 14c3c86e22
Fix hex parser accepting multiple leading prefixes (#2421)
`hex_to_rgba` previously stripped every leading `#`, so invalid inputs such as `##000000` were accepted despite `is_valid_hex` rejecting them.

Remove only one optional prefix and add regression coverage for the minimized failing input.

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-07-11 00:55:51 +02:00
Abhijith Neil Abraham 287868e171
feature: add KeyPoints.merge() method (#2412)
* feat: add KeyPoints.merge() method
* docs: address review comments on merge docstring and changelog date
* chore: retrigger CI after transient links-check failure
* ci(links-check): accept transient 5xx responses to stop flaky failures
* test(keypoints): add validation for consistent coordinate depth across skeletons
* docs(keypoints): document coordinate-depth ValueError in merge() Raises
* test(keypoints): add docstring, zero-keypoint, and merge+with_nms coverage

---------

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: OpenAI Codex <codex@openai.com>
2026-07-09 21:37:26 +02:00
Jirka Borovec 5344cb99dd
fix: close out remaining review findings (#2418)
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>
2026-07-09 17:53:52 +02:00
Jirka Borovec 75023c5f2f
fix: remaining review findings in dataset, docs, and tests (#2416)
- 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>
2026-07-08 23:00:32 +02:00
Jirka Borovec 23a2227ae7
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>
2026-07-08 14:30:32 +02:00
Jirka Borovec 072f78471c
fix: resolve medium dataset findings (#2408)
- Reinstated NumPy-safe `Classifications` equality and ordered class-list comparisons in dataset equality.
- Restored greedy matching plus size-bucket scoring for Precision, Recall, F1, and MeanAverageRecall, with regression coverage for the medium-object boundary case.
- Filter size-bucket precision, recall, and F1 against target boxes so predictions no longer claim the bucket.
- Preserve confidence order for bucketed mAR@K scoring and return zero when a bucket has no support.
- Add regression coverage for bucket matching, empty-support mAR, top-K limits, and missing-mask errors.

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-08 08:56:34 +02:00
Jirka Borovec 74db9e29ff
fix(utils): normalize timm confidences and verify assets (#2414)
- Convert timm classification logits with softmax so confidence values match the normalized scale used by other classification adapters.
- Verify asset MD5 hashes after fresh downloads and retry once when a payload is corrupted.
- Add focused regressions for timm confidence scaling and asset download integrity paths.
- Convert from_timm outputs to probabilities before applying thresholds and document that existing thresholds may need retuning.
- Add downloader regression coverage for repeated MD5 mismatches so exhausted retries now raise ValueError.

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-07 21:59:23 +02:00
Jirka Borovec dde422703c
fix(tracker): harden ByteTrack edge cases (#2413)
- Keep ByteTrack confidence-threshold boundary detections eligible and avoid impossible activation thresholds above score 1.0.
- Stop mutating caller-owned detections and assignment cost matrices while preserving matched tracker output.
- Filter invalid tensor boxes before Kalman updates and respect minimum consecutive frames on first-frame tensor updates.
- Avoids per-call np.arange allocation by cloning detections with slice(None) while preserving non-mutation behavior.
- Adds regressions for delayed activation on the second consecutive tensor frame and broader invalid-tensor rejection cases.

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-07 21:05:03 +02:00
Jirka Borovec 814a226eba
fix(metrics): harden scoring edge cases (#2411)
- Use COCO 101-point AP averaging in the legacy mAP path so perfect and imperfect curves score consistently.
- Validate confusion-matrix class ids before indexing and preserve target ignore flags in the COCO-style evaluator.
- Keep mAR per-class recall for each max-detection cutoff and cover the scoring fixes with focused regressions.
- Return empty mAR scores with the same max-detection axis as non-empty results.
- Add an empty-input regression covering recall score and per-class result shapes.
- Update the public mAR docstring to describe per-image detection limits.

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-07 18:46:05 +02:00
Jirka Borovec 6a69197177
fix(dataset): harden dataset IO edge cases (#2410)
- Avoid mutating caller-owned Detections during dataset construction and reject invalid class ids with clear ValueErrors.
- Make COCO loading/export tolerant of missing optional metadata, add from_coco(use_iscrowd), and export mask pixel area when needed.
- Let folder-structure and YOLO loading skip common clutter and accept PIL-readable image modes with regression coverage.
- Preserve from_coco positional show_progress compatibility while keeping use_iscrowd keyword-only.
- Filter class-folder loading to image files and export missing COCO mask area from decoded masks.
- Add regression coverage, changelog updates, and types-tqdm for mypy.

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-07 16:29:43 +02:00
Abhijith Neil Abraham 5b4c8b6d0d
fix(key_points): handle empty and numpy index input, keep degenerate skeletons (#2402)
* handle empty and numpy index input, keep degenerate skeletons

- Filter non-finite keypoint coordinates when converting to detections while preserving finite zero-area skeletons.
- Treat zero-length KeyPoints selections as empty and add regression coverage for metadata alignment and selected-index equivalence.

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-07-07 00:02:38 +02:00
Jirka Borovec c3413a8f10
fix(annotators): resolve annotator medium findings (#2407)
- Added deterministic color lookup with flexible palette resolution and clear errors for empty palettes
- Improved annotator and utility handling for warning formatting, plotting imports, and icon caching
- Added validation for keypoint edges, MediaPipe inputs, and VideoSink state

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-06 22:43:35 +02:00
Jirka Borovec e13090f84b
Fix detection medium review findings (#2400)
- Fixed detection medium findings across adapters, mask non-max merge, sinks, segmentation parsing, LineZone history, and mask ROI handling
- Fixed mask non-max merge deprecation warnings to honor the standard warning opt-out and include version context
- Fixed mask non-max merge validation for invalid IoU thresholds
- Fixed CompactMask non-max merge grouping to update merged mask candidates correctly
- Fixed selected and compacted detections to copy arrays and metadata, preventing mutations from leaking back to source detections
- Fixed LineZone crossing history eviction to tolerate short tracking gaps and evict stale state per tracker/class key
- Fixed semantic segmentation handling to preserve class ID 0
- Improved mask ROI conversion performance by avoiding unnecessary full-frame copies and repeated scans
- Updated JSONSink changelog/docs to document native bool/int/float output while leaving CSVSink unchanged
- Updated detection docstrings for mask parsing, selection copy semantics, validation errors, and argument readability guidance

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-07-06 19:02:38 +02:00
Jirka Borovec bd0f44fcfd
fix: resolve remaining High findings from deep codebase review (#2389)
- Fixed crop annotation so overlapping detections sample from the original scene
- Fixed dataset exports to reject basename collisions, including case-insensitive collisions
- Fixed LMM connector mapping to support mirror enum aliases without a hand-maintained dispatch table
- Updated benchmark documentation to install the released inference package with metrics support

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-03 22:58:07 +02:00
Abhijith Neil Abraham afcf13a6f5
fix(annotators): clip BackgroundOverlayAnnotator boxes to the scene… (#2396)
* fix(annotators): clip BackgroundOverlayAnnotator boxes to the scene before   restoring detection regions
* fix(annotators): use explicit np.int32 cast in BackgroundOverlayAnnotator
* test(annotators): strengthen BackgroundOverlayAnnotator test coverage
* docs(changelog): add Unreleased entry for BackgroundOverlayAnnotator fix

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-03 18:36:25 +02:00
Jirka Borovec 15dbbb5cb1
fix(annotators): clip crops, fix heatmap wrap, release capture (#2393)
- Fixed annotators to avoid internal deprecation warnings from image overlay usage while preserving the public deprecated wrapper
- Fixed CropAnnotator crashes for partially out-of-frame detections by clipping crops to scene bounds and skipping degenerate boxes
- Fixed HeatMapAnnotator heat disappearing after 256 accumulated frames
- Fixed video frame generation to release the capture when iteration ends early
- Updated documentation for overlay deprecation, crop clipping behavior, and video capture release guarantees

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-03 11:03:45 +02:00
Jirka Borovec 99049d84e1
Fix: resolve major complex review (#2388)
- Fixed in-memory dict-form `DetectionDataset` image access, iteration, equality, and merge behavior, with deprecation messaging retained
- Fixed mAP to honor `metric_target` for mask and oriented-bounding-box evaluation, including correct IoU routing, area handling, crowd semantics, and missing-content errors
- Fixed `ConfusionMatrix.plot()` when plotting raw counts with default normalization disabled
- Improved mask mAP crowd handling performance and memory usage
- Updated the count-in-zone guide to use current APIs

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-02 18:14:04 +02:00
Agis Kounelis 8692148c67
fix(detection): make `get_anchors_coordinates` OBB-aware (#2382)
- Fixed `get_anchors_coordinates` to compute anchor positions from oriented bounding boxes when OBB geometry is available, ensuring anchor-based operations (such as zone counting and annotators) align with the rotated object instead of its axis-aligned bounding box.
- Preserved existing behavior for axis-aligned boxes, while continuing to use mask centroids for `CENTER_OF_MASS` anchors when masks are available.
- Improved the `get_anchors_coordinates` documentation with the updated anchor selection order, OBB usage examples, and notes describing OBB winding-order requirements and anchor tie-breaking behavior.

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-02 00:04:26 +02:00
Jirka Borovec d590eb6658
perf(detection): keep mixed-mask Detections.merge compact (#2383)
- Improved `Detections.merge()` to preserve `CompactMask` output when merging dense and compact masks by converting dense masks to compact form, avoiding unnecessary full-mask materialization while keeping all-dense and all-compact behavior unchanged.
- Added validation to mixed-mask merging that raises `ValueError` when compact masks have inconsistent image shapes or dense mask dimensions do not match the compact mask image size.
- Added the public `CompactMask.image_shape` property for safe access to compact mask dimensions.
- Updated `Detections.merge()` documentation to describe mixed-mask merge behavior, output types, validation errors, the lossy dense-to-compact conversion outside detection bounding boxes, and that NMS/NMM pairwise operations do not preserve `CompactMask`.
- Added a comprehensive "Use Compact Masks" how-to guide covering compact mask ingestion, inference, annotator mask requirements, and mixed-mask merging, and integrated it into the documentation navigation.

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-07-01 21:01:29 +02:00
Jirka Borovec 04858a2727
feat: declare annotator mask requirements (#2370)
- Added a `requires_mask` flag to annotators so integrations can determine whether masks must be materialized before annotation.
- Updated mask-only annotators to declare `requires_mask=True`, while mask-optional annotators explicitly declare `requires_mask=False`, including compatibility support for `ComparisonAnnotator`.

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-01 19:34:21 +02:00
Jirka Borovec beb047095f
feat: add compact RLE mask ingestion (#2367)
- Added compact COCO RLE mask ingestion with a `CompactMask` representation and optional compact mask parsing during inference for substantially lower memory usage on sparse segmentation results.
- Added `Detections.to_compact_masks()` to convert existing dense masks into compact masks while preserving detection and collection metadata.
- Improved compact mask decoding performance with cropped RLE processing, batched decoding on the fast path, vectorized decoding for small images, optimized RLE traversal, and faster delta decoding.
- Improved mask metrics to operate directly on `CompactMask` instances, preserving the compact representation while producing results equivalent to dense masks.
- Fixed mixed-modality inference handling by keeping detections and masks aligned, isolating malformed RLE failures to individual predictions where possible, and falling back safely when decoding cannot be completed.
- Fixed compact mask conversion and parsing to preserve dense-mask pixel content across public parsing and slicing paths, while correctly documenting and applying the intended bbox-cropping behavior for compact COCO RLE masks.
- Improved COCO RLE validation with checks for malformed payloads, invalid dimensions, count overflows, image size limits, count-sum mismatches, bounding-box mismatches, and safe fallback behavior for incompatible mask sizes.
- Added inference benchmarks and documentation demonstrating the memory and inference-time characteristics of compact masks, including guidance on their performance tradeoffs and behavior.

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-01 12:50:40 +02:00
Jirka Borovec 0a95bae8a8
chore: bump minimum Python to 3.10 (#2260)
- Drop Python 3.9 from CI test matrix
- requires-python = ">=3.10" in pyproject.toml
- ruff target-version py39 → py310
- mypy python_version 3.9 → 3.10
- Remove Python 3.9 classifier

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-29 14:45:30 +02:00
Saif Khan 57bb5e7e8b
Add adaptive TP/FP/FN validation mosaic export (#2271)
- remove top-level cv2/annotator imports; lazy-load inside rendering functions
- remove save_result_images bool; save_directory_path is now keyword-only after metric_target
- drop hardcoded result/ subdirectory from benchmark output path
- propagate metric_target into _split_detections_by_outcome for correct OBB IoU dispatch
- add filename collision UserWarning in benchmark loop
- remove dead/unreachable combined None-check in _split_detections_by_outcome
- add Google-style docstrings to all 5 new private visualization functions
- add TestSplitDetectionsByOutcome covering 7 edge cases (empty inputs, cross-class, confidence-None)
- fix FP/FN pixel assertions to check interior box pixels rather than border/title regions
- fix benchmark_a_model.md: full panel names, add Visual Benchmarking section, update API examples

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-26 21:33:49 +02:00
Agis Kounelis 27ba0aa92f
fix(detection): do not crash `from_inference` on partial `tracker_id` (#2353)
process_roboflow_result appended tracker_id only for predictions that carried
one, while xyxy/confidence/class_id were appended for every prediction. A
result where some predictions are tracked and others are not produced a
tracker_id array shorter than the boxes, so Detections.from_inference raised
"tracker_id must be a 1D np.ndarray with shape (N,)".

Collect tracker_id for every prediction (None when absent) and build the array
only when all detections carry one, otherwise leave it None. Fully-tracked and
untracked results are unchanged.

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-26 16:58:52 +02:00
Madhav-C 2169192492
feat(dataset): add LabelMe format support to DetectionDataset (#2299)
- Added LabelMe import and export support for DetectionDataset, including per-image JSON loading/saving alongside existing dataset formats
- Added LabelMe rectangle-to-box and polygon-to-mask conversion, with rectangle masks available when mask output is requested or polygon annotations are present
- Added LabelMe path-safety protections by resolving image paths by basename and rejecting unsafe or ambiguous image references
- Added validation for duplicate image basenames, malformed shape points, missing imagePath values, and invalid class IDs during LabelMe load/export
- Improved LabelMe handling by warning and skipping unsupported shape types
- Updated documentation and changelog with LabelMe workflow examples and supported-format references

---------

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>
2026-06-25 17:07:39 +02:00