Compare commits

...
958 Commits
Author SHA1 Message Date
Swapnil GautamandClaude Fable 5 7d325d23e3 docs: convert fenced examples to doctests in dataset/formats/createml.py (#2475)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 18:12:40 +02:00
fb22686a5e ITZ-90 replaces ga tag with unified instance tag (#2028)
Co-authored-by: Piotr Skalski <piotr.skalski92@gmail.com>
Co-authored-by: jirka <6035284+borda@users.noreply.github.com>
2026-08-05 19:54:21 +02:00
Daniiiil1 6b143e4e41 test(metrics): verify live sklearn parity (#2470)
* add sklearn parity goldens
* compute sklearn parity live
* separate empty input semantics
2026-08-05 19:24:44 +02:00
Swapnil GautamandClaude Fable 5 bc20dd19fb docs: convert fenced examples to doctests in dataset/formats/coco.py (#2474)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 14:51:58 +02:00
dependabot[bot] e82349fabf ⬆️ Bump cryptography from 48.0.1 to 50.0.0 in the uv group across 1 directory (#2473)
Bumps the uv group with 1 update in the / directory: [cryptography](https://github.com/pyca/cryptography).


Updates `cryptography` from 48.0.1 to 50.0.0
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/48.0.1...50.0.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 50.0.0
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 20:32:01 +02:00
dependabot[bot] 01df50b440 ⬆️ Bump pymdown-extensions from 10.21.3 to 11.0 in the uv group across 1 directory (#2472)
Bumps the uv group with 1 update in the / directory: [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions).


Updates `pymdown-extensions` from 10.21.3 to 11.0
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.21.3...11.0)

---
updated-dependencies:
- dependency-name: pymdown-extensions
  dependency-version: '11.0'
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 19:45:30 +02:00
jirka a95d85ce07 rolling towards 0.31.0.dev 2026-08-04 19:43:57 +02:00
Jirka Borovec 813c4295bf releasing 0.30.0 (#2462) 2026-08-04 16:22:04 +02:00
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
pre-commit-ci[bot] f7f53d0a60 chore(pre_commit): ⬆ pre_commit autoupdate (#2471)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.16.0 → v0.16.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.16.0...v0.16.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-03 19:50:44 +02:00
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
475d551908 refactor: vectorize get_labels_text() in annotators/utils (#2465)
* refactor: vectorize `get_labels_text()` in annotators/utils.py
* test: add tests for all get_labels_text branches
* style: flatten elif/else to guard clauses in get_labels_text()
* refactor: guard get_labels_text() against array/detections length mismatch
* test: add missing get_labels_text() coverage

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-08-03 17:43:14 +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
dependabot[bot] 3c19d176b3 ⬆️ Bump the github-actions group with 2 updates (#2466)
Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v7...v7.0.1)

Updates `astral-sh/setup-uv` from 8.3.0 to 9.0.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v8.3.0...c771a70e6277c0a99b617c7a806ffedaca235ff9)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: astral-sh/setup-uv
  dependency-version: 9.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 10:42:38 +02:00
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
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
5212af7b70 docs: improve doctests in draw/utils.py (#2425)
* docs: wrap obb_polygon_area doctest in pycon fence
* Update scene assignment in drawing functions

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-07-28 10:31:16 +02:00
Andrew BarnesandJirka Borovec 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]andjirka 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
dependabot[bot] caff4d1ec2 ⬆️ Bump the github-actions group with 2 updates (#2458)
Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish).


Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v7...v7.0.1)

Updates `pypa/gh-action-pypi-publish` from 1.14.0 to 1.14.1
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/cef221092ed1bacb1cc03d23a2d87d1d172e277b...ba38be9e461d3875417946c167d0b5f3d385a247)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 09:20:23 +02:00
dependabot[bot] ceddf331c6 ⬆️ Update pydeprecate requirement from <0.11,>=0.9 to >=0.9,<0.12 (#2457)
Updates the requirements on [pydeprecate](https://github.com/Borda/pyDeprecate) to permit the latest version.
- [Release notes](https://github.com/Borda/pyDeprecate/releases)
- [Changelog](https://github.com/Borda/pyDeprecate/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Borda/pyDeprecate/compare/v0.9.0...v0.11.0)

---
updated-dependencies:
- dependency-name: pydeprecate
  dependency-version: 0.11.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 09:20:12 +02:00
dependabot[bot] 9c06bfeddb ⬆️ Bump jupyterlab from 4.5.9 to 4.5.10 in the uv group across 1 directory (#2456)
Bumps the uv group with 1 update in the / directory: [jupyterlab](https://github.com/jupyterlab/jupyterlab).


Updates `jupyterlab` from 4.5.9 to 4.5.10
- [Release notes](https://github.com/jupyterlab/jupyterlab/releases)
- [Changelog](https://github.com/jupyterlab/jupyterlab/blob/main/RELEASE.md)
- [Commits](https://github.com/jupyterlab/jupyterlab/compare/@jupyterlab/lsp@4.5.9...@jupyterlab/lsp@4.5.10)

---
updated-dependencies:
- dependency-name: jupyterlab
  dependency-version: 4.5.10
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 09:20:06 +02:00
dependabot[bot] fe77de5b9f ⬆️ Bump gitpython from 3.1.44 to 3.1.54 in the uv group across 1 directory (#2454)
Bumps the uv group with 1 update in the / directory: [gitpython](https://github.com/gitpython-developers/GitPython).


Updates `gitpython` from 3.1.44 to 3.1.54
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.44...3.1.54)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-version: 3.1.54
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-26 22:31:58 +02:00
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
Vikas saini 156ee33740 docs: convert fenced examples to doctests in draw/utils.py (#2451) 2026-07-21 17:40:13 +02:00
dependabot[bot] 7d915a7357 ⬆️ Bump pillow from 12.2.0 to 12.3.0 in the uv group across 1 directory (#2450)
Bumps the uv group with 1 update in the / directory: [pillow](https://github.com/python-pillow/Pillow).


Updates `pillow` from 12.2.0 to 12.3.0
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/12.2.0...12.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: direct:production
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-21 16:21:26 +02:00
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
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
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
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
pre-commit-ci[bot]andJirka Borovec 140c05f273 chore(pre_commit): ⬆ pre_commit autoupdate (#2448)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/JoC0de/pre-commit-prettier: 0737985b8f21a8d83195f6ced1045e7637fc82fb → v3.9.5](https://github.com/JoC0de/pre-commit-prettier/compare/0737985b8f21a8d83195f6ced1045e7637fc82fb...v3.9.5)
- [github.com/tox-dev/pyproject-fmt: v2.25.2 → v2.25.3](https://github.com/tox-dev/pyproject-fmt/compare/v2.25.2...v2.25.3)
- [github.com/astral-sh/ruff-pre-commit: v0.15.21 → v0.15.22](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.21...v0.15.22)
- [github.com/codespell-project/codespell: v2.4.2 → v2.4.3](https://github.com/codespell-project/codespell/compare/v2.4.2...v2.4.3)

* Apply suggestions from code review

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>

* Update .pre-commit-config.yaml

---------

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>
2026-07-20 22:00:13 +02:00
206adc083c ci: add doctest fence hook (#2447)
* ci: add doctest fence hook
* docs: fence source doctests

---------

Co-authored-by: Codex <codex@openai.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-20 13:35:46 +02:00
Jirka Borovec 5fccf8a966 chore: normalize doctest code fences to pycon in src docs (#2446) 2026-07-20 11:22:27 +02:00
dependabot[bot] 8be58fa0aa ⬆️ Bump astral-sh/setup-uv from 8.3.0 to 8.3.2 in the github-actions group (#2445)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 8.3.0 to 8.3.2
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/d31148d669074a8d0a63714ba94f3201e7020bc3...11f9893b081a58869d3b5fccaea48c9e9e46f990)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 8.3.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 10:58:30 +02:00
dependabot[bot] f1f8213c01 ⬆️ Update opencv-python requirement from <5,>=4.5.5.64 to >=4.5.5.64,<6 (#2444)
Updates the requirements on [opencv-python](https://github.com/opencv/opencv-python) to permit the latest version.
- [Release notes](https://github.com/opencv/opencv-python/releases)
- [Commits](https://github.com/opencv/opencv-python/commits)

---
updated-dependencies:
- dependency-name: opencv-python
  dependency-version: 5.0.0.93
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 10:58:09 +02:00
937ed4af37 feat(detection): add require_all_anchors to PolygonZone (#2272)
Currently a detection counts as 'in the zone' only when every anchor in
triggering_anchors is inside. For boxes that straddle the zone boundary
this means a detection with many anchors (e.g. the four corners) is often
under-counted unless the user shrinks triggering_anchors to a single point.

Add require_all_anchors: bool = True so callers can opt into 'any anchor
inside is enough'. Default preserves current behaviour.

* test: strengthen PolygonZone require_all_anchors coverage
* docs: clarify require_all_anchors anchor-based semantics

---------

Co-authored-by: jirka <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 18:56:42 +02:00
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
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
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
jirkaandclaude[bot] 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 Borovecandclaude[bot] 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
jirkaandclaude[bot] 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
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
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
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
39eb6571ce feat(cv2): add drawing fallbacks (#2433)
* feat(cv2): add drawing fallbacks
* code: reject non-default hierarchy in _draw_contours fallback
* tests: keep cv2 optional so cv2-less fallback tests still run

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-16 12:53:01 +02:00
7096ee911c feat(cv2): add geometry fallbacks (#2432)
- Added geometry fallbacks for OpenCV-dependent operations, including connected-component processing.
- Fixed contour hierarchy detection for concave shapes by reliably selecting an interior point.
- Improved contour hierarchy remapping performance for large contour sets.

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-16 00:54:57 +02:00
3d669f1ab4 feat(cv2): add image fallback backend (#2431)
- Organize facade constants and implementations into thematic private modules.
- Add NumPy/Pillow/SciPy fallbacks with OpenCV parity coverage.
- Mirror package modules in cv2 tests and verify blocked imports.
- Split compound operation tests into isolated cases.
- Parameterize color parity and fallback bindings for targeted failures.
- Inline color conversion cases at their only use site.
- Inline fallback binding cases while preserving reusable manifests.

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-15 21:55:08 +02:00
8ecd9a6680 refactor(cv2): add optional backend facade (#2430)
* refactor(cv2): add optional backend facade
* test: guard real cv2 oracle import for cv2-less environments
* test: preserve existing PYTHONPATH in subprocess import tests
* lint: auto-fix violations after resolve cycle
* fix(typing): remove obsolete suppressions
* test(cv2): parametrize constant alignment tests and refactor fallback validation
* test(cv2): simplify constant grouping and optimize REQUIRED_SYMBOLS validation

---------

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-15 20:53:24 +02:00
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
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
pre-commit-ci[bot]andJirka Borovec 3e80c0ce3c chore(pre_commit): ⬆ pre_commit autoupdate (#2426)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/JoC0de/pre-commit-prettier: fc2da0552b28c24c836d045bfb6c3057b3d11e62 → v3.9.5](https://github.com/JoC0de/pre-commit-prettier/compare/fc2da0552b28c24c836d045bfb6c3057b3d11e62...v3.9.5)
- [github.com/tox-dev/pyproject-fmt: v2.25.1 → v2.25.2](https://github.com/tox-dev/pyproject-fmt/compare/v2.25.1...v2.25.2)
- [github.com/astral-sh/ruff-pre-commit: v0.15.20 → v0.15.21](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.20...v0.15.21)
- [github.com/pre-commit/mirrors-mypy: v2.1.0 → v2.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v2.1.0...v2.3.0)

* Apply suggestions from code review

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>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-07-14 12:46:15 +02:00
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
dependabot[bot] 6306b7ca71 ⬆️ Bump mistune from 3.2.1 to 3.3.0 in the uv group across 1 directory (#2423)
Bumps the uv group with 1 update in the / directory: [mistune](https://github.com/lepture/mistune).


Updates `mistune` from 3.2.1 to 3.3.0
- [Release notes](https://github.com/lepture/mistune/releases)
- [Changelog](https://github.com/lepture/mistune/blob/main/docs/changes.rst)
- [Commits](https://github.com/lepture/mistune/compare/v3.2.1...v3.3.0)

---
updated-dependencies:
- dependency-name: mistune
  dependency-version: 3.3.0
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-11 00:57:39 +02:00
Teïlo MandJirka Borovec 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
dependabot[bot] 39c015c0ff ⬆️ Bump soupsieve from 2.7 to 2.8.4 in the uv group across 1 directory (#2422)
Bumps the uv group with 1 update in the / directory: [soupsieve](https://github.com/facelessuser/soupsieve).


Updates `soupsieve` from 2.7 to 2.8.4
- [Release notes](https://github.com/facelessuser/soupsieve/releases)
- [Commits](https://github.com/facelessuser/soupsieve/compare/2.7...2.8.4)

---
updated-dependencies:
- dependency-name: soupsieve
  dependency-version: 2.8.4
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-11 00:50:36 +02:00
OrbisAI Security 9897b0790f fix: this dependabot configuration does not set a co... in... (#2419)
Automated security fix generated by OrbisAI Security
2026-07-09 22:05:09 +02:00
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
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 8dedc3474d chore: update pre-release workflow to support additional tag formats (#2420) 2026-07-09 15:19:43 +02:00
dependabot[bot] 1e4489f61b ⬆️ Bump the uv group across 1 directory with 6 updates (#2417)
Bumps the uv group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [pillow](https://github.com/python-pillow/Pillow) | `11.3.0` | `12.2.0` |
| [requests](https://github.com/psf/requests) | `2.32.5` | `2.33.0` |
| [pytest](https://github.com/pytest-dev/pytest) | `8.4.2` | `9.0.3` |
| [bleach](https://github.com/mozilla/bleach) | `6.2.0` | `6.4.0` |
| [jupyter-server](https://github.com/jupyter-server/jupyter_server) | `2.18.0` | `2.20.0` |
| [urllib3](https://github.com/urllib3/urllib3) | `2.6.3` | `2.7.0` |



Updates `pillow` from 11.3.0 to 12.2.0
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/11.3.0...12.2.0)

Updates `requests` from 2.32.5 to 2.33.0
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.5...v2.33.0)

Updates `pytest` from 8.4.2 to 9.0.3
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.4.2...9.0.3)

Updates `bleach` from 6.2.0 to 6.4.0
- [Changelog](https://github.com/mozilla/bleach/blob/main/CHANGES)
- [Commits](https://github.com/mozilla/bleach/compare/v6.2.0...v6.4.0)

Updates `jupyter-server` from 2.18.0 to 2.20.0
- [Release notes](https://github.com/jupyter-server/jupyter_server/releases)
- [Changelog](https://github.com/jupyter-server/jupyter_server/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter-server/jupyter_server/compare/v2.18.0...v2.20.0)

Updates `urllib3` from 2.6.3 to 2.7.0
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.6.3...2.7.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.2.0
  dependency-type: direct:production
  dependency-group: uv
- dependency-name: requests
  dependency-version: 2.33.0
  dependency-type: direct:production
  dependency-group: uv
- dependency-name: pytest
  dependency-version: 9.0.3
  dependency-type: direct:development
  dependency-group: uv
- dependency-name: bleach
  dependency-version: 6.4.0
  dependency-type: indirect
  dependency-group: uv
- dependency-name: jupyter-server
  dependency-version: 2.20.0
  dependency-type: indirect
  dependency-group: uv
- dependency-name: urllib3
  dependency-version: 2.7.0
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-09 00:51:33 +02:00
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
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 BorovecandCodex 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 BorovecandCodex 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 BorovecandCodex 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 BorovecandCodex 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 BorovecandCodex 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
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 BorovecandCodex 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
pre-commit-ci[bot]andcopilot-swe-agent[bot] beede8a638 chore(pre_commit): ⬆ pre_commit autoupdate (#2406)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/JoC0de/pre-commit-prettier: v3.8.4 → v3.9.4](https://github.com/JoC0de/pre-commit-prettier/compare/v3.8.4...v3.9.4)

* chore(pre_commit): use SHA instead of version tag for pre-commit-prettier

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-06 21:17:27 +02:00
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
dependabot[bot] 8fd47a9ec6 ⬆️ Bump astral-sh/setup-uv from 8.2.0 to 8.3.0 in the github-actions group (#2405)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 8.2.0 to 8.3.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/fac544c07dec837d0ccb6301d7b5580bf5edae39...d31148d669074a8d0a63714ba94f3201e7020bc3)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 8.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-06 10:35:25 +02:00
dependabot[bot] ced30b48f7 ⬆️ Update pydeprecate requirement from <0.10,>=0.9 to >=0.9,<0.11 (#2404)
Updates the requirements on [pydeprecate](https://github.com/Borda/pyDeprecate) to permit the latest version.
- [Release notes](https://github.com/Borda/pyDeprecate/releases)
- [Changelog](https://github.com/Borda/pyDeprecate/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Borda/pyDeprecate/compare/v0.9.0...v0.10.1)

---
updated-dependencies:
- dependency-name: pydeprecate
  dependency-version: 0.10.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-06 10:34:57 +02:00
Jirka Borovecandclaude[bot] 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
Jirka Borovecandclaude[bot] 78aec073c4 test: cover public API gaps and dataset split (#2399)
* test: cover public API gaps and dataset split
* test(sinks): switch VideoSink to AVI/MJPG and add ImageSink clearing test
* test(detection): add box_non_max_merge 6-column class-separation tests
* test(dataset): drop deprecated dict API and strengthen class-id assertion
* test(public_api): strengthen importability check with getattr

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-03 20:57:42 +02:00
Jirka Borovecandclaude[bot] eea04b3656 fix(detection): harden model connectors and mask extraction (#2398)
- `from_tensorflow` scaled boxes in place on the array returned by `.numpy()`, which can share memory with the source tensor — corrupting caller data and double-scaling on a repeat call; copy before scaling
- `from_lmm` raised a bare `KeyError` for `MOONDREAM` and `QWEN_3_VL`, which the enum and docstring advertise; map both to their `VLM` members
- `from_deepseek_vl_2` returned a `(0,)`-shaped `xyxy` on empty output, so a zero-detection response crashed the `Detections` constructor; return `(0, 4)` like the other parsers
- `extract_ultralytics_masks` binarized bilinear-resized masks with `> 0`, dilating every mask at object boundaries; threshold at 0.5 to match Ultralytics
- add connector coverage: fake-result shims and round-trip tests (N>1, N=1, empty) for the nine previously untested `from_*` connectors and the `detection/tools/transformers.py` processors; one empty-`segments_info` panoptic case is xfail-marked pending a separate fix

* test(ci-fix): drop deprecated Pillow mode arg from panoptic helpers
* test(coverage): add from_qwen_3_vl end-to-end parametrized tests
* test(quality): harden test isolation, xfail strictness, and kwarg forwarding
* fix(detection): fix class_name empty dtype; annotate mask threshold asymmetry
* chore: ruff-format cleanup (blank lines)

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-03 20:09:57 +02:00
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 Borovecandclaude[bot] 0e1056df19 fix(metrics): count false positives on empty-GT images (#2397)
- Fixed mAP calculation to count predictions on background-only images as false positives
- Fixed all-background mAP inputs to return 0.0 instead of NaN when no ground-truth classes exist
- Updated `from_tensors` documentation to define empty-target background images and their false-positive behavior

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-03 16:17:08 +02:00
f173905c8b fix(dataset): stop split mutation, determinize VOC, guard collisions (#2394)
- `train_test_split` seeded the global `random` module and shuffled the caller's list in place, so `DetectionDataset.split()` reordered its own `image_paths` and polluted process-wide randomness; use a local `random.Random` and shuffle a copy
- Pascal VOC class ids were assigned in `set`-iteration and filesystem-glob order, so the same dataset produced different `class_id` values across runs; sort class names and the loaded file list
- dataset exports keyed output files on basename, silently overwriting when two entries shared a name across directories (common after `merge()`); detect basename collisions and raise
- add regression tests for split determinism, VOC id stability, and export collisions

* fix(dataset): add LabelMe collision guard, hoist pre-flight checks, make guard private
* test(dataset): add collision guard tests for as_yolo, as_pascal_voc, and boundary cases
* docs(dataset): document ValueError raises, fix stale docstrings, add non-mutation guarantee

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-07-03 15:02:01 +02:00
Jirka Borovecandclaude[bot] 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
Abhijith Neil Abraham 0d4c3a4fcf fix(annotators): clip CropAnnotator boxes to the scene before cropping (#2391) 2026-07-03 10:33:49 +02:00
f196e15f26 fix: replace deprecated 2-D np.cross with explicit determinant (#2386)
- Add filterwarnings = ["error::DeprecationWarning"] to pyproject.toml so
  future np.cross 2-D reintroductions fail CI immediately (closes #2384)
- Add test_get_polygon_center_no_deprecation_warning: asserts no
  DeprecationWarning from get_polygon_center (Copilot inline comment)
- Add test_cross_product_no_deprecation_warning: asserts no DeprecationWarning
  from cross_product (Copilot inline comment)
- Add test_cross_product_sign (4 parametrised cases): above / below / on-line /
  offset-start — directly tests the inline determinant correctness
- Improve cross_product docstring: blank line after summary, adds Examples
  section with correct output, notes NumPy 2.0 rationale

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-02 19:01:39 +02:00
Jirka Borovecandclaude[bot] 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
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
058d8fd990 perf(detection): count mask pixels with count_nonzero (#2361)
Mask pixel-area counting used `np.sum` — `np.array([np.sum(m) for m in
masks])` in `Detections.area` and `np.sum(mask, axis=(1, 2))` in the metrics
`get_mask_size_category`. For boolean masks `np.count_nonzero` (with no axis)
dispatches to NumPy's SIMD popcount over the raw byte buffer, whereas every
axis-reduction form — `np.sum(..., axis=...)` and even `np.count_nonzero(...,
axis=...)` — falls back to a slower generic reduction. So counting per mask
with `np.count_nonzero` is several times faster than the "obvious" vectorized
sum, while producing bit-identical integer counts.

Route both sites through `np.fromiter((np.count_nonzero(m) for m in masks),
dtype=np.int64, count=len(masks))`. `dtype=np.int64` preserves the documented
`Detections.area` mask-branch dtype on every platform (a bare
`np.array([...])` of Python ints would be int32 on Windows).

Measured ~5x on 640x640 masks (e.g. `Detections.area`, N=300: ~24ms -> ~4ms),
faster across densities. `get_mask_size_category` feeds the size-bucketed
F1/Precision/Recall/mAP/mAR metrics, where it is invoked repeatedly per
dataset. Counts are integer-exact (verified over 400 randomized trials plus
empty / all-true / all-false / 1x1 edge cases).

Adds parity tests for `Detections.area` (dense mask) and
`get_mask_size_category` against an `np.sum` reference.

---------

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-01 23:22:46 +02:00
8f576b02a8 fix(detection): scale from_tensorflow boxes by correct axes (#2360)
`Detections.from_tensorflow` scaled the normalized box coordinates by the
wrong image dimensions: the y coordinates (ymin/ymax, columns 0 and 2) were
multiplied by width and the x coordinates (xmin/xmax, columns 1 and 3) by
height. Tensorflow Hub object-detection models emit `detection_boxes` as
normalized `[ymin, xmin, ymax, xmax]`, so y must scale by height and x by
width.

The bug is masked on square images (width == height) but corrupts every
coordinate on the common non-square case — e.g. a box normalized to
`[0.1, 0.2, 0.5, 0.6]` on a 1000x500 image came out as
`[100, 100, 300, 500]` instead of the correct `[200, 50, 600, 250]`.

Swap the two multipliers so y scales by `resolution_wh[1]` (height) and x by
`resolution_wh[0]` (width). Adds a non-square regression test (the connector
was previously untested).

- Expand tensorflow_results arg to document required dict keys and tensor
  shapes so callers know what to pass before getting a KeyError
- Add Note: section documenting the [ymin, xmin, ymax, xmax] normalized
  box format; the inline comment was only visible to code readers
- Fix SOURCE_IMAGE_PATH undefined identifier → "<SOURCE_IMAGE_PATH>"
  string placeholder (consistent with other connector examples in file)

---------

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-01 22:44:01 +02:00
a32323d5bd perf(detection): vectorize box_iou_batch_with_jaccard (#2359)
`box_iou_batch_with_jaccard` computed COCO-style Jaccard IoU with a double
Python `for` loop calling a scalar `_jaccard` helper once per (detection,
ground-truth) pair — an O(N*M) per-element pattern in otherwise pure-NumPy
code. It is the inner IoU of `COCOEvaluator._compute_iou`, called once per
(image, category) during mAP evaluation, and is also public API
(`sv.box_iou_batch_with_jaccard`).

Replace the loop with a broadcasted NumPy implementation and drop the now
unused scalar `_jaccard`. The far corners are built as `x2 = x + w` and the
union is associated as `(area_det + area_gt - area_inter) + eps` so the
result is bit-identical to the previous per-pair output (verified to
`max|diff| = 0` over 4000 randomized trials including zero/negative-width
degenerate boxes and crowd flags). Crowd semantics are preserved: a crowd
ground truth uses the detection area as the union.

Speedup scales with batch size — ~1.6x at 5x5, ~27x at 15x60, ~66x at
50x100 — and is faster even at the smallest sizes, so there is no regime
where it regresses. End-to-end COCO mAP results are unchanged (the existing
metrics suite passes without modification).

Adds `TestBoxIouBatchWithJaccard`: parity against an independent per-pair
reference across empty / single / busy / degenerate+crowd batches, the crowd
union semantics, the empty-input contract, and the `is_crowd` length guard.

- Improved COCO-style Jaccard IoU batch evaluation performance while preserving existing results, crowd handling, degenerate-box behavior, and public API semantics
- Fixed empty-input returns to preserve the documented `(len(boxes_detection), len(boxes_true))` output shape
- Fixed `is_crowd` length validation to raise a descriptive `ValueError`
- Updated Jaccard IoU documentation to clarify COCO `[x, y, w, h]` input format, output orientation, and NaN propagation

---------

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-01 22:43:26 +02:00
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
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
3f816c0b6c perf: avoid compact mask materialization in polygon annotator (#2369)
Use CompactMask crops for polygon extraction and offset crop-local contours back into image coordinates.

Add a regression test covering tight crops, disconnected contours, empty masks, dense parity, and no integer CompactMask indexing.

- Add `_iter_mask_crops()` helper under shared-utilities seam: yields
  (detection_idx, mask_or_crop, offset_or_None) encapsulating the
  CompactMask vs dense isinstance dispatch in one place (eliminates 4th
  inline copy of the same pattern; see _paint_masks_by_area)
- Refactor PolygonAnnotator.annotate() to consume _iter_mask_crops;
  removes the 9-line inline dispatch block
- Add TODO comment at isinstance site flagging MaskLike Protocol as
  follow-up (separate PR; review item #3 self-resolved)
- Extend PolygonAnnotator.annotate() docstring with Note section
  covering CompactMask fast path and offset semantics
- Add N=0 empty CompactMask test (scene unchanged, no error)
- Add all-False mask test (no polygons drawn, documents boundary behavior)
- Add N=1 single-detection parity test (CompactMask == dense)
- Add float xyxy truncation test (sub-pixel xyxy → same output as int xyxy)
- Add disjoint-contour coordinate assertion: both blobs painted at correct
  image-space coords after crop→image offset translation
- Add PolygonAnnotator to TestCompactMaskParity.test_annotator_compact_mask_matches_dense_mask parametrize

---------

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-01 18:05:46 +02:00
3ecd5d0744 Optimize mask annotation ROI blending (#2368)
- Improved MaskAnnotator performance by blending mask overlays only within the affected ROI while preserving dense mask and CompactMask rendering behavior
- Fixed all-false masks to skip unnecessary ROI blending
- Updated compact-mask benchmark output to clarify annotation speedup reporting

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-01 15:55:21 +02:00
Jirka Borovec 098f5315b5 chore: update uv.lock to require Python 3.10+ (#2381) 2026-07-01 13:28:01 +02:00
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 Borovecandclaude[bot] 4624dde770 fix(metrics): replace np.unique matching with greedy algorithm (#2380)
The two-pass np.unique deduplication in _match_detection_batch dropped
valid TP assignments when a prediction's best-IoU target was already
claimed by a higher-confidence prediction. The greedy one-pass algorithm
(sort by IoU desc, assign if neither target nor pred already matched)
was already used in _split_detections_by_outcome and
ConfusionMatrix.evaluate_detection_batch but missing from Recall,
F1Score, Precision, MeanAverageRecall, and MeanAveragePrecision.

- Fix all five _match_detection_batch implementations
- Add regression tests reproducing the issue #2378 example in each
  affected metric class (IoU matrix [[1.0, 0.667], [0.333, 0.538]])
- Add kind='stable' to np.argsort in _match_detection_batch across all 5 metric
  implementations (Recall, Precision, F1Score, MeanAverageRecall, deprecated
  MeanAveragePrecision) to ensure deterministic TP assignment when IoU values tie
- Add test_greedy_matching_two_valid_pairs to TestDetectionMetrics covering the
  deprecated MeanAveragePrecision._match_detection_batch with the issue #2378 IoU
  matrix, closing the one missing regression test flagged by /review

* refactor(metrics): extract _greedy_match helper to eliminate 5x duplication

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-01 12:30:09 +02:00
97f5c0ca53 perf(annotators): skip corner circles when drawing square label backgrounds (#2346)
Both rounded-rectangle helpers (LabelAnnotator.draw_rounded_rectangle and the
public draw_rounded_rectangle in draw/utils) always drew two rectangles plus
four corner circles, even when border_radius is 0, which is the default for
LabelAnnotator and VertexLabelAnnotator. With a zero radius that is six cv2
calls per label per frame (the four circles are zero-radius no-ops) where one
fill rectangle does the same thing.

Add a square-corner fast path to both helpers. Output is pixel identical; only
the redundant calls go away. On a 1080p frame with 100 labels LabelAnnotator
drops from ~2.1 ms to ~1.3 ms (about 1.6x), and the rounded-rectangle call
itself is ~2.8x faster at radius 0. The radius > 0 path is unchanged.

Adds tests pinning square output to a plain rectangle for both helpers (the
public draw/utils function had no tests before).

- Rename LabelAnnotator.draw_rounded_rectangle to _draw_rounded_rectangle
  (accidentally public static method — now signals internal)
- Expand draw/utils.py border_radius docstring: document <= 0 and
  clamp-to-zero fast-path behaviour
- Add crash-era comment to both test files: border_radius < 0 previously
  raised cv2.error; fast path silently draws square corners instead
- Add clamped-to-zero test in both test files: positive radius on a
  1px-wide box clamps to 0 and triggers the fast path
- Strengthen positive-radius assertion: full center-row check + all four
  corners unpainted (replaces two-pixel spot check)
- Add pytest.param(id=) slugs to all parametrize decorators per
  CONTRIBUTING.md convention
- Add Google-style docstring with Args, Returns, Example to
  `LabelAnnotator.draw_rounded_rectangle` (was undocumented @staticmethod)
- Rename `testdraw_*` → `test_draw_*` in `TestLabelAnnotator` to restore
  consistent test naming broken by the earlier private-rename commit
- Expand `draw/utils.draw_rounded_rectangle` border_radius docstring:
  note that negative values previously raised `cv2.error` and now draw
  square corners silently; drop "as a fast path" implementation detail
- Add `Example:` block to `draw/utils.draw_rounded_rectangle`

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-07-01 01:25:25 +02:00
e1b7a16101 fix(detection): keep from_inference aligned on partial masks (#2362)
process_roboflow_result appended a mask only for predictions carrying one
(RLE or polygon), while xyxy/confidence/class_id were appended for every
prediction. A result mixing masked and box-only predictions (e.g. a
segmentation batch where one polygon is empty) produced a mask array shorter
than the boxes, so Detections.from_inference raised a shape-mismatch error.

Append None for box-only predictions and build the mask array only when every
prediction has a mask, otherwise drop masks to preserve alignment, mirroring
the tracker_id handling. Fully-masked and mask-free results are unchanged.

- Update `masks` Returns clause to document partial-drop case and corrupt-RLE blast radius (D1+C1)
- Remove stale "known limitation" note from from_inference docstring; describe actual behavior (D2)
- Extract _all_present_or_none() helper; eliminate duplicated partial-drop-warn pattern (S1)

---------

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-01 00:52:57 +02:00
15f56dea30 chore(pre_commit): ⬆ pre_commit autoupdate (#2375)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/JoC0de/pre-commit-prettier: v3.8.4 → v3.9.3](https://github.com/JoC0de/pre-commit-prettier/compare/v3.8.4...v3.9.3)
- [github.com/tox-dev/pyproject-fmt: v2.25.0 → v2.25.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.25.0...v2.25.1)
- [github.com/astral-sh/ruff-pre-commit: v0.15.18 → v0.15.20](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.18...v0.15.20)

* fix(pre_commit): 🎨 auto format pre-commit hooks
* fix(pyproject): restore valid mypy TOML overrides
* chore: update pyproject.toml to exclude examples and tests in mypy configuration

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
2026-06-30 23:02:13 +02:00
Jirka BorovecandCodex 934da124f5 chore(typing): Add explicit selection helpers (#2373)
* Add explicit selection helpers
* improve typing in detection metrics and update pre-commit dependencies

- Add explicit type annotation for `panel_array` in `_draw_panel` function.
- Update `.pre-commit-config.yaml` to include `tomli>=2.0.1` as an additional dependency for `pyproject-fmt`.

---------

Co-authored-by: Codex <codex@openai.com>
2026-06-29 15:39:58 +02:00
pre-commit-ci[bot]andJirka Borovec ad2c75021f chore(pre_commit): ⬆ pre_commit autoupdate (#2248)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/JoC0de/pre-commit-prettier: v3.8.3 → v3.8.4](https://github.com/JoC0de/pre-commit-prettier/compare/v3.8.3...v3.8.4)
- [github.com/tox-dev/pyproject-fmt: v2.21.1 → v2.25.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.21.1...v2.25.0)
- [github.com/astral-sh/ruff-pre-commit: v0.15.12 → v0.15.18](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.12...v0.15.18)
- [github.com/pre-commit/mirrors-mypy: v1.20.2 → v2.1.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.20.2...v2.1.0)

---------

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>
2026-06-29 14:52:18 +02:00
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
5a90113b15 ⬆️ Update mkdocstrings-python requirement from <2,>=1.10.9 to >=1.10.9,<3 (#2366)
* ⬆️ Update mkdocstrings-python requirement

Updates the requirements on [mkdocstrings-python](https://github.com/mkdocstrings/python) to permit the latest version.
- [Release notes](https://github.com/mkdocstrings/python/releases)
- [Changelog](https://github.com/mkdocstrings/python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/python/compare/1.10.9...2.0.5)

---
updated-dependencies:
- dependency-name: mkdocstrings-python
  dependency-version: 2.0.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

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

* Update docs dependency stack for mkdocstrings 2

Move mkdocstrings-python handler options to their 2.x-compatible location, scope the docs dependency group to Python 3.10+, and keep the general pytest matrix from installing docs dependencies.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.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>
Co-authored-by: Codex <codex@openai.com>
2026-06-29 11:20:32 +02:00
dependabot[bot]andJirka Borovec 58aacd3f74 ⬆️ Update pytest requirement from <9,>=7.2.2 to >=7.2.2,<10 (#2363)
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.2.2...9.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 9.1.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-06-29 10:52:52 +02:00
b5f0752f41 ⬆️ Update build requirement from <1.5,>=0.10 to >=0.10,<1.6 (#2365)
* ⬆️ Update build requirement from <1.5,>=0.10 to >=0.10,<1.6

Updates the requirements on [build](https://github.com/pypa/build) to permit the latest version.
- [Release notes](https://github.com/pypa/build/releases)
- [Changelog](https://github.com/pypa/build/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/build/compare/0.10.0...1.5.0)

---
updated-dependencies:
- dependency-name: build
  dependency-version: 1.5.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Apply suggestions from code review

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.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-06-29 10:48:06 +02:00
939097bdce ⬆️ Update mkdocstrings requirement from <0.31,>=0.25.2 to >=0.25.2,<1.1 (#2364)
* ⬆️ Update mkdocstrings requirement

Updates the requirements on [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) to permit the latest version.
- [Release notes](https://github.com/mkdocstrings/mkdocstrings/releases)
- [Changelog](https://github.com/mkdocstrings/mkdocstrings/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/mkdocstrings/compare/0.25.2...1.0.4)

---
updated-dependencies:
- dependency-name: mkdocstrings
  dependency-version: 1.0.4
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Apply suggestions from code review

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.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-06-29 10:43:02 +02:00
Jirka BorovecandCodex 46fdd5ceba fix(pre-commit): pin mypy hook python version (#2371)
Co-authored-by: Codex <codex@openai.com>
2026-06-29 10:19:51 +02:00
Jirka BorovecandCodex 09b21992c5 chore: port example typing refinements (#2358)
Co-authored-by: Codex <codex@openai.com>
2026-06-27 09:08:54 +02:00
Jirka BorovecandCodex 10b538373b chore: postpone annotations and add validation refinements (#2357)
Add postponed annotations to test modules and modernize one test helper annotation for Python 3.9-compatible collection.

---------

Co-authored-by: Codex <codex@openai.com>
2026-06-27 08:36:26 +02:00
f34a940c0a chore: postpone annotations in src typing (#2356)
* chore: postpone annotations in src typing
* chore: refine py310 source typing
* chore: add TypeGuard import for typing_extensions under TYPE_CHECKING
* chore: port source typing refinements
* chore(detection): update confusion matrix examples to use integer dtype
* chore: replace pipe-based typing with Union in key points module
* chore(detection): replace pipe-based typing with Union for compatibility
* chore: remove untyped import ignores for deprecated library

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-27 07:23:05 +02:00
jirka 4b867f282b chore: update .gitignore to include additional directories and files 2026-06-26 22:29:15 +02:00
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
2aa43bceab Inference slicer batching (#1239)
- Port OBB sequential fallback to batch path (same guard as single-image path)
- Port compact_masks RLE compression into _run_callback_batch
- Port out-of-slice-bounds SupervisionWarnings to _run_callback_batch
- Add list-type and length-match guard before zip in _run_callback_batch
- Add OBB-with-thread_workers warning to batch path
- Widen callback param annotation to union of single-image and batch signatures
- Update class docstring: dual callback contract, batch_size arg, new Raises, usage example
- Remove redundant list() re-wraps in batch execution path
- Add TestInferenceSlicerBatch: 12 parametrised tests covering all new batch behaviours

---------

Co-authored-by: Linas Kondrackis <linas.ko+dev@skiff.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: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-26 19:15:54 +02:00
7239af5048 Refactor/remove asserts annotators image (#2354)
- ValueError → TypeError in all three ensure_*_image_for_* decorators (conversion.py): the decorator intercepts non-ndarray/PIL inputs before the wrapped body runs, so the inner raises were unreachable; fixing at the decorator level fixes all annotators at once
- Remove 5 dead isinstance guards from key_points/annotators.py and 4 from utils/image.py (all now covered by the decorator fix)
- Remove dead assert isinstance(scene, Image.Image) from RichLabelAnnotator.annotate (ensure_pil_image_for_class_method guarantees PIL.Image before inner body)
- Add @ensure_cv2_image_for_class_method to VertexLabelAnnotator.annotate for PIL parity (only decorated annotator missing it)
- Rewrite tests to call public API directly (no __wrapped__ bypass); replace with TestAnnotatorInputValidation class (parametrized, IDs, AAA) + parametrized test_image_utils_wrong_type_raises
- Add Raises: TypeError sections to all 6 annotator .annotate() docstrings, 4 image util docstrings, and 3 decorator docstrings

---------

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 17:51:01 +02:00
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
jirkaandclaude[bot] 25d98c85f3 test(dataset): refactor labelme tests with parametrize
- Merge test_polygon_shapes_require_image_dims and test_force_masks_requires_image_dims into test_requires_image_dims_when_mask_needed with polygon-shape and force-masks-rectangle ids

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-25 17:18:25 +02:00
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
jirkaandclaude[bot] a3a860cf3f test(dataset): refactor createml tests with parametrize
- Merge 4 separate malformed-annotation raises into parametrized test_raises_on_malformed_annotation
- Merge 3 path-security raises into parametrized test_raises_on_unsafe_image_path (lambda captures per-case images_directory_path)
- Merge 3 malformed-JSON raises into parametrized test_raises_on_malformed_json
- Merge 2 save/load round-trip tests into parametrized test_save_load_round_trip
- Drop unused DoesNotRaise/ExitStack and exception param from test_converts_annotations

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-25 15:43:02 +02:00
9ff41b9706 feat(dataset): add CreateML format support to DetectionDataset (#2284)
- Added CreateML import/export support for detection datasets, including pixel-space center/width/height box conversion, class-name inference, global class-id consistency, and image path safety validation.
- Added optional progress bars for CreateML loading, exporting, and image saving.
- Improved CreateML validation with clear errors for malformed JSON, missing fields, duplicate images, null annotations, and unsafe image paths.
- Updated dataset documentation and references to include CreateML workflows and `from_createml` / `as_createml` usage.

---------

Co-authored-by: jirka <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 15:26:34 +02:00
jirkaandclaude[bot] 44b62cd164 test(detection): refactor GeoTIFF slicer tests with fixtures and parametrize
- Convert `_fixed_detection_callback` module fn to `fixed_detection_callback` fixture
- Add `make_raster_dataset` factory fixture replacing direct `_FakeRasterDataset(...)` calls in 8 tests
- Add `make_recording_callback` factory fixture replacing duplicated closure pattern
- Merge `test_windowed_raster_reads_correct_window_content` and `test_windowed_raster_matches_in_memory_array_with_overlap` into single parametrized `test_raster_tiles_match_array_tiles[no-overlap|with-overlap]`
- Drop verbose section divider comments

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-25 14:24:54 +02:00
a179d9120f feat(detection): support windowed GeoTIFF reads in InferenceSlicer (#2281)
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>
2026-06-25 14:07:42 +02:00
14f6f245c8 Docs/convert detections doctests (#2351)
* docs: convert Detections.empty and Detections.merge examples to doctests

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Dylan Parsons <dylanparsons@users.noreply.github.com>
2026-06-24 08:19:04 +02:00
jirka 3e610a0558 Bump version to 0.30.0.dev 2026-06-23 22:14:07 +02:00
af6365acfb feat: add show_progress to dataset load/save operations (#2275)
- Added optional progress bars for dataset loading and saving across detection and classification datasets via a `show_progress` parameter, covering COCO, YOLO, Pascal VOC, and folder-structure workflows while remaining disabled by default for backward compatibility.
- Improved progress reporting accuracy by providing total item counts to progress bars during dataset loading operations.
- Updated dataset save and load APIs and documentation to consistently support progress display options across formats.
- Fixed documentation examples and doctests to remain runnable without requiring progress-bar-specific arguments.
- Fixed progress-bar integration and test coverage to ensure correct behavior for all supported dataset formats, save/load paths, and default no-progress behavior when `show_progress` is not enabled.

---------

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-23 22:04:49 +02:00
Jirka Borovec 49ecac0376 Releasing supervision 0.29.1 (#2350) 2026-06-23 21:53:06 +02:00
dependabot[bot] 9251893bd9 ⬆️ Bump jupyterlab from 4.5.7 to 4.5.9 in the uv group across 1 directory (#2348)
---
updated-dependencies:
- dependency-name: jupyterlab
  dependency-version: 4.5.9
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 16:17:44 +02:00
dependabot[bot] ccd7098f2f ⬆️ Bump actions/checkout from 6 to 7 in the github-actions group (#2347)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 08:55:18 +02:00
jirka 07d182be56 docs: refine Table of Contents formatting with collapsible details 2026-06-19 09:21:02 +02:00
Vikas sainiandpre-commit-ci[bot] cca3c14911 Docs: Refactor README formatting and fix pre-commit hook (#2316)
Updated README to improve formatting and structure.
Updated links, section headers, and example code paths in README.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-18 15:42:25 +02:00
44546a13f2 fix(vlm): handle malformed Gemini/Qwen model output without crashing (#2342)
Two ways the VLM parsers crashed on adversarial model output instead of
degrading gracefully (the contract they already honor for invalid JSON):

1. Gemini 2.5: a mask value that is not a 'data:image/png;base64,' string
   appended an empty mask and then 'continue'd, skipping the confidence
   handler at the bottom of the loop. The item's box was recorded but its
   confidence was not, so the confidence array ended up shorter than xyxy
   and Detections.from_vlm raised a shape ValueError. Replaced the
   'continue' with an if/else so the confidence handler always runs.

2. Gemini 2.0 / Gemini 2.5 / Qwen 2.5: valid JSON whose top level is not a
   list, or whose elements are not dicts (e.g. '[1, 2, 3]'), raised
   TypeError from the 'key not in item' membership test. Added a top-level
   list guard (Gemini 2.0/2.5; Qwen already had one) and a per-element
   dict guard so wrong-shaped JSON degrades to empty Detections.

Add regression tests for the mask/confidence alignment and for graceful
degradation across all three parsers.

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-18 15:31:31 +02:00
4b60bbc9cc fix(dataset): stop Pascal VOC export from mutating source detections (#2341)
object_to_pascal_voc applied the 1-index offset in place (xyxy += 1).
Because Detections.__iter__ yields each row of xyxy as a view sharing
memory with detections.xyxy, detections_to_pascal_voc wrote the +1 shift
straight back into the caller's array. A single export shifted every box
by +1px; a second export compounded it, producing wrong XML. A single
export-then-reload happened to round-trip because from_pascal_voc
subtracts 1, which is why no test caught it.

Rebind to a new array (xyxy = xyxy + 1) instead of mutating in place.
On-disk output is unchanged; the source detections are left intact.

Add regression tests asserting object_to_pascal_voc does not mutate its
inputs and that two consecutive exports are identical and leave xyxy
unchanged.

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-18 15:29:37 +02:00
6918d44190 docs(cookbooks): add Oriented Bounding Boxes cookbook (#2314)
- Added an end-to-end cookbook focused on oriented bounding boxes (OBB), demonstrating how OBB detections differ from axis-aligned boxes, why oriented overlap and NMS matter, how to use footprint-based filtering with `Detections.area`, and how to export annotations in YOLO OBB format.
- Added visual examples that clearly compare axis-aligned and oriented boxes, including a close-up showing how axis-aligned envelopes can significantly overestimate object footprints for angled objects.
- Improved the cookbook narrative to center on the practical consequences of using oriented versus axis-aligned boxes, including tighter localization and more appropriate NMS behavior for densely packed, rotated objects.
- Updated cookbook references, naming, dependency versions, image attribution, and changelog links to align with the released 0.29.0 documentation.
- Fixed the 0.29.0 changelog by removing a duplicate `Detections.area` entry and keeping the more accurate correctness-fix classification.

---------

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-18 13:33:30 +02:00
a48532f6f5 perf(annotators): share mask painting and give HaloAnnotator the CompactMask path (#2339)
MaskAnnotator paints CompactMask detections into their bounding-box crop, but
HaloAnnotator never got that path: it materialized every mask full-frame, painted
via full-frame boolean indexing, and built its foreground mask as a 2M-element
Python list per frame. Extract the shared compact/dense painting into a single
_paint_masks_by_area helper used by both annotators. On a 1080p frame with 30
masks, HaloAnnotator on CompactMask runs about 4x faster; output is unchanged.

- Replace in-place `union` param with `collect_union: bool` return value;
  HaloAnnotator now captures the returned union array
- Add Google-style Args/Returns to `_paint_masks_by_area` docstring
- Fix HaloAnnotator.annotate() example (was maskless → no-op) and scene arg wording
- Add section comment above shared helper for discoverability
- Add union accumulation tests (dense + CompactMask paths via collect_union=True)
- Add test documenting out-of-bbox True-pixel divergence between compact and dense
- Add image-edge bbox test for CompactMask annotators
- Move helper tests into TestPaintMasksByArea and TestCompactMaskParity classes
- Rename test_annotate_with_empty_masks → test_annotate_with_all_false_mask

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-18 12:37:11 +02:00
11a586c133 perf(detection): compute mask IoU via matmul instead of an (N, M, H, W) intermediate (#2323)
- Reimplemented dense mask IoU/IoS computation using matrix multiplication on flattened masks instead of constructing a full `(N, M, H, W)` overlap tensor
- Significantly reduced memory usage and improved performance for large mask sets while preserving identical IoU/IoS results
- Added automatic precision handling for large masks to keep intersection and area counts numerically accurate
- Improved memory-limit handling and chunking logic to reflect actual matmul memory usage
- Added validation that compared mask sets share the same spatial dimensions
- Added validation for invalid mask tensor ranks and input shapes
- Added safe handling for empty-mask inputs
- Added warnings when inputs exceed the minimum memory footprint that chunking cannot reduce
- Fixed large-mask area calculations that could produce incorrect IoU values
- Suppressed spurious runtime warnings during valid matrix-multiplication computations
- Added regression coverage for correctness, chunking, rectangular matrices, empty inputs, shape mismatches, large-mask precision, and memory-limit edge cases

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-18 10:45:56 +02:00
31e84f7909 feat: add KeyPoints.with_nms() method (#2338)
* feat: add with_nms() method to KeyPoints class Derive axis-aligned bounding boxes from valid keypoints and delegate to box_non_max_suppression for filtering. Requires detection_confidence; supports class-aware and class-agnostic modes.

- Add overlap_metric: OverlapMetric = OverlapMetric.IOU param to KeyPoints.with_nms() for API parity with Detections.with_nms()
- Integrate self.visible into keypoint validity: valid = valid & self.visible when visible is not None
- Pass overlap_metric through to box_non_max_suppression
- Fix docstring: add Defaults to for threshold/class_agnostic, threshold range constraint, overlap_metric arg
- Add UnReleased changelog entry
- Add 5 new test cases: all-zero-skeleton-passes-through, visible-mask-excludes-keypoints-from-bbox, single-valid-keypoint-zero-area-bbox, threshold boundary 0.0/1.0
- Add missing raises test: no-detection-confidence-class-agnostic
- Update `with_nms` method to raise `ValueError` instead of `AssertionError` for missing required fields (`detection_confidence`, `class_id` when `class_agnostic=False`).
- Adjust corresponding test to check for `ValueError` with match argument.

---------

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-18 10:42:43 +02:00
jirka 7e765eb054 docs: reformat entries in changelog for improved readability 2026-06-17 22:41:17 +02:00
393ff52954 fix(json_sink): serialize NumPy scalars in custom_data (#2334)
- Fixed `JSONSink` to correctly serialize NumPy scalar values stored in `custom_data`
- Added JSON serialization support for NumPy arrays by converting them to standard JSON-compatible lists
- Prevented buffered export failures caused by non-serializable NumPy values during `json.dump`
- Added regression coverage for multiple NumPy scalar types, NumPy arrays, and unsupported-object error handling
- Updated documentation and changelog to describe NumPy serialization behavior in `JSONSink`

---------

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-17 22:27:03 +02:00
c9962c9262 fix(smoother): handle detections without confidence (#2333)
- Fixed `DetectionsSmoother` to work with detections that have no confidence scores
- Changed confidence aggregation to average only the confidence values that are present, leaving confidence as `None` when no values exist
- Fixed smoothing of mixed-confidence tracks (some frames with confidence, some without) while preserving available confidence information
- Fixed crashes when merging smoothed tracks that disagree on confidence availability by normalizing confidence fields before merge
- Added regression coverage for no-confidence, mixed-confidence, multi-track, full-window, and tracker-id-missing scenarios
- Updated documentation and changelog to reflect the new confidence-handling behavior

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-17 21:16:43 +02:00
04b6d45ea2 fix(polygons): honor target point count in approximate_polygon (#2332)
- Fixed `approximate_polygon` so the returned polygon respects the requested point-count reduction target instead of returning an over-budget approximation
- Preserved the minimum valid polygon size (3 points) while simplifying polygons
- Added validation requiring `epsilon_step > 0` to prevent invalid and non-terminating configurations
- Added regression tests covering target-point budgeting, polygon validity, invalid percentage values, and invalid `epsilon_step` values
- Improved documentation with clearer behavior guarantees, validation rules, examples, and edge-case explanations

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-17 21:11:26 +02:00
2854932965 fix(metrics): count false positives on background images and absent classes (#2331)
- Fixed Precision and F1Score metrics to correctly count false positives on images with no ground-truth objects
- Fixed Precision and F1Score metrics to include prediction-only classes when computing class statistics and confusion-matrix aggregates
- Corrected MICRO and MACRO averaging so false positives from absent classes affect the score as expected
- Preserved WEIGHTED averaging behavior by weighting only classes with ground-truth support
- Added safeguards for all-background evaluation batches, returning stable zero-valued weighted scores when no support exists
- Fixed handling of predictions with `class_id=None` in background-only evaluation paths
- Added regression coverage for background-image false positives, absent-class predictions, averaging modes, and zero-support edge cases
- Updated metric documentation and result metadata to reflect that tracked classes now include prediction-only classes

---------

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-17 19:46:10 +02:00
bcc785fbb5 fix(ci): clear latest alias before deploying docs to release/latest (#2340)
mike deploy fails when target name exists as an alias; delete it first.

---------

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-06-17 19:36:25 +02:00
c0df72b84a perf: vectorize mask_to_xyxy and KeyPoints.as_detections (bit-identical) (#2330)
- Vectorized `mask_to_xyxy` by replacing per-mask pixel scans with batched occupancy-profile reductions, yielding large speedups while preserving identical outputs
- Added direct test coverage for `mask_to_xyxy`, including edge and corner-pixel mask cases
- Vectorized `KeyPoints.as_detections` by computing all bounding boxes in a single batch operation instead of constructing and merging per-skeleton `Detections`
- Vectorized keypoint-confidence aggregation in `KeyPoints.as_detections` using NumPy reductions
- Preserved exact output behavior for bounding boxes, confidence values, class IDs, metadata, selected-keypoint subsets, and missing-keypoint handling
- Added regression coverage for selected-keypoint indexing, mixed valid/invalid skeleton batches, detection-confidence paths, and confidence aggregation behavior
- Fixed strict mypy typing issues introduced by the vectorized implementations
- Improved documentation for `mask_to_xyxy` and `selected_keypoint_indices` behavior

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-17 18:58:47 +02:00
15cf80abac fix: accept deprecated confidence kwarg in KeyPoints() constructor (#2335)
- Move conflict ValueError before warn_deprecated so stray warning not
  emitted on invalid calls (both kwargs passed)
- Add backtick-quoted version numbers to deprecation message for style
  consistency with other warn_deprecated calls in the same class
- Make ValueError message actionable: name deprecated param and remedy
- Add Google-style docstring to __init__: Args + Raises sections
- Fix pre-existing mypy error in detection/core.py (_merge_obb_corners
  had bare np.ndarray without type args)
- Add docstrings to all test methods in TestDeprecatedConfidenceConstructor
- Parametrize ValueError test with both kwarg orderings (confidence-first
  and keypoint-confidence-first) to document order-independence
- Add test_constructor_normal_keypoint_confidence_path: confirms custom
  __init__ initialises all fields and emits no warning on normal path
- Add test_constructor_confidence_none_does_not_warn: guards the
  `if confidence is not None` branch against guard-condition typos
- Add test_constructor_data_none_defaults_to_empty_dict: tests the
  None->{} normalisation path introduced by the custom __init__
- Add test_keypoints_init_covers_all_dataclass_fields: drift guard that
  asserts dataclasses.fields(KeyPoints) == __init__ params, catching
  future field additions that forget to update __init__

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-17 16:15:34 +02:00
Jirka Borovec b9c24ddafd docs(changelog): backfill missing 0.29.0 entries and fix duplicate (#2329) 2026-06-16 12:16:38 +02:00
c2490e6015 chore: preserve all polygons when exporting multi-part masks to COCO (#2322)
* test(coco): strengthen multi-polygon export test coverage
* docs(coco): document segmentation shape and iscrowd routing in docstring
* test(coco): parametrize multipart polygon tests

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.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-16 00:43:19 +02:00
Jirka Borovec a914a00ab8 docs: fix broken links in changelog file (#2328) 2026-06-16 00:16:00 +02:00
dependabot[bot] d3a0a84dd5 ⬆️ Bump the uv group across 1 directory with 2 updates (#2326)
Bumps the uv group with 2 updates in the / directory: [cryptography](https://github.com/pyca/cryptography) and [tornado](https://github.com/tornadoweb/tornado).


Updates `cryptography` from 46.0.7 to 48.0.1
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.7...48.0.1)

Updates `tornado` from 6.5.6 to 6.5.7
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.5.6...v6.5.7)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 48.0.1
  dependency-type: indirect
- dependency-name: tornado
  dependency-version: 6.5.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 23:45:40 +02:00
SkalskiP 1e551ec9c0 releasing 0.29.0 2026-06-15 23:36:28 +02:00
SkalskiP 1fa735d0d9 releasing 0.29.0rc1 2026-06-15 23:24:53 +02:00
Piotr Skalski 62a24d7960 Unify deprecation policy: enforce 3 minor release minimum window (#2324)
* Unify deprecation policy: 3 minor releases minimum

* Add 0.29.0 changelog entry

* Bump version to 0.29.0
2026-06-15 23:04:55 +02:00
Piotr Skalski 3d07099cf9 Fix ellipse annotators to draw level-by-level instead of point-by-point (#2325) 2026-06-15 22:51:06 +02:00
483e3e9335 fix(detection): make oriented_box_iou_batch exact and gate non-overlapping pairs (#2317)
* fix(detection): make oriented_box_iou_batch exact and gate non-overlapping pairs
* test(detection): cover gate passthrough and invalid metric in oriented IoU
* test(detection): add edge-case OBB coverage for oriented_box_iou_batch

- Parametrize test_self_comparison_is_symmetric_with_unit_diagonal with N=1
  and N=2 (R6: N=1 path exercising triangular-mirror with single (0,0) pair)
- Add test_degenerate_boxes_score_zero: collapsed, collinear, zero-area
  self-comparison → 0.0 (documents divergence from box_iou_batch semantics)
- Add test_empty_input_returns_correct_shape: (0,M), (N,0), (0,0) variants
  exercising early-return path at TestOrientedBoxIouBatch level
- Add test_invalid_shape_raises_value_error: 3-D wrong inner dims, 2-D wrong
  columns, 1-D input — matches exact error messages from implementation
- Fix test_is_invariant_to_canvas_transforms: remove stale pixel-IoU /
  canvas reference; tighten tolerances to rtol=1e-5 / atol=1e-7 (exact
  arithmetic no longer has quantization noise)
- Add Raises: section to oriented_box_iou_batch documenting all four
  ValueError paths (3-D wrong inner dims, 2-D wrong columns, wrong ndim,
  unsupported overlap_metric)
- Add Note: block documenting is_self_comparison identity-based contract
  (disabled by upstream .copy()), convexity precondition, and NaN/Inf
  silent-zero behavior
- Align Returns: style with box_iou_batch sibling (named entry semantics)
- Add Examples: doctest block (doctest: +ELLIPSIS for IoU value)
- Strengthen np.clip comment: explicitly mark as load-bearing; explains
  that cv2 intersection in float32 can exceed float64 area by ~25 ULP
- Add one-line comment at NMS caller: is_self_comparison trigger context
- Add Args:/Returns: to _polygon_areas and _aabb_envelopes private helpers
- Expand _overlapping_envelope_pairs docstring: Note (correctness guarantee
  — not an approximation), Args: and Returns: blocks

* refactor(detection): fuse _overlapping_envelope_pairs to halve peak memory
* test(detection): fix degenerate-collinear OBB NMM expectation for exact IoU

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-15 20:54:06 +02:00
e0e1abd865 fix(obb): NMM now computes geometric union via min-area rotated rect (#2312)
* 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>
2026-06-15 16:23:31 +02:00
117a9baab8 fix(coco): preserve segmentation in as_coco() round-trip (#2321)
* fix(coco): preserve segmentation in as_coco() round-trip (#2285)
* fix(coco): address Copilot review — normalize flat polygon lists, tighten test assertions
* fix(coco): type annotation, config constant, merge-compat, lint fixes
* test(coco): add two-polygon and RLE round-trip tests
* fix(tests): update expected_results for always-store coco_raw_segmentation
* fix(coco): use COCO_RAW_SEGMENTATION key in export fallback
* fix(coco): adjust mask_bool assignment to ensure proper usage in iscrowd logic
* test: simplify COCO segmentation regression cases
* fix(coco): add type annotation for raw_segs to ensure clarity
* test(coco): improve docstring and add comments for segmentation round-trip validation

---------

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>
Co-authored-by: Codex <codex@openai.com>
2026-06-15 15:00:27 +02:00
dependabot[bot] 497f336d13 ⬆️ Bump tornado from 6.5.5 to 6.5.6 in the uv group across 1 directory (#2315)
Bumps the uv group with 1 update in the / directory: [tornado](https://github.com/tornadoweb/tornado).


Updates `tornado` from 6.5.5 to 6.5.6
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.5.5...v6.5.6)

---
updated-dependencies:
- dependency-name: tornado
  dependency-version: 6.5.6
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-15 01:03:43 +02:00
jirka ef8ba557a1 releasing 0.29.0.rc0 2026-06-11 18:37:56 +02:00
caf060521d refactor: enrich KeyPoints with visibility mask, split confidence fields, and redesign uncertainty annotator (#2286)
- Added `KeyPoints.visible` mask support for per-keypoint visibility
- Split confidence into `keypoint_confidence` and `detection_confidence`
- Kept legacy `KeyPoints.confidence` as deprecated forwarding alias
- Updated `KeyPoints` slicing/filtering to preserve visibility and confidence fields
- Fixed `KeyPoints.__getitem__` row-index normalization for NumPy scalar, 0-D array, and boolean indexing
- Fixed `detection_confidence` indexing to use normalized row indices
- Updated `VertexAnnotator` to skip invisible keypoints
- Updated `EdgeAnnotator` to skip invisible keypoints and edges
- Added per-class skeleton support to `EdgeAnnotator`
- Added multi-skeleton support to `VertexLabelAnnotator`
- Added label validation for `VertexLabelAnnotator`
- Added color-list length validation for keypoint annotators
- Added `VertexEllipseAreaAnnotator`
- Added `VertexEllipseOutlineAnnotator`
- Added `VertexEllipseHaloAnnotator`
- Kept/exported `VertexEllipseAnnotator` alongside the new ellipse variants
- Standardized keypoint annotator docstrings and executable examples
- Added/updated `validate_detection_confidence` and `validate_visible`
- Removed/cleaned old keypoint validator shims
- Added regression tests for visibility, confidence fields, multi-skeleton behavior, and indexing edge cases
- Updated helpers and RF-DETR/keypoint tests for the new confidence/visibility model
- Added API design principles to contributing docs
- Ignored local multi-skeleton test script in `.gitignore`

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.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-06-11 18:34:33 +02:00
Jirka Borovec b8ebc14489 docs(agents): refine AGENTS.md (#2308) 2026-06-10 22:25:31 +02:00
8a4063086f chore: update YOLO OBB annotation export support (#2302)
* fix(yolo): validate OBB corner shape and test is_obb=False passthrough
* docs(config): add attribute docstring to ORIENTED_BOX_COORDINATES

---------

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-10 15:28:42 +02:00
a549f44792 Add OBB support to ConfusionMatrix via MetricTarget (#2247)
* feat(metrics): OBB support in ConfusionMatrix, MASKS guard, shape validation
* refactor(tests): extract reusable ConfusionMatrix MASKS test cases
* refine(metrics): exclude metric_target from ConfusionMatrix.__eq__
* refactor(metrics): consolidate _assert_supported_target call sites
* fix(metrics): normalise OBB (N,4,2) shape explicitly in detections_to_tensor
* test(metrics): add OBB wrong-target-cols case to validate_input_tensors
* test(metrics): add OBB edge-case parametrize cases to detections_to_tensor
* test(metrics): replace validate_input_tensors with _validate_input_tensors in test_detection
* refactor(metrics): make ConfusionMatrix unhashable
* fix(metrics): add shape validation to evaluate_detection_batch
* fix(metrics): cast class_id to float32 in detections_to_tensor
* test(metrics): fix test_evaluate_detection_batch targets shape

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.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-06-10 13:29:33 +02:00
cb9d3dccb8 chore(deprecation): use TargetMode enum to silence deprecate FutureWarnings on import (#2304)
* fix(deprecation): use TargetMode enum to silence deprecate FutureWarnings on import
* chore: bump `pydeprecate` dependency to v0.9 and update lockfile

---------

Co-authored-by: Jirka Borovec <6035284+Borda@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>
2026-06-09 23:40:16 +02:00
ace3ebd03e fix(detection): make Detections.area OBB-aware (#2306)
* fix(detection): make Detections.area OBB-aware

When detections carry ORIENTED_BOX_COORDINATES (the four xyxyxyxy corners),
the area property returned the area of the derived axis-aligned bounding
box instead of the rotated body. The AABB overestimates by up to ~2x for a
45-degree rotation, which silently miscomputes downstream values — most
visibly the area-sorted z-ordering inside MaskAnnotator / HaloAnnotator,
and any user code that filters detections by area.

* docs(detection): use string literal in Detections.area doctest
* test(detection): single-line docstring on test_uses_oriented_box_corners_when_present
* fix(detection): validate (N,4,2) shape of OBB data field in Detections.area
* perf(detection): replace np.roll pair with cross-diagonal shoelace in Detections.area
* perf(detection): cast x/y slices to float64 instead of full corners array
* refactor(detection): extract obb_polygon_area to detection/utils/boxes.py
* test(detection): add test_raises_on_malformed_obb_coordinates_shape
* test(detection): assert per-branch dtype contract for Detections.area
* docs(detection): document OBB dispatch contract and dtype in Detections.area docstring

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-09 22:20:34 +02:00
Jirka Borovecandpre-commit-ci[bot] 9faa4f6133 chore: update mdformat hook arguments to disable wrapping (#2307)
* chore: update `mdformat` hook arguments to disable wrapping
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-09 16:15:05 +02:00
97f4951f08 docs(contributing): formalise test conventions and doctest guidelines (#2305)
* formalise test conventions and doctest guidelines
* strengthen doctest rule and add syntax guide
* relax doctest rule to strong recommendation
* fix line-length ref and heading depth rules

---------

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-06-09 15:51:18 +02:00
3b485f719a refine(detection): make with_nms and with_nmm OBB-aware (#2303)
* fix(detection): make with_nms and with_nmm OBB-aware
* perf(detection): bound rasterization canvas in oriented_box_iou_batch
* fix(detection): with_nmm OBB/AABB xyxy fix; 3-path dispatch docs
* fix(detection): shape validation, NMM assert, docstring/Examples
* test(detection): with_nmm fallback, OBB AABB fix, boundary and IOS tests
* docs(changelog): document OBB with_nms/nmm behaviour change for #2303
* docs(detection): convert OBB NMS/NMM examples to doctests
* refactor(test): group OBB NMS/NMM tests into classes
* refactor(test): merge duplicate NMS class-awareness tests via parametrize
* refactor(test): parametrize overlap-metric and dispatch tests

---------

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-06-09 13:11:09 +02:00
c92458b70e fix(dataset): preserve OBB rotation in DetectionDataset.as_yolo (#2289)
DetectionDataset.from_yolo accepts is_obb=True and stores the four
corners in detections.data["xyxyxyxy"], but DetectionDataset.as_yolo
has no matching option and only reads xyxy/mask. The standard
from_yolo -> split -> as_yolo flow silently writes 5-token
axis-aligned lines, and re-loading the saved file with is_obb=True
crashes the validator because it expects 9 tokens.

Add is_obb to as_yolo, save_yolo_annotations, and
detections_to_yolo_annotations. When True, the four corners from
data["xyxyxyxy"] are serialized via the existing object_to_yolo
polygon path. Masks are ignored, mirroring from_yolo(is_obb=True)
semantics. A missing xyxyxyxy raises ValueError early.

- Add UserWarning in as_yolo when area/approx params passed with is_obb=True (silently ignored)
- Add UserWarning in detections_to_yolo_annotations when mask present + is_obb=True
- Update ValueError message to include expected shape (N, 4, 2) for manual callers
- Add Google-style docstrings to detections_to_yolo_annotations and save_yolo_annotations
- Add test: N>1 OBB detections per image (corner indexing via data-dict slicing)
- Add test: dataset round-trip with background-only (no label file) image
- Add test: as_yolo() without is_obb=True on OBB-loaded dataset emits 5-token lines
- Replace all tempfile.TemporaryDirectory / os.path.join / os.makedirs
  with pytest tmp_path and pathlib Path
- Merge 3 load-mask tests into parametrized test_load_yolo_annotations_mask_behaviour
  (obb-no-mask, obb-force_masks-ignored, segmentation-produces-mask)
- Merge token-count tests into parametrized test_dataset_as_yolo_obb_output_token_count
  (obb-save-nine-tokens, default-save-five-tokens)
- Split corner accuracy into dedicated test_dataset_as_yolo_obb_round_trip_corner_accuracy
- Drop import os and import tempfile

---------

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-08 15:31:04 +02:00
dependabot[bot] eef8c96d95 ⬆️ Bump the github-actions group with 2 updates (#2300)
Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [codecov/codecov-action](https://github.com/codecov/codecov-action).


Updates `astral-sh/setup-uv` from 8.1.0 to 8.2.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/08807647e7069bb48b6ef5acd8ec9567f424441b...fac544c07dec837d0ccb6301d7b5580bf5edae39)

Updates `codecov/codecov-action` from 6 to 7
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 8.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: codecov/codecov-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-08 13:45:31 +02:00
b82d6f95be fix: normalize file extension filters (#2298)
* fix: normalize file extension filters
* fix(file): add is_file and empty-ext guards
* test(file): collapse extension tests into parametrized form
* fix: match multi-part extension suffix tails

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Codex <codex@openai.com>
2026-06-08 13:41:25 +02:00
b18a30ea1a fix: support grayscale letterbox images (#2297)
- Delete letterbox_image alpha block (lines 266-270): block wrote to
  caller's input array, not image_with_borders; used wrong coordinate
  system (resized vs original dims); redundant since cv2.copyMakeBorder
  already sets alpha=0 in padded regions when given a 3-element value
- Add test_letterbox_image_for_rgba_opencv_image: asserts padded alpha=0,
  interior alpha preserved, and input array not mutated after call
- Update letterbox_image docstring: image param lists (H,W,3)/(H,W,4)/
  (H,W)/PIL shapes; add Note on BGRA alpha behavior; add grayscale doctest

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-07 11:06:21 -06:00
35006d7342 fix: sort YOLO class names by numeric keys (#2296)
* fix: sort yolo class names by numeric keys
* fix(yolo): reject double-hyphen keys in _is_int_like predicate
* fix(yolo): raise ValueError for mixed numeric/non-numeric names keys
* test(yolo): parametrize _extract_class_names with all key-type cases
* refine(yolo): rename lambda param key→k to avoid shadowing outer variable
* docs(yolo): comment bool guard in _is_int_like
* docs(yolo): docstring for _extract_class_names

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-07 10:54:43 -06:00
3410d92daa refactor: privatize validation helpers (#2294)
* refactor: privatize validation helpers
* fix: correct error message in _validate_keypoint_confidence

- Fix f"({n, m})" -> f"({n}, {m})" (set literal -> proper shape string)
- Fix error message "1D" -> "2D" to match actual array dimensionality

* fix: correct error message in _validate_xy

- Fix f"({n, m},)" -> f"({n}, {m}, 2) or ({n}, {m}, 3)"
- Fix error message "2D" -> "3D" to match actual array dimensionality

* bump pydeprecate version to >=0.9,<0.10 and fix type ignore tag for decorator
* chore: extend deprecation removal timeline to 0.32.0 across validators

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-06 13:15:54 -06:00
Piotr SkalskiandCursor 5a8e211a04 Docs/api design principles contributing (#2292)
* fix: resolve ruff line-length and mypy union syntax errors in keypoints module

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add API design principles to CONTRIBUTING.md

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 18:09:09 -06:00
Piotr Skalski 1e8a48559b Revert "feat: store keypoints on detections (#2290)" (#2291)
This reverts commit e03111e67c.
2026-06-04 11:43:48 -06:00
e03111e67c feat: store keypoints on detections (#2290)
* docs: add API design principles to contribution guidelines
* feat: store keypoints on detections
* test: add "keypoints" to internal test cases
* docs: document keypoints field semantics and add docstring + dtype guard
* refactor: deduplicate keypoints shape check and add K-mismatch guard
* docs: clarify Detections.keypoints vs sv.KeyPoints decision rule and add KeyPoints filter example
* feat(key_points): add KeyPoints.from_detections() cross-container adapter
* test: extend keypoints test coverage — dtype guard, __eq__, dynamic field sets
* test: expand keypoints test coverage (M7/M8)
* fix: correct validate_xy expected_shape and dimensionality message
* fix: add ndim guard in KeyPoints.from_detections
* test: add unit tests for KeyPoints.from_detections adapter
* refactor: fix class_id cast and import formatting in key_points

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-04 09:09:37 -06:00
Lourdhu RajuandClaude Opus 4.7 0c67942d32 Refactor/polygon zone doctest (#2264)
Replaces the static python code block with a pycon doctest using
primitive numpy inputs, so the example is now executed and verified
by `pytest --doctest-modules`. Removes the external YOLO, ByteTrack,
and cv2 dependencies from the example.

Follows the same pattern as PR #2207 (LineZone). Part of the
documentation-as-tests effort tracked in #2106.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 08:33:46 +02:00
7d2259669b Fix OBB IoU for non-square canvases (#2282)
* Fix OBB IoU canvas dimensions
* test(metrics): fix OBB metric parametrize — remove MAP, add smoke test
* test(metrics): clarify MAP OBB test is smoke test only
* test(iou): parametrize OBB scaling invariance test with y-dominant case
* fix(iou): add empty-input guard and x/y axis docs to oriented_box_iou_batch

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-01 09:20:38 +02:00
fb02e5c959 docs: clarify MaskAnnotator mask requirements (#2279)
* docs: clarify MaskAnnotator mask requirements
* Potential fix for pull request finding

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-29 10:24:45 +02:00
918b6139ef feat(keypoints): add keypoint conversion bridge (#2277)
* feat(keypoints): add RF-DETR keypoint conversion bridge
* feat: add RF-DETR keypoint uncertainty visualization
* refactor(keypoints): remove deprecated RF-DETR keypoint conversion logic
* refactor: improve internal handling of keypoint data and detection utilities
* fix(keypoints): handle non-finite confidence values and empty keypoint arrays
* docs(keypoint): add VertexEllipseAnnotator to annotators docs
* docs(keypoints): add Example block to KeyPoints.from_rfdetr docstring
* docs(keypoints): document source_shape HW ordering in from_rfdetr
* feat(keypoints): validate precision_cholesky shape in from_rfdetr
* refine(keypoints): add warning log for silent precision matrix failures
* fix(keypoints): fix mypy type errors in VertexEllipseAnnotator
* test(keypoints): add confidence_threshold filter test for VertexEllipseAnnotator
* test(keypoints): add max_axis_length cap and constructor validator tests
* docs(keypoints): document max_axis_length=None risk in VertexEllipseAnnotator
* docs(keypoints): add Raises section to VertexEllipseAnnotator.annotate docstring
* docs(keypoints): document confidence scale convention in from_rfdetr
* docs(keypoints): note from_rfdetr input convention in KeyPoints class docstring
* fix(types): improve type hinting for internal and keypoints modules
* fix(keypoints): handle None class_id in from_rfdetr conversion

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-28 10:36:41 +02:00
81218c5f1b fix(coco): emit 1-indexed category_id in COCO export (#2276)
* fix): emit 1-indexed category_id in COCO export
* test): add regression and guard tests for 1-indexed category_id
* docs): warn in coco_annotations_to_detections that remap is required

---------

Co-authored-by: madhavcodez <madhavcodez@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-27 10:40:32 +02:00
2c3a2ef6f9 fix(detection): preserve class_name string dtype on empty Detections.from_inference (#2270)
* fix): preserve class_name string dtype on empty Detections.from_inference
* test): fix stale float64 dtype expectation in test_process_roboflow_result
* docs): document data[class_name] contract in from_inference Returns
* fix): set string-dtype class_name on empty from_ultralytics and from_vlm paths
* test): strengthen from_inference empty-path dtype test
* test): cover SDK .dict() path for empty predictions in from_inference
* docs): add docstring to process_roboflow_result
* test): use dtype.kind comparison for empty/non-empty class_name
* docs): update example in `process_roboflow_result` docstring

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-27 10:39:49 +02:00
2fdb970430 fix(annotators): avoid divide-by-zero in HeatMapAnnotator on empty detections (#2269)
When HeatMapAnnotator is called on a fresh annotator with empty detections
(common on the first frames of a video before the model produces any output),
self.heat_mask is all zeros, so temp / temp.max() raises
RuntimeWarning: invalid value encountered in divide and produces nan/inf
in-flight. Skip the normalisation when temp.max() == 0; the resulting
all-zero heat mask filters out via the > 0 check below, so the scene is
returned unchanged.

- Fix `kernel_size: int = 25` → `int | None = 25`; document None disables blur
- Add Note to annotate docstring: empty detections returns scene unchanged
- Add happy path test: single detection must produce visible heat output
- Add stateful tests: empty→real and real→empty sequence coverage

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-26 22:27:07 +02:00
dependabot[bot] fb2dec9775 ⬆️ Update pydeprecate requirement from <0.8,>=0.7 to >=0.7,<0.9 (#2268)
Updates the requirements on [pydeprecate](https://github.com/Borda/pyDeprecate) to permit the latest version.
- [Release notes](https://github.com/Borda/pyDeprecate/releases)
- [Changelog](https://github.com/Borda/pyDeprecate/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Borda/pyDeprecate/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: pydeprecate
  dependency-version: 0.8.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-25 11:30:37 +02:00
befdb7c661 fix(dataset): make COCO annotation/image ids chainable across splits (#2267)
* fix(dataset): make COCO annotation/image ids chainable across splits (#768)

Exporting train/valid/test splits with DetectionDataset.as_coco
previously restarted image_id and annotation_id at 1 for every split,
producing three JSON files whose ids collided and could not be safely
merged into a single COCO collection.

Adds optional starting_image_id and starting_annotation_id parameters
to save_coco_annotations and DetectionDataset.as_coco (default 1 to
preserve existing behavior) and returns a (next_image_id,
next_annotation_id) tuple so callers can feed the result of one
export straight into the next:

    next_image, next_ann = train.as_coco(annotations_path="train.json")
    next_image, next_ann = valid.as_coco(
        annotations_path="valid.json",
        starting_image_id=next_image,
        starting_annotation_id=next_ann,
    )
    test.as_coco(
        annotations_path="test.json",
        starting_image_id=next_image,
        starting_annotation_id=next_ann,
    )

The images-only branch of as_coco (annotations_path=None) round-trips
the starting ids unchanged so chaining still works there.

Adds 4 regression tests covering defaults, custom starting ids,
end-to-end three-split chaining with global uniqueness assertions,
and the images-only round-trip.

* docs: address review polish on COCO id-chaining
* fix(dataset): align save_coco_annotations approximation_percentage default to 0.0
* docs(dataset): add one-line summary to save_coco_annotations docstring
* docs: add changelog entry for COCO id chaining (PR #2267)
* docs(dataset): document file_name uniqueness limitation in save_coco_annotations
* feat(dataset): validate starting_image_id and starting_annotation_id >= 1
* docs(dataset): add Example section to save_coco_annotations docstring
* docs(dataset): unpack final as_coco return value in chaining example
* test(dataset): add COCO chaining tests and fix test helper for zero detections

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-22 21:41:42 +02:00
cb259065a5 Add from_coco regression coverage for multi-segment COCO masks (#2258)
* test: cover from_coco multi-segment masks
* test: add from_coco multi-segment regression
* test: extract coco multi-segment fixture
* test(coco): move multi-segment mask test to TestFromCocoMasks
* test(coco): fix fixture area and document bbox intent
* test(coco): add force_masks=True sibling test for multi-segment masks
* test(coco): add uneven-length segments case to TestFromCocoMasks
* test(coco): parametrize force_masks in TestFromCocoMasks

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-22 20:42:11 +02:00
Madhav-C 4b856f1c04 docs(examples): fix outdated CLI flag names in heatmap_and_track README (#2266)
The README listed `--track_threshold` and `--match_threshold`, but
script.py exposes `--track_activation_threshold` and
`--minimum_matching_threshold` (the CLI surface is derived from the
main() signature by jsonargparse.auto_cli). Following the README as
written produced "unknown argument" errors.

Aligns the README with the actual CLI surface.
2026-05-22 20:00:30 +02:00
6461d3fbac Restructure annotator docs tabs to avoid Material’s 20-tab limit (#2257)
* Initial plan
* fix: split annotator docs tabs into categories
* test: harden annotator docs regression test
* docs: fix blur example assignment
* docs(annotators): restructure tabs, harden regression tests
* docs(annotators): remove broken oriented box preview image

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-22 19:54:33 +02:00
Jirka Borovec 2c13b269e6 Update changelog after version 0.28.0 release
Updated the date modified and added a new entry for version 0.28.0 with details on sv.CompactMask.
2026-05-22 19:14:29 +02:00
Jirka Borovec f1176270eb Bump version to 0.29.0.dev 2026-05-22 19:12:20 +02:00
5b883fed5b Guard InferenceSlicer against OBB callback crashes when thread_workers > 1 (#2256)
* fix: serialize OBB inference slicer callbacks
* test: simplify OBB slicer regression test
* refactor: simplify OBB slicer fallback path
* test: make OBB slicer regression deterministic
* fix(slicer): add thread_workers validation and lock for OBB warn flag
* docs(slicer): document OBB fallback, merge order, perf note, dual-use key

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@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>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-22 18:53:26 +02:00
Jirka Borovec e7376d558e ci(tests): disable matplotlib GUI and exclude non-test dirs from collection (#2262) 2026-05-20 23:40:21 +02:00
dependabot[bot] 17d7717515 ⬆️ Bump pymdown-extensions from 10.16.1 to 10.21.3 in the uv group across 1 directory (#2255)
Bumps the uv group with 1 update in the / directory: [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions).


Updates `pymdown-extensions` from 10.16.1 to 10.21.3
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.16.1...10.21.3)

---
updated-dependencies:
- dependency-name: pymdown-extensions
  dependency-version: 10.21.3
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 11:59:25 +02:00
dependabot[bot] 7e6df44d86 ⬆️ Bump idna from 3.10 to 3.15 in the uv group across 1 directory (#2254)
Bumps the uv group with 1 update in the / directory: [idna](https://github.com/kjd/idna).


Updates `idna` from 3.10 to 3.15
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md)
- [Commits](https://github.com/kjd/idna/compare/v3.10...v3.15)

---
updated-dependencies:
- dependency-name: idna
  dependency-version: '3.15'
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 11:50:16 +02:00
01ec36b31d fix: return empty int ndarray instead of None for class_id on empty VLM parse (#2239)
When from_paligemma or from_google_gemini_2_0 find no detections (no regex
matches, JSON decode error, or empty bounding-box list), they previously
returned None for class_id. All other early-exit and filter paths already
return a zero-length ndarray of dtype int. This inconsistency causes
downstream AttributeError when callers unconditionally call .shape or
iterate over the result.

Affected paths:
- from_paligemma: matches.shape[0] == 0 branch
- from_google_gemini_2_0: JSONDecodeError branch and len(xyxy) == 0 branch

---------

Co-authored-by: YousefZahran1 <youssefzahran.y@gmail.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-05-19 14:31:44 +02:00
f4b0767a88 docs: add sample image download and sv.plot_image() to detect_and_annotate tutorial (#2242)
* docs: add sample image download and sv.plot_image() to detect_and_annotate tutorial
* Potential fix for pull request finding

---------

Co-authored-by: PatelPrem21 <prem_23247@ldrp.ac.in>
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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-19 14:22:49 +02:00
7e28315595 fix: preserve audio stream in process_video (#2252)
- Move `tempfile.mkstemp` + `os.close` inside `try` block so OSError (disk full,
  unwritable dir) is caught by the existing `except Exception` handler instead of
  propagating to the caller, preserving the warn-and-degrade contract
- Pass `dir=os.path.dirname(os.path.abspath(video_path))` so the temp file is on
  the same filesystem as the output, restoring `os.rename` semantics in `shutil.move`
- Initialise `tmp_path = None` before `try`; guard `finally` with
  `tmp_path is not None` to satisfy mypy and avoid referencing an unbound name
- Add `-loglevel error -nostats` so ffmpeg only writes actual errors to stderr
  (eliminates progress/stats spam that would buffer in PIPE indefinitely)
- Decode `result.stderr` and include it in the warning when ffmpeg exits
  non-zero, so failure messages surface diagnostically instead of being discarded
- Change bare `process_video(...)` call to `sv.process_video(...)` so the
  example matches the public API pattern and does not raise NameError for users
  copying the snippet
- Remove unused `import cv2` which was never referenced in the example body
- Clarify that missing/failing ffmpeg warns and continues rather than raising
- Add install hint for ffmpeg (apt/brew)
- Note that audio is truncated to match the processed video duration (-shortest)
- test_mux_audio_moves_file_on_success: mock subprocess.run returncode=0;
  assert shutil.move is called once with video_path as destination — catches
  any regression that drops the move call after a successful ffmpeg run
- test_mux_audio_swallows_subprocess_exception: mock subprocess.run raising
  OSError; assert no exception escapes _mux_audio and original file is intact
- Fix failed_result.stderr = b"" in test_mux_audio_warns_on_ffmpeg_failure
  to match the updated _mux_audio which now decodes result.stderr
- Skip _mux_audio when writer_worker.is_alive() after join timeout to avoid
  muxing an incomplete output file
- Fix test_mux_audio_moves_file_on_success: patch os.replace (not shutil.move)
  to match implementation changed in 2027938d
- Move four test_mux_audio_* free functions into TestMuxAudio class
- Strip mux_audio_ prefix from method names; class carries the unit
- Condense multi-line docstrings to single-line per testing rules
- Collapse test_warns_when_ffmpeg_missing, test_warns_on_ffmpeg_failure,
  test_swallows_subprocess_exception into one parametrized
  test_file_unchanged_on_failure[ffmpeg_missing|ffmpeg_fails|subprocess_raises]
- Promote two class methods back to module-level functions
- Collapse nested with-patch statements into single with a, b: form

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-19 14:09:45 +02:00
b68b41ae7a ci(docs): skip RC tags, strip .postX, fix latest alias deploy (#2253)
- Skip mike deploy for RC releases (tags containing rc/RC)
- Strip .postX suffix before deploying (0.27.0.post1 → 0.27.0)
- Add -u flag to latest deploy to handle existing alias

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-19 12:02:24 +02:00
dependabot[bot] 6fb4e80837 ⬆️ Bump mistune from 3.1.3 to 3.2.1 in the uv group across 1 directory (#2250)
Bumps the uv group with 1 update in the / directory: [mistune](https://github.com/lepture/mistune).


Updates `mistune` from 3.1.3 to 3.2.1
- [Release notes](https://github.com/lepture/mistune/releases)
- [Changelog](https://github.com/lepture/mistune/blob/main/docs/changes.rst)
- [Commits](https://github.com/lepture/mistune/compare/v3.1.3...v3.2.1)

---
updated-dependencies:
- dependency-name: mistune
  dependency-version: 3.2.1
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-14 13:02:13 +02:00
7dce60697f Simplified wording Update README.md (#2249)
---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-13 18:25:06 +02:00
dependabot[bot] 26ae68a2b6 ⬆️ Bump AButler/upload-release-assets from 3.0 to 4.0 in the github-actions group (#2243)
Bumps the github-actions group with 1 update: [AButler/upload-release-assets](https://github.com/abutler/upload-release-assets).


Updates `AButler/upload-release-assets` from 3.0 to 4.0
- [Release notes](https://github.com/abutler/upload-release-assets/releases)
- [Commits](https://github.com/abutler/upload-release-assets/compare/v3.0...v4.0)

---
updated-dependencies:
- dependency-name: AButler/upload-release-assets
  dependency-version: '4.0'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-13 17:58:05 +02:00
dependabot[bot] 878e6414da ⬆️ Bump jupyter-server from 2.16.0 to 2.18.0 in the uv group across 1 directory (#2245)
Bumps the uv group with 1 update in the / directory: [jupyter-server](https://github.com/jupyter-server/jupyter_server).


Updates `jupyter-server` from 2.16.0 to 2.18.0
- [Release notes](https://github.com/jupyter-server/jupyter_server/releases)
- [Changelog](https://github.com/jupyter-server/jupyter_server/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter-server/jupyter_server/compare/v2.16.0...v2.18.0)

---
updated-dependencies:
- dependency-name: jupyter-server
  dependency-version: 2.18.0
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-13 17:57:51 +02:00
2beeda7851 docs: link "Memory-Efficient Instance Segmentation" notebook and update deprecations (#2241)
* link "Memory-Efficient Instance Segmentation" notebook and update deprecations
* fix(notebook): correct broken Colab badge URL in compact-mask-sam3

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-05-01 00:49:15 +02:00
dependabot[bot] 6ec8fa9a23 ⬆️ Bump notebook from 7.4.4 to 7.5.6 in the uv group across 1 directory (#2238)
Bumps the uv group with 1 update in the / directory: [notebook](https://github.com/jupyter/notebook).


Updates `notebook` from 7.4.4 to 7.5.6
- [Release notes](https://github.com/jupyter/notebook/releases)
- [Changelog](https://github.com/jupyter/notebook/blob/@jupyter-notebook/tree@7.5.6/CHANGELOG.md)
- [Commits](https://github.com/jupyter/notebook/compare/@jupyter-notebook/tree@7.4.4...@jupyter-notebook/tree@7.5.6)

---
updated-dependencies:
- dependency-name: notebook
  dependency-version: 7.5.6
  dependency-type: direct:development
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-30 23:52:40 +02:00
Jirka Borovec 1f199de502 drop outdated release_process.md 2026-04-30 23:52:00 +02:00
Jirka Borovec d8a25481c4 chore(notebooks): migrate demo scripts to Jupyter notebooks (#2240)
- Removed `convert_to_ipynb.sh` script and standalone `.py` demo files.
- Added `docs/notebooks/compact-mask-sam3.ipynb` showcasing new features (`sv.CompactMask` and `sv.Detections.from_sam3`) introduced in version `0.28.0`.
2026-04-30 23:49:11 +02:00
87b1b86f39 releasing 0.28.0 (#2220)
* docs: add 0.28.0 changelog entries and release demo notebook
* feat: add script for converting Python scripts to Jupyter notebooks
* chore: reorganize imports in release-demo notebook and update lint config
* docs: fix broken link in changelog entry for ConfusionMatrix

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-30 17:11:50 +02:00
pre-commit-ci[bot] 1170a90ffc chore(pre_commit): ⬆ pre_commit autoupdate (#2235)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.11 → v0.15.12](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.11...v0.15.12)
- [github.com/pre-commit/mirrors-mypy: v1.20.1 → v1.20.2](https://github.com/pre-commit/mirrors-mypy/compare/v1.20.1...v1.20.2)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-04-28 09:03:07 +02:00
dependabot[bot] 2e0e8d9132 ⬆️ Update wheel requirement from <0.47,>=0.40 to >=0.40,<0.48 (#2234)
Updates the requirements on [wheel](https://github.com/pypa/wheel) to permit the latest version.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.40.0...0.47.0)

---
updated-dependencies:
- dependency-name: wheel
  dependency-version: 0.47.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-27 09:28:09 +02:00
Jirka BorovecandCopilot 15730b2b5d docs: update author references and improve metadata (#2233)
- Standardize author naming by removing aliases (e.g., "SkalskiP" → "Piotr Skalski").
- Refine JSON-LD schema with added fields, `speakable` specifications, and expanded FAQs.
- Update copyright year to 2026.
- Highlight project milestones (GitHub stars and PyPI downloads) for visibility.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-25 07:15:59 +02:00
2db1e3af34 docs: improve SEO and GEO docs publishing (#2232)
* docs: improve SEO and GEO docs publishing
* docs: refine language for model compatibility and package features
* fix: correct spelling "Underestand" → "Understand" in notebook title
* fix: derive JSON-LD SearchAction URL from config.site_url
* lint: reformat notebook JSON (indent 1→4, pretty-format-json)
* docs: refine description for `supervision.assets` video addition

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-24 23:39:22 +02:00
jirka 840226afce chore: update pre-commit hooks configuration
- Add `check-json` hook and re-add `check-yaml` hook.
- Configure `check-added-large-files` with a max size of 500 KB.
- Format `ruff-check` hook arguments for consistency.
2026-04-24 18:07:59 +02:00
dc03ceac31 fix(docs): expand llms.txt, add FAQ schema, author attribution to how… (#2231)
- Expand llms.txt from 12 to 36+ URLs with FAQ, benchmarking, and API sections
- FAQPage schema: 5 → 12 Q&As in theme/main.html
- TechArticle schema: add dynamic author/date from page meta
- Add authors + date_modified frontmatter to all 8 how-to pages
- Add description meta to 7 reference pages (detection/core, trackers, datasets/core, metrics/mean_average_precision, cookbooks, assets, changelog)
- FAQ sections to all 8 how-to pages (Q&A format for AI citation)
- Author bios at bottom of each how-to page (E-E-A-T signal)
- FAQPage + TechArticle schema for how_to, reference, and cookbook pages in theme/main.html
- llms.txt Key APIs: expand from bare list to descriptive prose paragraphs
- Changelog: add date_modified frontmatter

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-23 18:33:14 +02:00
dependabot[bot] f9ab57afde ⬆️ Bump nbconvert from 7.17.0 to 7.17.1 in the uv group across 1 directory (#2226)
Bumps the uv group with 1 update in the / directory: [nbconvert](https://github.com/jupyter/nbconvert).


Updates `nbconvert` from 7.17.0 to 7.17.1
- [Release notes](https://github.com/jupyter/nbconvert/releases)
- [Changelog](https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/nbconvert/compare/v7.17.0...v7.17.1)

---
updated-dependencies:
- dependency-name: nbconvert
  dependency-version: 7.17.1
  dependency-type: direct:development
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-22 20:33:54 +02:00
pre-commit-ci[bot] fb19852919 chore(pre_commit): ⬆ pre_commit autoupdate (#2225)
updates:
- [github.com/JoC0de/pre-commit-prettier: v3.8.2 → v3.8.3](https://github.com/JoC0de/pre-commit-prettier/compare/v3.8.2...v3.8.3)
- [github.com/astral-sh/ruff-pre-commit: v0.15.10 → v0.15.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.10...v0.15.11)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-04-22 20:29:35 +02:00
jirka 60f8d28535 releasing 0.28.0.rc2 2026-04-22 18:21:43 +02:00
153cde5854 feat(compact_mask): add resize() method and benchmark stage (#2227)
* feat: add resize() method and benchmark stage
* perf: optimise resize() — vectorised coords, L3 direct RLE
* refactor: split _rle_resize and extract _resize_crop
* test: expand resize() tests for scaling and edge cases
* refactor: switch resize helpers to F-order (column-major) RLE
* fix: merge True/True RLE junctions in _rle_join_cols
* perf: vectorize _rle_scale_col RLE re-encoding
* test: add density-dispatch and parallel-path resize tests
* refactor: harden resize() threading and RLE invariants
* fix: accurate resize timing and exact nearest-neighbour parity
* type: add explicit numpy typing to ndarray declarations

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-22 15:34:12 +02:00
de87030a21 refactor(rle): consolidate RLE primitives (#2230)
* consolidate RLE primitives
* remove wrapper fns, inline converters in CompactMask
* correct _delta_encode doctest example input
* add coverage for multi-byte base48, negative deltas, oversized RLE
* docs: fix RLE decoder example
* coerce mask_2d to bool before view(uint8) in _mask_to_rle_counts

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-04-22 12:32:14 +02:00
5a59dcdec6 refactor(masks): switch CompactMask RLE to F-order (#2228)
* refactor(masks): switch CompactMask RLE to F-order
* docs(masks): update _rle_area docstring example to F-order RLE
* test(masks): verify _rle_encode produces COCO-compatible F-order RLE

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-04-22 08:12:00 +02:00
jirka 87e8153876 chore: extend .gitignore for Claude-related scratchpad directories... 2026-04-21 18:03:43 +02:00
c4a3038c57 feat(docs): add GEO infrastructure for AI search visibility (#2224)
* feat: add GEO infrastructure for AI search visibility
* fix: guard GEO blocks with {% if page %} to fix 404 build error
* feat: GEO platform optimization — FAQPage, IndexNow, answer paragraphs
* fix: move Disallow:/0.*/ to User-agent:* in robots.txt
* fix: block all numeric versioned paths in robots.txt

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-04-21 11:40:44 +02:00
dependabot[bot] 6069c477b0 ⬆️ Bump astral-sh/setup-uv from 8.0.0 to 8.1.0 in the github-actions group (#2223)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 8.0.0 to 8.1.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/cec208311dfd045dd5311c1add060b2062131d57...08807647e7069bb48b6ef5acd8ec9567f424441b)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 8.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 10:28:20 +02:00
6beabe3fb4 fix(dataset): reject COCO annotations whose file_name escapes the images directory (#2218)
* test: add regression tests for COCO loader path containment
* fix: reject COCO annotations whose file_name escapes the images directory
* docs: document ValueError contract in load_coco_annotations
* test: cover COCO equality-guard branch (file_name → images dir)
* test: cover COCO is_dir-guard branch (file_name → subdirectory)
* fix: wrap Path.resolve() for untrusted file_name in try/except
* test: add positive test for valid nested file_name in COCO loader
* test: add missing docstrings to COCO path-containment tests
* test: add `from __future__ import annotations` to JSON and CSV tests
* fix: replace `os.path.join` with `Path` for consistent path handling in COCO loader

---------

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 Code <noreply@anthropic.com>
2026-04-18 00:58:44 +02:00
8df86e2599 fix(annotators): TraceAnnotator handles stationary tracker ids in smooth mode (#2217)
* test: add regression test for TraceAnnotator smooth on stationary tracker
* fix: TraceAnnotator handles stationary tracker ids in smooth mode
* test: strengthen moving-tracker smooth assertion
* fix: guard splprep against collinear input; use unique_xy in fallback
* test: add boundary and regression tests for smooth mode
* docs: document smooth fallback behavior in TraceAnnotator
* test: add shape preservation assertions in annotate tests

---------

Co-authored-by: Jirka Borovec <6035284+Borda@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>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-18 00:50:15 +02:00
06beb6ff2f fix(sinks): slice list and tuple custom_data values per row (#2216)
* test: add regression tests for list/tuple custom_data slicing
* fix: slice list and tuple custom_data values per row
* docs: document custom_data slicing contract in append() docstrings
* docs: add docstring to _slice_value in CSVSink and JSONSink
* docs: add docstring to parse_detection_data in CSVSink and JSONSink
* test: add test for detections.data with plain Python list values
* test: add _slice_value edge-case unit tests
* docs: add per-row slicing note to CSVSink and JSONSink class docstrings

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-04-18 00:24:36 +02:00
Jirka Borovec 5d165e04c2 docs: update image links in README for accurate asset references (#2222) 2026-04-17 21:47:02 +02:00
jirka a5c4ebad08 docs: add "Compact Mask" section to detection module in docs 2026-04-17 16:43:49 +02:00
jirka 9590b72f44 releasing 0.28.0.rc1 2026-04-17 11:40:31 +02:00
Jirka Borovec 77dd68ee27 refactor: deprecate ByteTrack class in favor of ByteTrackTracker (#2215)
- Mark `ByteTrack` as deprecated using `@deprecated_class`.
- Add deprecation details and alternatives in the class docstring.
- Update version annotations for deprecation (`deprecated_in="0.28.0"`, `remove_in="0.30.0"`).
2026-04-16 21:18:07 +02:00
Vincenzoandjirka c61fbf6355 refactor: convert LineZone docstring example to doctest (#2207)
* refactor: convert LineZone docstring example to doctest
* refactor: added pycon and frame generator to doctest

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
2026-04-15 23:00:30 +02:00
62efdee025 feat: Detections.from_inference supports compressed RLE masks (#2178)
* 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>
2026-04-15 22:35:47 +02:00
jirkaandClaude Code f28874c0c2 fix: move keypoint shims to src/ and use warn_deprecated
- Move supervision/keypoint/ → src/supervision/keypoint/ so shims are
  included in built wheels (project uses src layout)
- Replace raw DeprecationWarning with warn_deprecated (SupervisionWarnings)
  in all three shim files for consistent warning behaviour
- Fix wrong import path (supervision.utils.deprecation → .internal)
  and remove unsupported stacklevel arg from warn_deprecated call

[resolve #7] Review comment by @copilot (PR #2214):
"This warning uses the standard DeprecationWarning..."
[resolve #8] Review comment by @copilot (PR #2214):
"These deprecation shim modules are added under the top-level supervision/..."

---
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-15 20:59:46 +02:00
jirkaandClaude Code 982c801db7 fix: restore functools.wraps on conversion.py wrapper functions
Decorated functions now preserve __name__, __doc__, and __wrapped__
metadata, fixing introspection and documentation generation for all
annotators using ensure_cv2/pil_image_for_* decorators.

[resolve #9] Review comment by @copilot (PR #2214):
"The decorator wrappers in this file no longer use functools.wraps..."

---
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-15 20:59:46 +02:00
jirkaandClaude Code 0ce6846880 fix: use warn_deprecated for LMM.from_value deprecation in vlm.py
Replace FutureWarning with warn_deprecated so the LMM deprecation
respects the SUPERVISON_DEPRECATION_WARNING env var filter, consistent
with other deprecations across the library.

[resolve #4] Review comment by @copilot (PR #2214):
"Same as Detections.from_lmm: this uses the standard FutureWarning..."

---
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-15 20:59:46 +02:00
jirkaandClaude Code f5baeef7ae fix: align from_lmm deprecation version and use warn_deprecated
- Replace FutureWarning with warn_deprecated (SupervisionWarnings) in
  Detections.from_lmm to respect SUPERVISON_DEPRECATION_WARNING env var
- Align removal version from 0.30.0 to 0.31.0 for consistency with
  all other deprecations introduced in this PR

[resolve #3] Review comment by @copilot (PR #2214):
"Deprecation warning says from_lmm will be removed in supervision-0.30.0..."
[resolve #4] Review comment by @copilot (PR #2214):
"Emitting deprecation warnings with the standard FutureWarning here byp..."

---
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-15 20:59:46 +02:00
Jirka BorovecandCopilot 09f3ea13e7 Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-15 20:59:46 +02:00
jirka b7ad4c1df0 add pydeprecate dependency and update lockfile 2026-04-15 20:59:46 +02:00
jirka ed7606f886 fix: resolve typing regressions in image utilities 2026-04-15 20:59:46 +02:00
jirka a0f5c9a41a Refactor deprecation handling for LMM and from_lmm, replacing @deprecated with warnings.warn
(cherry picked from commit 27e5fa3e9a)
2026-04-15 20:59:46 +02:00
jirka 23fca01cfc adjust deprecation version for from_lmm
(cherry picked from commit fd4845a5cf)
2026-04-15 20:59:46 +02:00
jirka 35cb41bd21 Revive create_tiles implementation and all related functions
(cherry picked from commit 650ca0ae2f)
2026-04-15 20:59:46 +02:00
jirka 6dce8ba38d Update deprecation annotations to extend remove_in versions across multiple modules
(cherry picked from commit bc521bc2d0)
2026-04-15 20:59:46 +02:00
jirka 10f4b86b70 Refactor imports for consistency and update deprecated utility usage across modules
(cherry picked from commit 7f3dcaedbd)
2026-04-15 20:59:46 +02:00
jirka 6fa7395b99 Update deprecation annotations and refactor deprecated utility usage
(cherry picked from commit 0ba57b2f57)
(cherry picked from commit ae6aa369ae)
2026-04-15 20:59:46 +02:00
jirka eddcf3d09f Add deprecation warnings for keypoint validation utilities in supervision
(cherry picked from commit e36fbe061d)
2026-04-15 20:59:46 +02:00
jirka e275a239ad Add deprecation warning for create_tiles in image utilities
(cherry picked from commit 224c7569a1)
2026-04-15 20:59:46 +02:00
jirka cd36ae05e9 Add deprecation warning for ensure_cv2_image_for_processing in conversion utilities
(cherry picked from commit c9761515f3)
2026-04-15 20:59:46 +02:00
jirka 3997182ee7 Add deprecation warnings for annotation utilities and update dependencies
(cherry picked from commit 219161f1f9)
2026-04-15 20:59:46 +02:00
jirka 845e47f472 Introduce deprecation warnings for supervision.keypoint module, redirecting to supervision.key_points.
(cherry picked from commit 99e772c466)
2026-04-15 20:59:46 +02:00
dependabot[bot] 565cd919e9 ⬆️ Bump pytest from 8.4.1 to 8.4.2 in the uv group across 1 directory (#2213)
Bumps the uv group with 1 update in the / directory: [pytest](https://github.com/pytest-dev/pytest).


Updates `pytest` from 8.4.1 to 8.4.2
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.4.1...8.4.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 8.4.2
  dependency-type: direct:development
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 11:14:43 +02:00
e514142b3d fix: slice numpy array values in custom_data per row in CSVSink (#2199)
* fix: slice numpy array values in custom_data per row in CSVSink and JSONSink
* fix: restore non-ndarray custom_data passthrough in CSVSink
* test: add JSONSink test for numpy array custom_data slicing
* test: add mixed-type custom_data test (ndarray + scalar together)
* refactor: extract _slice_value helper; drop redundant ndarray test

---------

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 Code <noreply@anthropic.com>
2026-04-14 00:51:52 +02:00
pre-commit-ci[bot] 72fc49f124 chore(pre_commit): ⬆ pre_commit autoupdate (#2212)
updates:
- [github.com/JoC0de/pre-commit-prettier: v3.8.1 → v3.8.2](https://github.com/JoC0de/pre-commit-prettier/compare/v3.8.1...v3.8.2)
- [github.com/tox-dev/pyproject-fmt: v2.21.0 → v2.21.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.21.0...v2.21.1)
- [github.com/astral-sh/ruff-pre-commit: v0.15.9 → v0.15.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.9...v0.15.10)
- [github.com/pre-commit/mirrors-mypy: v1.20.0 → v1.20.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.20.0...v1.20.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-04-13 20:06:21 +02:00
51dd062407 fix: VideoInfo.fps returns float instead of truncated int (#2210)
* VideoInfo.fps returns float instead of int

Truncating the raw CAP_PROP_FPS value with int() causes timing drift for
non-integer frame rates (23.976, 29.97, 59.94). Over a long video this
accumulates into noticeable sync errors — e.g. 23 vs 23.976 drifts ~1s
per minute of footage.

Changes:
- VideoInfo.fps type annotation: int -> float
- from_video_path: int(video.get(CAP_PROP_FPS)) -> float(...)
- ByteTrack.frame_rate type annotation: int -> float (already converts
  to int internally via max_time_lost = int(frame_rate / 30.0 * buffer))
- Tests: assert fps is float, add float_fps_video_path fixture at 23.976

* fix: update examples to cast float fps to int where required
* fix: wrap long docstring line in FPSBasedTimer (ruff E501)
* test: remove unused float_fps_video_path fixture

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-13 20:05:19 +02:00
e19f3120ca fix: is_empty() returns False for empty tracker arrays (#2209)
* fix: is_empty() returns False for empty tracker arrays (closes #2195)
* fix: use tuple in pytest.mark.parametrize (ruff PT006)
* test: add mask regression case and improve test_is_empty quality
* docs: update is_empty() docstring with pycon examples for clarity and consistency

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-04-13 17:10:59 +02:00
dependabot[bot] 6b5eed2ba1 ⬆️ Bump the github-actions group with 2 updates (#2211)
Bumps the github-actions group with 2 updates: [actions/github-script](https://github.com/actions/github-script) and [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish).


Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/ed597411d8f924073f98dfc5c65a23a2325f34cd...3a2844b7e9c422d3c10d287c895573f7108da1b3)

Updates `pypa/gh-action-pypi-publish` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e...cef221092ed1bacb1cc03d23a2d87d1d172e277b)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: 9.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 11:12:33 +02:00
dependabot[bot] 5a29ad9525 ⬆️ Bump cryptography from 46.0.6 to 46.0.7 in the uv group across 1 directory (#2208)
Bumps the uv group with 1 update in the / directory: [cryptography](https://github.com/pyca/cryptography).


Updates `cryptography` from 46.0.6 to 46.0.7
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.6...46.0.7)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.7
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 11:12:17 +02:00
9b7099d3fc feat: add CompactMask for memory-efficient crop-RLE mask storage (#2159)
Dense (N, H, W) bool masks cause OOM for aerial imagery (1000 objects x
4K image ~ 8.3 GB). CompactMask encodes each mask as a run-length
sequence of its bounding-box crop, reducing typical usage to ~2 MB.

* fix: correct bounding box coordinates in CompactMask doctests
* feat: implement memory-efficient IoU and NMS with CompactMask integration
* test: add extensive tests for CompactMask IoU, NMS, and InferenceSlicer integration
* feat(examples): add CompactMask demo and benchmark
* feat(examples): expand CompactMask benchmark with new stages and metrics
* feat(tests): add detailed CompactMask tests for NMM, centroids, holes, and segments
* feat(compact_mask): add repack(), fix merge perf, and add parity tests
* fix(masks): handle empty crops by defaulting centroid to (0, 0)
* feat(compact_mask): add `bbox_xyxy` property and improve type annotations
* feat(compact_mask): enhance `with_offset` for clipping and add tests
* docs(compact_mask): unwrap prose and add per-operation speedup analysis
* perf(compact_mask): fast path in with_offset avoids decode/re-encode
* fix(benchmark): count NMS mismatches and explain exact-vs-resize difference
* test(compact_mask): add 121 parametrised random-scenario parity tests
* refactor: rename single-char variables to descriptive names
* fix(nms): remove resize-to-640 approximation from mask_non_max_suppression
* docs(compact_mask): update README with fresh benchmark results
* refactor(benchmark): improve summary table logic, add CSV export
* docs(compact_mask): update README with revised benchmark speedups and cleanup

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-13 11:10:12 +02:00
pre-commit-ci[bot] ee8a61a3e7 chore(pre_commit): ⬆ pre_commit autoupdate (#2201)
updates:
- [github.com/tox-dev/pyproject-fmt: v2.20.0 → v2.21.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.20.0...v2.21.0)
- [github.com/astral-sh/ruff-pre-commit: v0.15.8 → v0.15.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.8...v0.15.9)
- [github.com/pre-commit/mirrors-mypy: v1.19.1 → v1.20.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.19.1...v1.20.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-04-08 14:27:22 +02:00
48035c14e2 fixed precision converting annotations with "force_mask=True" (#1746)
* changing polygon format conversion
* reformating polygon type conversion
* handling mask dimensions
* fix: resolve unresolved PR #1746 review comments
* refactor(tests): restructure YOLO polygon mask precision tests with fixtures

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-03-31 11:51:30 +02:00
ddb3515b56 Fix extreme memory usage when loading OBB datasets (#2187)
* fix: prevent mask generation for OBB annotations to avoid extreme memory usage
* docs: clarify force_masks is ignored when is_obb=True
* test: pin force_masks=True is ignored for OBB and segmentation mask regression

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-31 10:24:22 +02:00
85ba8be9dd Fix KeyPoints 2D boolean mask indexing (uniform-count selection) (#2188)
* Fix KeyPoints 2D boolean mask filtering (keypoints[keypoints.confidence > 0.5])
* Fix ruff E501 and mypy type annotation in KeyPoints 2D mask branch
* Add match= to pytest.raises to fix ruff PT011
* Add shape validation for 2D boolean mask in KeyPoints.__getitem__
* Add edge-case tests for KeyPoints 2D boolean mask filtering
* refactor: extract 2D bool mask handling into _get_by_2d_bool_mask private method
* Document 2D mask uniform-count requirement; add canonical single-object test

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-31 01:48:57 +02:00
129118817a make pixel and kernel size dynamic (#709)
* make pixel and kernel size dynamic
* fix: zero-area guard and is-not-None check in Blur/PixelateAnnotator

- Skip loop iteration when clip_boxes produces x2<=x1 or y2<=y1 (zero-area ROI) to prevent cv2.error crash in both annotators
- Replace falsy `or` pattern with explicit `is not None` so kernel_size=0 / pixel_size=0 are not silently treated as dynamic
- Replace hardcoded `cv2.mean(roi)[:3]` with ndim-aware fill: scalar for grayscale, channel-matched tuple for colour images; avoids shape mismatch broadcast error on single-channel frames
- test_annotate_bbox_smaller_than_pixel_size_does_not_raise: guards against the OpenCV resize crash from issue #703 when bbox < pixel_size
- test_annotate_grayscale_image_does_not_raise: normal pixelation path on 2-D grayscale frame
- test_annotate_grayscale_image_small_roi_does_not_raise: avg-fill fallback on 2-D grayscale frame
- Add ValueError guard in BlurAnnotator.__init__ and PixelateAnnotator.__init__ for explicit sizes < 1; previously passed straight to cv2 causing ZeroDivisionError or OpenCV assertion failures
- Add parametrized tests for invalid sizes (0, -1, -10) and zero-area bbox skipping for both annotators

---------

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 Code <noreply@anthropic.com>
2026-03-30 22:17:53 +02:00
9ed1f07ca0 Add unittests for supervision.key_points.core (#2190)
* adding unit testcases for keypoints from_inference(), from_mediapipe() and from_yolo_nas() functions
* modifying test_from_mediapipe_input()
* Apply suggestions from code review

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-30 20:36:31 +02:00
38be1be4b2 Fix lossy COCO round-trip: preserve area and iscrowd in as_coco (#2185)
* fix: preserve area and iscrowd from detection data in COCO export
* fix: use np.asarray().item() to satisfy mypy in iscrowd/area extraction
* test: shorten test name to fix ruff E501 line-length violation
* test: verify data["area"] overrides bbox area when mask is present
* test: stricter iscrowd type check (bool subclass fix)
* test: stricter iscrowd type check in preserves_iscrowd_from_data
* test: stricter iscrowd type check in iscrowd_is_int_when_mask_provided
* fix: prefer data["iscrowd"] over geometry when mask is present

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-03-30 20:17:42 +02:00
pre-commit-ci[bot] d33715464b chore(pre_commit): ⬆ pre_commit autoupdate (#2192)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.7 → v0.15.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.7...v0.15.8)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-30 19:50:35 +02:00
e6fab4b7fa Add out-of-bounds detection warning to InferenceSlicer (#2186)
When a user's callback accidentally runs inference on the full image instead
of the provided slice, detections get incorrect offsets applied, causing a
repeating grid pattern. Add a validation check in _run_callback that emits a
SupervisionWarnings warning when any detection coordinate exceeds the slice
dimensions or is negative. An instance flag prevents repeated warnings across
many slices.

- Wrap _out_of_slice_bounds_warned check-and-set in threading.Lock to prevent duplicate warnings under ThreadPoolExecutor with thread_workers > 1
- Change stacklevel=2 to stacklevel=1 — under executor.submit the stacklevel=2 frame points into concurrent.futures internals, not user code
- Assert exactly 1 warning fires with thread_workers=4 (validates Lock fix)
- Assert no warning for detection touching but not exceeding slice boundary (pins > vs >= semantics)
- Assert second slicer call does not re-warn (documents once-per-instance semantic)
- Extract warning message into `msg` variable to satisfy E501 line-length limit


---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-30 19:26:33 +02:00
8b60ee1a0e feat: add support for hexadecimal RGBA color format (#2004)
This commit adds support for 4-digit and 8-digit hexadecimal color codes
with alpha channel (e.g., #FF00FF80 for 50% transparent magenta).

Changes:
- Extended Color dataclass with optional alpha field (default 255)
- Updated _validate_color_hex to accept lengths 3, 4, 6, 8
- Updated from_hex to parse 4-digit (#RGBA) and 8-digit (#RRGGBBAA) hex codes
- Modified as_hex to return #RRGGBBAA when alpha != 255
- Added as_rgba() and as_bgra() methods
- Added from_rgba_tuple() and from_bgra_tuple() class methods
- Updated __eq__ and __hash__ to include alpha channel
- Added comprehensive unit tests for all RGBA functionality
- Updated docstrings with examples of new alpha channel support

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-30 15:57:18 +02:00
dependabot[bot] a6ee3e98c7 ⬆️ Bump the github-actions group with 2 updates (#2184)
Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [codecov/codecov-action](https://github.com/codecov/codecov-action).


Updates `astral-sh/setup-uv` from 7.6.0 to 8.0.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/37802adc94f370d6bfd71619e3f0bf239e1f3b78...cec208311dfd045dd5311c1add060b2062131d57)

Updates `codecov/codecov-action` from 5 to 6
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: codecov/codecov-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 13:05:55 +02:00
dependabot[bot] 8b2f961ba8 ⬆️ Bump cryptography from 46.0.5 to 46.0.6 in the uv group across 1 directory (#2183)
Bumps the uv group with 1 update in the / directory: [cryptography](https://github.com/pyca/cryptography).


Updates `cryptography` from 46.0.5 to 46.0.6
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.5...46.0.6)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.6
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-29 21:13:10 +02:00
dependabot[bot] c8a8540698 ⬆️ Bump requests from 2.32.4 to 2.32.5 in the uv group across 1 directory (#2182)
Bumps the uv group with 1 update in the / directory: [requests](https://github.com/psf/requests).


Updates `requests` from 2.32.4 to 2.32.5
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.4...v2.32.5)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.32.5
  dependency-type: direct:production
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-29 21:09:02 +02:00
pre-commit-ci[bot] d6a24d0dd9 chore(pre_commit): ⬆ pre_commit autoupdate (#2180)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/tox-dev/pyproject-fmt: v2.18.1 → v2.20.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.18.1...v2.20.0)
- [github.com/astral-sh/ruff-pre-commit: v0.15.6 → v0.15.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.6...v0.15.7)

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-24 21:07:32 +01:00
dependabot[bot] d94db74493 ⬆️ Bump astral-sh/setup-uv from 7.5.0 to 7.6.0 in the github-actions group (#2179)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 7.5.0 to 7.6.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/e06108dd0aef18192324c70427afc47652e63a82...37802adc94f370d6bfd71619e3f0bf239e1f3b78)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-24 21:07:21 +01:00
pre-commit-ci[bot] fdaadacbe3 chore(pre_commit): ⬆ pre_commit autoupdate (#2177)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/tox-dev/pyproject-fmt: v2.16.2 → v2.18.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.16.2...v2.18.1)
- [github.com/astral-sh/ruff-pre-commit: v0.15.5 → v0.15.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.5...v0.15.6)

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-19 17:21:44 +01:00
dependabot[bot] 819fcde7e4 ⬆️ bump astral-sh/setup-uv in the github-actions group (#2176)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 7.3.1 to 7.5.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/5a095e7a2014a4212f075830d4f7277575a9d098...e06108dd0aef18192324c70427afc47652e63a82)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-19 17:09:07 +01:00
ad7a9988e7 docs: replace YOLO with RF-DETR in README (#2175)
Swap Ultralytics YOLO references for RFDETRSmall (rfdetr package) and
rfdetr-small (Roboflow Inference) to showcase RF-DETR as the primary
model in the quickstart and connector examples.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-14 18:50:34 +01:00
cee411689d refactor: convert docstring examples to doctest format (#2173)
* migrate docstrings (doctest - pycon)
* Refine doctests in `mean_average_recall.py` and `f1_score.py` for consistent formatting
* Expand doctests across metrics modules for detailed result output
* Apply suggestions from code review

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-13 10:42:16 +01:00
Omkar Kabde 600099e8ab Refactor docstring section headers (#2171)
* use `Args` in docstrings
* remove type hints in docstrings
2026-03-13 10:09:48 +01:00
7912e7e5bb Fix typing - last mypy ignored modules (#2172)
* fix mypy errors
* remove modules from pyproject
* Apply suggestions from code review

---------

Co-authored-by: Jirka Borovec <6035284+Borda@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-03-13 10:06:59 +01:00
dependabot[bot] 2dee466abc chore(deps): bump tornado in the uv group across 1 directory (#2174)
Bumps the uv group with 1 update in the / directory: [tornado](https://github.com/tornadoweb/tornado).


Updates `tornado` from 6.5.1 to 6.5.5
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.5.1...v6.5.5)

---
updated-dependencies:
- dependency-name: tornado
  dependency-version: 6.5.5
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-13 09:58:52 +01:00
c010656161 fix: prevent single object from appearing in multiple polygon zones (#1991)
* fix: prevent single object from appearing in multiple polygon zones

when checking if a detection is inside a polygon zone, the previous implementation
would clip the bounding box to fit within each ROI's dimensions before calculating
anchor points. This caused the same detection to produce different anchor points
for different ROIs, allowing it to be counted as present in multiple zones.

* Add regression test for PolygonZone trigger issue #1987 and remove unused `frame_resolution_wh` attribute
* refactor(polygon_zone): vectorize trigger() and strengthen tests

Replace the O(n×m) Python double-loop in PolygonZone.trigger() with
vectorized NumPy. Semantics are identical: compute a (num_anchors,
num_detections) in_bounds mask, use np.clip solely for safe fancy-index
access, then AND with the polygon mask and reduce with np.all(axis=0).
Also removes the now-unused `from dataclasses import replace` import and
a latent np.all(axis=1) call on a 1D array.

Test improvements:
- Group into TestPolygonZoneInit / TestPolygonZoneTrigger classes
- Replace the trivially-passing regression (sum=0 on both old and new
  code) with adjacent zones + straddling detection that gives sum=2 on
  the old clip_boxes implementation and sum=1 on the fix
- Rename tests to describe behaviour, not issue numbers
- Add test_out_of_bounds_anchor_excluded and
  test_anchor_on_polygon_boundary_included edge cases

* test(polygon_zone): verify current_count updates with expected results during trigger

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 21:19:09 +01:00
ca9bff184c refactor docstrings in src/supervision/detection/utils (#2165)
* refactor docstrings in `src/supervision/detection/utils`
* Fix indentation in return docstring in `vlms.py` for consistency
* Apply suggestions from code review

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-03-10 18:56:04 +01:00
e4cedb6861 refactor docstrings in src/supervision/detection/tools (#2164)
* refactor docstrings in `src/supervision/detection/tools`
* Refine type annotations and docstrings in `transformers.py` to include `TensorLike` protocol and enhance segmentation handling
* Enhance type safety in `transformers.py` by introducing `_is_tensor_like` with `TypeGuard` and refining segmentation result handling
* Refine `CSVSink` type annotations by introducing `WriterProtocol` for improved type safety
* Remove `_is_tensor_like`, `TensorLike` protocol, and `TypeGuard` usage from `transformers.py`, streamline segmentation handling, and fix typos in `CSVSink` and `JSONSink` docstrings

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-10 18:51:27 +01:00
664bf3cf79 refactor docstrings in scr/supervision/detection (#2162)
* refactor docstrings in `scr/supervision/detection`
* Enhance docstrings across multiple modules: clarify attributes/args, improve formatting, and update logic for handling sentinel values in metrics calculation.
* Ensure consistent handling of `class_id` as integer across YOLO and Pascal VOC formats, fix NoneType handling in line zone logic, and add test coverage for multiclass annotator with None `class_id`.
* Enforce `class_id` as integer in YOLO export, update line zone class count docstrings, and add test for non-integer `class_id`.
* Apply suggestions from code review

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-10 18:40:05 +01:00
a673640aad refactor docstrings in draw, classification, and key_points (#2161)
* refactor docstrings in draw, classification, and key_points
* Refactor type annotations, logging, and empty output handling across key modules
* Refactor type annotations in `core.py` to include conditional `TYPE_CHECKING` for `torch` imports
* Apply suggestions from code review

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-10 18:07:39 +01:00
jirka 7d8b2b3fc5 Update .gitignore to exclude tasks/ and *.local.md files 2026-03-10 17:58:40 +01:00
93f5622d15 refactor(metrics): update MeanAveragePrecisionResult to use float32 precision (#2169)
* refactor(metrics): update MeanAveragePrecisionResult to use float32 precision

This change reduces memory usage and improves computation speed while maintaining acceptable precision for most computer vision tasks.

- Changed mAP_scores, ap_per_class, and iou_thresholds from float64 to float32
- Updated EPS constant to use float32 precision
- Modified COCOEvaluator parameters and computations to use float32
- Added type annotations for variables in filter_segments_by_distance function
- Changed precision and recall calculations to use float32
- Updated average precision computation to handle float32 values
- Modified summarize_predictions to return float32 array

* update type annotation for `keep_labels` to use `npt.NDArray[np.bool_]`
* update EPS constant and mAP calculations for precision consistency
* Apply suggestions from code review

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-10 16:53:32 +01:00
Omkar Kabde a78bf58c6d refactor docstrings in src/supervision/annotators (#2163) 2026-03-10 10:31:18 +01:00
pre-commit-ci[bot]andJirka Borovec e5fef4501b chore(pre_commit): ⬆ pre_commit autoupdate (#2167)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.4 → v0.15.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.4...v0.15.5)
- [github.com/codespell-project/codespell: v2.4.1 → v2.4.2](https://github.com/codespell-project/codespell/compare/v2.4.1...v2.4.2)

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>
2026-03-10 10:20:55 +01:00
Deependu 0c69d0d333 chore: use python3 as default pre-commit language version (#2166) 2026-03-10 10:20:38 +01:00
CopilotandBorda 6d92214718 fix: suppress 429 false-positives in link-check CI (#2168)
* pass GITHUB_TOKEN to lychee and tune rate-limit settings
* rely on GITHUB_TOKEN + throttling
* increase concurrency to 8, restore 429 accept with explanatory comment

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
2026-03-10 10:13:15 +01:00
pre-commit-ci[bot] eef16454e2 chore(pre_commit): ⬆ pre_commit autoupdate (#2158)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.2 → v0.15.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.2...v0.15.4)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-03 09:43:13 +01:00
dependabot[bot] 87c63fe7a1 ⬆️ bump the github-actions group with 3 updates (#2157)
Bumps the github-actions group with 3 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `astral-sh/setup-uv` from 7.3.0 to 7.3.1
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/eac588ad8def6316056a12d4907a9d4d84ff7a3b...5a095e7a2014a4212f075830d4f7277575a9d098)

Updates `actions/upload-artifact` from 6 to 7
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

Updates `actions/download-artifact` from 7 to 8
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v7...v8)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 11:57:44 +01:00
Hee Jae KimandJirka Borovec 9eba61de10 fix: populate class_name in DetectionDataset annotations (#2156)
DetectionDataset.__init__ now maps class_id to class names using
CLASS_NAME_DATA_FIELD so that LabelAnnotator displays human-readable
labels instead of raw integer IDs.

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-02-25 19:37:59 +01:00
pre-commit-ci[bot] b385508606 chore(pre_commit): ⬆ pre_commit autoupdate (#2155)
updates:
- [github.com/tox-dev/pyproject-fmt: v2.16.0 → v2.16.2](https://github.com/tox-dev/pyproject-fmt/compare/v2.16.0...v2.16.2)
- [github.com/astral-sh/ruff-pre-commit: v0.15.1 → v0.15.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.1...v0.15.2)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-25 19:14:04 +01:00
jirka d70bc4f58b Add CLAUDE.md with project instructions and import reference to AGENTS.md 2026-02-22 19:36:36 +01:00
c2dedba3db feat: replace print statements with structured logging (#2154)
* feat: implement logging system to replace print statements
* refactor: rename get_logger to _get_logger to mark as internal
* test: add logger tests, fix corrupted-file warning test, add docstring example

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-20 13:14:53 +01:00
6ca9555efd Fix detections_to_coco_annotations function for empty polygons. (#1086)
* Fix `detections_to_coco_annotations` function for empty polygons.
* Add `segmentation` empty field for bboxes coco format
* update coco.py
Always include box, area, and segmentation in the result COCO JSON.
* `as_coco()` : Add COCO format disjoint masks support
* Fix `force_masks` parameter on `from_coco()` function
Allows reconstruction of disjointed masks
* Ensures the mask is binary
* Refactor `coco_annotations_to_masks` to handle disjoint polygon segmentation and missing segmentation gracefully. Add corresponding unit tests.
* Refactor `coco_annotations_to_masks` for improved type annotations and cleaner formatting
* Add warnings for handling empty polygons during COCO segmentation and related unit tests

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-20 12:08:26 +01:00
ae2c356321 Fix mask_annotate for int dtypes (#1445)
* Fix mask_annotate for int dtypes
* Add depreciation warning
* Add dtype=bool to test masks
* Remove ValueError (testing)
* Ensure boolean masks are consistently used in `Detections` and update validations, tests, and warnings for stricter type handling.
* Apply suggestions from code review

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-20 10:43:56 +01:00
f8f62891de Added HEX↔RGBA color utilities and tests (Hacktoberfest 2025) (#1988)
* Added color utility functions: hex_to_rgba, rgba_to_hex, is_valid_hex with tests
* Parametrize hex and RGBA utility tests in `test_utils.py` for improved clarity and coverage
* Enhance hex and RGBA utilities: improve test coverage, validations, and docstrings; refactor shared logic.
* Refactor color input handling with `_normalize_color_input` utility; add hex string support across annotators and enhance test coverage

---------

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>
2026-02-20 09:58:15 +01:00
162a46cae1 Fix inconsistent force_masks across dataset formats (#265)
* make force_masks consistent with yolo and voc
* Refactor mask detection logic across dataset formats to improve consistency and clarity. Rename helper functions for better readability. Add parametrized test cases with descriptive IDs.
* Refactor PASCAL VOC and COCO mask handling to improve consistency, add tests for mixed annotations and mask inference logic.
* Apply suggestions from code review

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-20 08:15:16 +01:00
Raif Olsonandjirka b5ccf6882d Fix external track ids (#1364)
* fix exteranl track ids getting assigned too early
* Fixed docstring to correct minimum_matching_threshold explaination
* Change overlap value for duplicate tracks to be 0.05
* Add test to ensure ByteTracker handles short-lived tracks without consuming external IDs

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
2026-02-20 00:58:55 +01:00
Jirka BorovecandCopilot 6576a846d9 Update lychee configuration to accept HTTP status code 401 (#2153)
* Update lychee configuration to accept HTTP status code 401
* remove status code 401 and add note for URL with inconsistent responses

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-20 00:05:53 +01:00
Erikandpre-commit-ci[bot] 49a0f372d7 Add support for SAM3 PVS output (#2152)
* Add support for SAM3 PVS output
* Updated docs (function description)

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-19 17:09:31 +01:00
pre-commit-ci[bot] 91c5f3f106 chore(pre_commit): ⬆ pre_commit autoupdate (#2151)
updates:
- [github.com/tox-dev/pyproject-fmt: v2.14.2 → v2.16.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.14.2...v2.16.0)
- [github.com/astral-sh/ruff-pre-commit: v0.15.0 → v0.15.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.0...v0.15.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-19 17:09:01 +01:00
0b4cc5ff5b Refine Copilot and CONTRIBUTING guidelines for clarity and conciseness (#2150)
* Refactor Copilot and CONTRIBUTING guidelines for clarity and conciseness
* Streamline and condense PR review guidelines in CONTRIBUTING.md for improved clarity and usability.
* Apply suggestions from code review
* 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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 23:14:02 +09:00
0ed48f0227 Add ImageAssets for download (#932)
* Add ImageAssets for download
* Update directory for consistency with video assets directory and add soccer image
* Fix unaligned table
* Add support for `ImageAssets` and extend `download_assets` functionality to handle both image and video assets.
* Refactor `Assets` enum initialization and improve `download_assets` logic with enhanced file checks and re-download handling. Add new tests for invalid asset cases and update existing test assertions.
* Simplify `download_assets` type handling and refactor `Assets` enum with additional attributes for filename and md5_hash.

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-12 19:22:15 +09:00
acbaf4ff25 Correct confusion matrix calculation-function evaluate_detection_batch (#1853)
* Correct confusion matrix calculation-function evaluate_detection_batch
* Correct confusion matrix computation
* Add 3 more tests for empty Detections-GTs
* Minor changes in too-long lines corrected
* Replace deprecated mock_detections with _create_detections
* Fix indentation in test assertions and add missing `self` parameter in `test_confusion_matrix`.
* Update metric computations to improve numerical stability and replace deprecated NumPy functions
* Add IoU+class matching tests and synthetic dataset fixtures for detection metrics
* Use `Optional` for type hinting `classes` parameter in `_yolo_dataset_factory`. Import `Optional` from `typing`.
* Refactor detection metric tests to simplify confusion matrix assertions and enhance IoU+class matching validation.
* Apply suggestions from code review
* 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 Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-12 18:54:00 +09:00
124be19928 Fix MeanAverageRecall compute mAR@K using top-K detections per image [COCO-compliant] (#2136)
* Supersedes #1967
* fix: COCO-compliant mAR calculation
* Add complex test of mAP
* fix(metrics): cast optional detections fields in mAR metric for mypy
* Add `create_yolo_dataset` utility and refactor tests with fixtures for reusable scenarios
* Refine docstrings for clarity and consistency, adding inline formatting and fixing typos in test helpers and metrics.

---------

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-02-12 17:59:11 +09:00
839d117f6c Added support for creating Detections instances from SAM3 (#2103)
* Added support for creating Detections instances from SAM3 output - both from `inference` and from RF hosted server (dict)
* added tests, addressed pr comments
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-12 16:12:42 +09:00
Jirka Borovec 9955f0137a Refine CI workflows to use uv sync and simplify command invocations (#2149) 2026-02-12 15:50:49 +09:00
dependabot[bot] 9fcabc8b9a chore(deps): bump pillow in the uv group across 1 directory (#2148)
Bumps the uv group with 1 update in the / directory: [pillow](https://github.com/python-pillow/Pillow).


Updates `pillow` from 10.4.0 to 11.3.0
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.4.0...11.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 11.3.0
  dependency-type: direct:production
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-12 15:43:08 +09:00
dependabot[bot] e5ff27b0aa chore(deps): bump cryptography in the uv group across 1 directory (#2147)
Bumps the uv group with 1 update in the / directory: [cryptography](https://github.com/pyca/cryptography).


Updates `cryptography` from 45.0.5 to 46.0.5
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/45.0.5...46.0.5)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.5
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-12 15:36:06 +09:00
a00ea2087f Add AGENTS.md with detailed guidelines for Copilot task execution (#2135)
* Add `AGENTS.md` with detailed guidelines for Copilot task execution
* Simplify `AGENTS.md` with concise AI agent guidelines and enhanced structure
* 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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 22:58:57 +09:00
Jirka Borovec 2dd1bc5df6 typing(dataset): resolve type annotations and sanitize docstrings (#2146)
* resolve type annotations and sanitize docstrings
* improve error messages in `_extract_class_names` for better debugging clarity
2026-02-10 22:23:32 +09:00
83dfc87ef5 Refactor/typing tracker (#2131)
* refactor(tracker): improve typing and docstrings
* refactor(tracker): improve typing for track objects
* refactor(tracker): improve typing in matching and filters
* Apply suggestions from review
* Refactor: enhance type annotations, assertions, and docstrings across `byte_tracker` for clarity and type safety.
* Refactor: replace "Parameters" with "Args" in docstrings for consistency with style guide

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-10 21:57:12 +09:00
Christoph Deil 00c96c03ee Fix Albumentations docs typo
(cherry picked from commit e37b32f5ca)
2026-02-10 21:48:50 +09:00
6f1eb63825 enable Prettier hook to pre-commit for YAML & TOML (#2142)
* add Prettier hook for consistent formatting YAML, and TOML files
* fix(pre_commit): 🎨 auto format pre-commit hooks

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-10 21:39:52 +09:00
dependabot[bot] e4d0be777d ⬆️ Bump astral-sh/setup-uv in the github-actions group (#2141)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 7.2.1 to 7.3.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/803947b9bd8e9f986429fa0c5a41c367cd732b41...eac588ad8def6316056a12d4907a9d4d84ff7a3b)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 21:28:06 +09:00
Kader Miyanyedi 54328e37a0 fix(typing): update type hints for utility functions in detection module (#2140) 2026-02-10 21:27:23 +09:00
dependabot[bot] 3dd9e56da4 chore(deps-dev): bump nbconvert in the uv group across 1 directory (#2144)
Bumps the uv group with 1 update in the / directory: [nbconvert](https://github.com/jupyter/nbconvert).


Updates `nbconvert` from 7.16.6 to 7.17.0
- [Release notes](https://github.com/jupyter/nbconvert/releases)
- [Changelog](https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/nbconvert/compare/v7.16.6...v7.17.0)

---
updated-dependencies:
- dependency-name: nbconvert
  dependency-version: 7.17.0
  dependency-type: direct:development
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 21:24:57 +09:00
pre-commit-ci[bot] 6d35301672 chore(pre_commit): ⬆ pre_commit autoupdate (#2143)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/tox-dev/pyproject-fmt: v2.12.1 → v2.14.2](https://github.com/tox-dev/pyproject-fmt/compare/v2.12.1...v2.14.2)
- [github.com/abravalheri/validate-pyproject: v0.24.1 → v0.25](https://github.com/abravalheri/validate-pyproject/compare/v0.24.1...v0.25)
- [github.com/astral-sh/ruff-pre-commit: v0.14.14 → v0.15.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.14...v0.15.0)

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-10 21:24:35 +09:00
Jirka Borovec 8e4fedf3f1 Add match arguments to all pytest.raises for more precise error validation in tests (#2145) 2026-02-10 21:22:55 +09:00
cd0aac2655 fix: add validation for RGB/BGR color values in Color class (#1984)
* fix: add validation for RGB/BGR color values in Color class

- Add range validation (0-255) to from_rgb_tuple() and from_bgr_tuple()
- Raise ValueError for invalid color values with descriptive messages
- Add comprehensive tests for both valid and invalid cases
- Update docstrings to document the new validation behavior

* 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-02-04 23:20:51 +09:00
Jirka BorovecandCopilot 6969e7a78c docs: fix copy doctests without >>> and ... by button & ctr+c (#2138)
* Add custom JavaScript for copying Python REPL code examples without prompts and integrate it into the docs
* Enhance JavaScript copy button functionality to support `.md-code__button` and streamline clipboard handling
* Remove unused `pycon_copy.js` references and streamline JavaScript dependencies in docs and configuration
* Enhance `stripPythonPrompts` to handle triple-quoted strings in REPL code parsing

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-04 23:09:16 +09:00
jirka ea3a0e9a4e Wrap all docstrings in the package with ``pycon`` for compatibility with MKDocs examples rendering 2026-02-04 20:31:18 +09:00
jirka 53950fd426 Update and enhance mkdocs.yml with new features and configuration refinements 2026-02-04 20:31:18 +09:00
Jirka Borovec c67d977682 example/time_in_zone: Update requirements for inference package 2026-02-04 19:59:08 +09:00
5c5bfe5544 docs: update detection core with tips for using Gemini integration (#1925)
* docs: update detection core with tips for using Gemini integration
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-04 18:39:20 +09:00
jirka 0ebab21e9c Add priority instruction for PR reviews to Copilot guidelines 2026-02-04 18:25:18 +09:00
CopilotandBorda 6566063e2b Normalize docstring argument sections and remove redundant types (#2133)
* chore: update docstrings typing and args headers

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
2026-02-04 18:14:28 +09:00
ecdbea340e Add GitHub Copilot PR review guidelines to .github directory (#2134)
* Update GitHub Copilot PR review guidelines to `.github` directory
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-04 18:09:00 +09:00
Jirka Borovecandpre-commit-ci[bot] 5ce6e484b8 Extend supervision modules' docstrings with doctests (#2132)
* Extend `supervision` modules' docstrings with doctests
* fix(pre_commit): 🎨 auto format pre-commit hooks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-04 16:39:27 +09:00
Jirka Borovecandpre-commit-ci[bot] 2d0404e67c Extend docstrings to test cases for enhanced readability (#2130)
* Extend docstrings to test cases for enhanced readability and consistency across testing modules
* Extend test case docstrings across multiple modules for improved clarity and consistency
* Refactor test case docstrings for clarity and consistency in `test_annotators.py`

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-03 17:28:33 +01:00
d89ebde4d1 docs: Fix outdated doc files (#1995)
* docs: Fix outdated doc files per issue #1920
* 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-02-03 16:52:55 +01:00
a897905955 fix "time in zone" demo and make it use RF-DETR (#1922)
* migrate YT video file download script to use `yt_dlp`; old script didn't work anymore
* RF-DETR file example works
* ultralytics stream example migrated to new inference
* migrate inference scripts to use RF-DETR-Medium
* RF-DETR naive stream example
* RF-DETR stream example
* updated README.md

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

* Migrate `time_in_zone` examples to use `jsonargparse` and update `--classes` argument format to accept lists
* Add licensing details for `ultralytics` and `supervision` in `README.md`

---------

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-02-03 15:57:36 +01:00
Jirka Borovec b8a2a6996c refactor: reorganize project structure and update module imports (#2112)
* refactor: reorganize project structure and update module imports
* configure setuptools to use 'src' layout and adjust package discovery
* refactor: move tests to `tests` directory and update imports accordingly
* update lint and mypy configurations to align with `src` and `tests` structure
* update test imports to use corrected `tests.helpers` module path
* fix(pre_commit): 🎨 auto format pre-commit hooks
2026-02-03 15:24:47 +01:00
2ca9bee083 Human behavior with YOLO-World Cookbook (#915)
* Real application underestand visitors with yolo-world
* Improvements in the examples
* Small improvements in typing
* improve path video results
* 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-02-03 14:59:08 +01:00
jirka 6af1ab31f4 Add codecov badge to README and adjust badge arrangement 2026-02-03 14:18:44 +01:00
jirka 5b56d40ef9 Update lychee configuration to accept additional HTTP status codes (200, 408) 2026-02-03 14:04:42 +01:00
Jirka Borovec 2abdccbe1d docs: Wrap all placeholder paths in quotes and code expressions (#2128)
* 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
2026-02-03 14:00:40 +01:00
Jirka Borovec d925cdf666 Standardize examples and error messages with uv CLI for virtual env. and dependency installation (#2129) 2026-02-03 13:59:35 +01:00
c592cd9ff3 Add count in zone guide to supervision docs (#549)
* add count in zone guide to table of contents
* add count in zone docs
* respond to feedback
* fix(pre_commit): 🎨 auto format pre-commit hooks
* update count in zone example
* Apply suggestions from code review

---------

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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 13:58:49 +01:00
Jirka Borovecandpre-commit-ci[bot] 66c49b2e80 examples/traffic_analysis: improve CLI argument handling (#2059)
* refactor(traffic_analysis): improve CLI argument handling
* fix(pre_commit): 🎨 auto format pre-commit hooks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-03 12:56:56 +01:00
0efb55ec19 examples/tracking: improve CLI argument parsing (#2058)
* refactor(tracking): improve CLI argument parsing
* Apply suggestions from code review
* 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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 12:52:50 +01:00
Jirka Borovecandpre-commit-ci[bot] 11f483b75e examples/time_in_zone: improve CLI argument handling (#2057)
* refactor(time_in_zone): improve CLI argument handling
* Refactor examples with `jsonargparse` for improved CLI, rename `confidence` and `iou` arguments for consistency, and update documentation and requirements.
* fix(pre_commit): 🎨 auto format pre-commit hook

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-03 12:49:55 +01:00
1688e71ed9 examples/speed_estimation: improve CLI argument parsing (#2056)
* refactor(speed_estimation): improve CLI argument parsing
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 12:02:22 +01:00
45aedbda7e examples/heatmap_and_track: improve CLI argument parsing (#2055)
* refactor(heatmap_and_track): improve CLI argument parsing
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Make `source_video_path` optional with default fallback to `download_video`; update defaults for `target_video_path`.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 11:52:25 +01:00
6a1b2b8eb4 examples/count_people_in_zone: resolve IoU threshold & improve CLI (#2054)
* refactor(count_people_in_zone): resolve IoU threshold & improve CLI
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 11:35:09 +01:00
jirka 0dc9188c5b Add link-check input to CI workflows with conditional execution adjustments 2026-02-03 10:35:02 +01:00
Jirka Borovec a4de1a0f47 Refine CI with link checks for forked PRs (#2127)
* exclude RF universe links
2026-02-03 10:12:21 +01:00
Jirka Borovec 195f4618a3 Resolve link checker to smoothly work with forked PRs (#2125)
* Resolve link checker to smoothly work with forked PRs
* Add Snyk quality badge URL to excluded links in lychee config
* Simplify Lychee action configuration by removing redundant `env` key usage
* Update augment_links script to include branch/ref as argument in build workflow
2026-02-03 09:49:09 +01:00
Jirka Borovecandjiri BOROVEC fd2d63c1d7 move CODE_OF_CONDUCT.md and CONTRIBUTING.md for improved accessibility (#2036)
* Fix relative links in contribution-related docs and README

---------

Co-authored-by: jiri BOROVEC <jirka@Jiris-MacBook-Pro-J4N257Y6Q2.local>
2026-02-03 03:58:28 +01:00
pre-commit-ci[bot]andjirka c1887da1e8 chore: ⬆ pre_commit autoupdate & resolve many numpy typing (#2126)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/tox-dev/pyproject-fmt: v2.11.1 → v2.12.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.11.1...v2.12.1)
- [github.com/pre-commit/mirrors-mypy: v1.13.0 → v1.19.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.13.0...v1.19.1)

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

* Convert type annotations across several `supervision/metrics` modules to `numpy.typing` for improved alignment with `numpy` standards.
* Add `# type: ignore[no-untyped-call]` annotations in `mean_average_precision.py` for linting compliance
* Refactor `detection.py` to use `getattr` for `np.trapz` and update dependencies in `.pre-commit-config.yaml` with version constraints
* Update `mean_average_precision.py` to remove redundant type ignore comments and refine `.pre-commit-config.yaml` by adding Python version and removing version constraints for `types-PyYAML` and `types-requests`.
* exclude Snyk badge URL

---------

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-02-03 03:47:46 +01:00
efbb5e2599 refactor(metrics): enforce strict typing, sanitize docs & fix numpy 2.0 compat (#2121)
* fix(pre_commit): 🎨 auto format pre-commit hooks
* refactor(metrics): enforce strict type safety and resolve mypy errors
- Fix incompatible types for Optional arguments in matching functions.
- Add explicit type annotations for empty lists and returns.
- Ensure numpy scalars are cast to native python floats.
- Extract variables to comply with line length limits (E501).
- Resolve 'Missing type parameters' for generic dicts and lists.

---------

Co-authored-by: RobertoHita <roberto.hita@edu.uah.es>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-02 17:59:18 +01:00
6149bacc77 Fix and augment relative links in MD files to GitHub blob URLs (#2061)
* Add script to augment relative links in MD files to GitHub blob URLs
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Add type annotations to `augment_links.py` and update config
* Add `lychee-action` for link checking in CI workflows
* Apply suggestions from code review
* links in README.md

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-02 17:47:59 +01:00
Jirka Borovec 86b268d396 Update pyproject.toml: simplify license field and remove legacy (#2124) 2026-02-02 17:13:31 +01:00
a5b51a11e5 Chore CI by adding checks for links and references (#2113)
* 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>
2026-02-02 17:01:19 +01:00
2b1abb1f5b fix(line_zone): tracker-id reuse across classes (#1868)
* fix(line_zone): index crossing state by (tracker_id, class_id)
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Refactor `test_line_zone_tracker_id_reuse_with_different_classes` to use `pytest.mark.parametrize` for improved readability and test coverage.
* Refactor `pytest.mark.parametrize` arguments in `test_line_counter` for improved readability.
* Refactor `pytest.mark.parametrize` in `test_line_counter` to include `pytest.param` for clearer test case descriptions and improved readability.

---------

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-02-02 14:23:47 +01:00
Jirka Borovec cfaea751f2 Refactor metric tests with fixtures and improved structure and clarity (#2123)
* Refactor metric test files by encapsulating fixtures and improved structure and clarity
* Update `test/metrics/conftest.py` fixture values to refine test case coverage
2026-02-02 12:18:10 +01:00
6e8e6fb276 add unit tests for precision, recall and f1_score metrics (#2119)
* add unit tests for precision, recall and f1_score metrics

These 3 metrics had zero test coverage. Created comprehensive tests
covering all main scenarios like perfect matches, partial overlaps,
empty cases, multiple classes and different iou thresholds.

All tests validate results mathematically and cover edge cases.
Tests follow the existing code style and use pytest parametrize
for different averaging methods.

---------

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-02-02 11:40:43 +01:00
jirka 6c2c3f8862 Convert various modules' type annotations + docstring examples to align with numpy.typing & fix linting 2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 64acee9bec Convert supervision/utils/image.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 5f17003f17 Convert supervision/utils/internal.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] cda79458a9 Convert supervision/utils/iterables.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 566844f591 Convert supervision/utils/notebook.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 4c35dee692 Convert supervision/utils/file.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] e2ca285610 Convert supervision/metrics/recall.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] c999fad06f Convert supervision/metrics/precision.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] a542406945 Convert supervision/metrics/mean_average_recall.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 00a123b5fb Convert supervision/metrics/mean_average_precision.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 3d939fd4a2 Convert supervision/metrics/f1_score.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] f005ea1d17 Convert supervision/metrics/detection.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] f6326d5590 Convert supervision/key_points/core.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] b4262bb08e Convert supervision/key_points/annotators.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] a9dad95fa7 Convert supervision/geometry/utils.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 91ff090168 Convert supervision/draw/utils.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 6d68a825ab Convert supervision/draw/color.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 2043ba7feb Convert supervision/detection/utils/vlms.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 5ac08abcf3 Convert supervision/detection/utils/masks.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 1c37d143b4 Convert supervision/detection/utils/iou_and_nms.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] f78b891011 Convert supervision/detection/utils/converters.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] f2fc5b2952 Convert supervision/detection/utils/boxes.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 09565ddacd Convert supervision/detection/tools/csv_sink.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 780db7520d Convert supervision/dataset/utils.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] fd9083ae76 Convert supervision/dataset/core.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] ebe3fd4d2f Convert supervision/classification/core.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] ce4204adc1 Convert supervision/assets/downloader.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] 48450b5da3 Convert supervision/annotators/utils.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
jirkaandcopilot-swe-agent[bot] fbd6f4dc5a Convert supervision/annotators/core.py docstrings to doctests
---

Co-authored-by: copilot-swe-agent[bot] <198982749+copilot@users.noreply.github.com>
2026-02-02 18:10:37 +09:00
Kader Miyanyedi 4c1f33189b refactor(typing): Typing error has been fixed for draw and geometry files. (#2120) 2026-02-02 07:57:24 +01:00
Danielandpre-commit-ci[bot] dcce0e4807 test(detection): add adapter tests and ignore local data directory (#2116)
* test(detection): add adapter tests and ignore local data directory
* fix(pre_commit): 🎨 auto format pre-commit hooks
* chore: retrigger ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-02-02 07:56:04 +01:00
dependabot[bot] b8e88bf9c5 ⬆️ Bump astral-sh/setup-uv in the github-actions group (#2122)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 7.2.0 to 7.2.1
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/61cb8a9741eeb8a550a1b8544337180c0fc8476b...803947b9bd8e9f986429fa0c5a41c367cd732b41)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 07:43:08 +01:00
3b09a6356a fix: process_video silent hang on callback error (#2022)
* Handle process_video worker exceptions
* test: add unit tests for process_video exception handling and fix docstring typo
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Handle `Full` exception in video writer queue and add test for small buffer scenario
* Apply suggestions from code review

---------

Co-authored-by: Your Name <realh4m@users.noreply.github.com>
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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-30 10:46:19 +01:00
5ced8c4ea0 Add unit tests for key_points - skeleton & annotators (#2099)
* Refactor key point annotator tests to use reusable fixtures for test clarity and maintainability
* Apply suggestions from code review
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Move `assert_image_mostly_same` helper to a shared module and update imports in tests
* Update test/key_points/test_skeletons.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-29 18:22:19 +01:00
Jirka Borovec b25556dae9 Remove unnecessary fetch-depth parameter from CI docs (#2115) 2026-01-29 17:02:14 +01:00
Jirka Borovecandpre-commit-ci[bot] beaa0be014 Add comprehensive unittests for KeyPoints functionality (#2109)
* Add comprehensive unittests for KeyPoints functionality
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Refactor and expand KeyPoints tests for improved coverage

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-29 16:50:11 +01:00
Jirka Borovecandpre-commit-ci[bot] a765bd9bd7 typing/annotators: Simplify type annotations in docstrings by removing redundant type details (#2086)
* Simplify type annotations in docstrings by removing redundant type details
* Refactor type annotations and improve type safety across annotator-related utilities and methods
* Enhance type safety by refining NumPy type annotations across annotator-related utilities and methods
* Refine type annotations by adding explicit NumPy ndarray type for `frame_id` in `put` method

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-29 16:40:30 +01:00
7bf03f5a3c typing/utils: Add annotations & enforce stricter typing (#2107)
* Update typing annotations and update type hints across utility modules
* Refine docstrings by aligning parameter descriptions with new typing annotations across utility modules
* Apply suggestions from code review
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Update typing annotations and docstrings across utility modules

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-29 15:46:17 +01:00
Jirka Borovec 93d419d7c6 Enable testing doctest in the package docstrings (#2111)
* Exclude examples directory from test coverage in CI workflow
* demo * case
2026-01-29 10:08:10 +01:00
44614dea94 test: add regression test for numpy color lookup (#2110)
* test: add regression test for numpy color lookup
* fix(pre_commit): 🎨 auto format pre-commit hooks
* test: fix numpy color lookup docstring length
* Update test/annotators/test_core.py

---------

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>
2026-01-28 16:01:26 +01:00
Jirka Borovec ac379e467a Add unittests for supervision.annotators.core module (#2093)
* Add unit tests for `supervision.annotators.core` module
* Update test/annotators/test_core.py
2026-01-27 07:19:16 +01:00
7507d3a68c Add unittests for assets and downloader functionality (#2095)
* Apply suggestions from code review
* Use BASE_VIDEO_URL constant in test instead of hard-coded URL (#2097)
* Replace hard-coded URL with BASE_VIDEO_URL constant in test
* Fix non-deterministic test_invalid_asset by patching Path.exists (#2096)
* Fix test_invalid_asset to be deterministic by patching Path.exists

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-27 07:18:06 +01:00
Jirka Borovec 06bd638f15 Refactor test utilities: clarify module purpose and improve function's names (#2094)
* fix wrong types in test_csv and test_json
2026-01-27 07:13:18 +01:00
Jirka Borovec 5d60d78362 Standardize workflow names for consistency (#2098) 2026-01-27 07:09:56 +01:00
Jirka Borovec 377a87dbba Chore release to use GH release events for PyPI & asset publishing (#2100)
* Chore release to use GH release events for PyPI & asset publishing
* Fix PyPI publish condition to exclude prereleases
* Allow manual triggering of PyPI publish via workflow_dispatch
2026-01-27 07:02:15 +01:00
pre-commit-ci[bot] c2c7ca03d3 chore(pre_commit): ⬆ pre_commit autoupdate (#2084)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/tox-dev/pyproject-fmt: v2.6.0 → v2.11.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.6.0...v2.11.1)
- [github.com/astral-sh/ruff-pre-commit: v0.14.11 → v0.14.14](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.11...v0.14.14)

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-27 07:01:02 +01:00
Jirka Borovec 21482e9109 typing/assets: Add type hints to methods and polish docstrings (#2087) 2026-01-27 05:06:36 +01:00
Jirka BorovecandCopilot 0bf55b7ac7 Configure mypy in pre-commit and pyproject.toml (#2091)
* Configure mypy in pre-commit and pyproject.toml
* ignore_missing_imports=false

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-27 04:55:24 +01:00
dependabot[bot] 0b48ad1c22 Bump wheel from 0.45.1 to 0.46.2 in the uv group across 1 directory (#2101)
Bumps the uv group with 1 update in the / directory: [wheel](https://github.com/pypa/wheel).


Updates `wheel` from 0.45.1 to 0.46.2
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.45.1...0.46.2)

---
updated-dependencies:
- dependency-name: wheel
  dependency-version: 0.46.2
  dependency-type: direct:development
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 14:29:27 +01:00
dependabot[bot] 31e478b84c ⬆️ Bump actions/checkout in the github-actions group (#2105)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.1 to 6.0.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 14:16:53 +01:00
dependabot[bot] 2bbb9ef2ed ⬆️ Update wheel requirement from <0.46,>=0.40 to >=0.40,<0.47 (#2104)
Updates the requirements on [wheel](https://github.com/pypa/wheel) to permit the latest version.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.40.0...0.46.3)

---
updated-dependencies:
- dependency-name: wheel
  dependency-version: 0.46.3
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 14:16:31 +01:00
b85b41d5f1 fix(yolo): round polygon coords before int cast to improve mask accuracy (#2080)
* fix(yolo): round polygon coords before int cast to improve mask accuracy

* fix: E501 Line too long

* Update uv.lock

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Piotr Skalski <piotr.skalski92@gmail.com>
2026-01-23 11:41:21 +01:00
Jirka Borovec 8419279fb9 ci: Remove conflicted removeOnDirtyLabel parameter from PR conflict labeler workflow (#2092) 2026-01-22 13:10:37 +01:00
Jirka BorovecandSkalskiP 1bab3fff8f Enable rendering of type annotations in signature headers (#2085)
* Enable rendering of type annotations in signature headers

* drop comment

---------

Co-authored-by: SkalskiP <piotr.skalski92@gmail.com>
2026-01-20 14:17:29 +01:00
dependabot[bot]andJirka Borovec 82a0aa2463 ⬆️ Bump the github-actions group with 3 updates (#2081)
Bumps the github-actions group with 3 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `astral-sh/setup-uv` from 7.1.6 to 7.2.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v7.1.6...61cb8a9741eeb8a550a1b8544337180c0fc8476b)

Updates `actions/upload-artifact` from 4 to 6
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

Updates `actions/download-artifact` from 4 to 7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-01-19 14:31:04 +01:00
dependabot[bot] f5a8bb93e8 Bump the uv group across 1 directory with 5 updates (#2079)
Bumps the uv group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [fonttools](https://github.com/fonttools/fonttools) | `4.58.5` | `4.60.2` |
| [jupyterlab](https://github.com/jupyterlab/jupyterlab) | `4.4.4` | `4.4.8` |
| [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) | `10.16` | `10.16.1` |
| [urllib3](https://github.com/urllib3/urllib3) | `2.5.0` | `2.6.3` |
| [virtualenv](https://github.com/pypa/virtualenv) | `20.31.2` | `20.36.1` |



Updates `fonttools` from 4.58.5 to 4.60.2
- [Release notes](https://github.com/fonttools/fonttools/releases)
- [Changelog](https://github.com/fonttools/fonttools/blob/main/NEWS.rst)
- [Commits](https://github.com/fonttools/fonttools/compare/4.58.5...4.60.2)

Updates `jupyterlab` from 4.4.4 to 4.4.8
- [Release notes](https://github.com/jupyterlab/jupyterlab/releases)
- [Changelog](https://github.com/jupyterlab/jupyterlab/blob/main/RELEASE.md)
- [Commits](https://github.com/jupyterlab/jupyterlab/compare/@jupyterlab/lsp@4.4.4...@jupyterlab/lsp@4.4.8)

Updates `pymdown-extensions` from 10.16 to 10.16.1
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.16...10.16.1)

Updates `urllib3` from 2.5.0 to 2.6.3
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.5.0...2.6.3)

Updates `virtualenv` from 20.31.2 to 20.36.1
- [Release notes](https://github.com/pypa/virtualenv/releases)
- [Changelog](https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pypa/virtualenv/compare/20.31.2...20.36.1)

---
updated-dependencies:
- dependency-name: fonttools
  dependency-version: 4.60.2
  dependency-type: indirect
  dependency-group: uv
- dependency-name: jupyterlab
  dependency-version: 4.4.8
  dependency-type: indirect
  dependency-group: uv
- dependency-name: pymdown-extensions
  dependency-version: 10.16.1
  dependency-type: indirect
  dependency-group: uv
- dependency-name: urllib3
  dependency-version: 2.6.3
  dependency-type: indirect
  dependency-group: uv
- dependency-name: virtualenv
  dependency-version: 20.36.1
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-19 14:28:25 +01:00
Jirka Borovec a90a1c967b Debugging workflow permissions and add PR dry-run (#2083)
* Debugging workflow permissions and add PR dry-run

* ls all

* path: dist/
2026-01-19 14:23:14 +01:00
Jirka Borovec e2c380acbc Debugging workflow permissions and add PR dry-run (#2082) 2026-01-19 12:35:46 +01:00
SkalskiP 819d74f57c bump version from 0.27.0 to 0.28.0rc0 2026-01-19 12:10:26 +01:00
jirka 47e6a4bc88 Rename workflow file for documentation CI process 2026-01-16 18:51:30 +01:00
09de0f4f06 feat(ruff): add pytest linting rule (#2053)
* feat(ruff): add pytest linting rule
* --unsafe-fixes
* fix(pre_commit): 🎨 auto format pre-commit hooks


---------

Co-authored-by: jiri BOROVEC <jirka@Jiris-MacBook-Pro-J4N257Y6Q2.local>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-13 19:34:22 +01:00
f1e0c9cdd7 chore(pre_commit): add pyproject-fmt and validate-pyproject hooks (#2045)
* chore(pre_commit): add pyproject-fmt and validate-pyproject hooks
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review
* format pre-commit hooks for consistency

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: jiri BOROVEC <jirka@Jiris-MacBook-Pro-J4N257Y6Q2.local>
2026-01-13 18:48:06 +01:00
KshitijAucharmalandJirka Borovec 72d55a2938 docs: changed --extra to --group for dev (#1972)
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-01-13 18:33:09 +01:00
3abb6245c1 chore(pre_commit): ⬆ pre_commit autoupdate (#2075)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.10 → v0.14.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.10...v0.14.11)
- [github.com/executablebooks/mdformat: 0.7.17 → 1.0.0](https://github.com/executablebooks/mdformat/compare/0.7.17...1.0.0)

* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

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: jirka <jirka.borovec@seznam.cz>
2026-01-12 20:15:27 +01:00
Jirka BorovecandCopilot a352e23d95 Switch PR Conflict Labeler workflow to eps1lon/actions-label-merge-conflict (#2076)
* Switch PR Conflict Labeler workflow to `eps1lon/actions-label-merge-conflict`
* Apply suggestions from code review

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 20:11:36 +01:00
Jirka BorovecandCopilot 75a2036ea3 Add GitHub Action for labeling PRs with conflicts (#2073)
* Add GitHub Action for labeling PRs with conflicts
* Apply suggestions from code review

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 16:06:55 +00:00
3d7642c09e chore(pre_commit): enable mdformat with additional dependencies (#2043)
* chore(pre_commit): enable mdformat with additional dependencies
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Fix mdformat-introduced syntax errors in documentation (#2044)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
2026-01-12 16:43:17 +01:00
fabbff2b60 Remove security noqa comments by fixing underlying issues (#2064)
* Fix security issues and remove noqa comments
- Replace MD5 hash_new with md5() and add usedforsecurity=False flag
- Add documentation explaining MD5 is for file integrity, not security
- Add timeout parameter to requests.get call
- Add explicit shell=False and check=False to subprocess.run
- Remove all security-related noqa comments
- Add per-file ignores for S311 in tests and S603 in examples

---------

Co-authored-by: jirka <jirka.borovec@seznam.cz>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-12 15:25:41 +01:00
Jirka BorovecandCopilot 751eddc0ce Add Discord link to issues for community collaboration (#2074)
* Add Discord link to issue templates for community collaboration

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 15:11:23 +01:00
Jirka BorovecandCopilot 8df7aea949 Update CI workflows for documentation build and deployment (#2063)
Material for MkDocs Insiders – Now free for everyone
-> https://squidfunk.github.io/mkdocs-material/blog/2025/11/11/insiders-now-free-for-everyone/

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 15:06:08 +01:00
bbc96e14c9 docs: Update CONTRIBUTING.md for clarity and formatting improvements (#2060)
* docs: Update CONTRIBUTING.md for clarity and formatting improvements
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review
* Update command for installing project dependencies
* Update CONTRIBUTING.md

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 14:05:28 +01:00
Jirka Borovecandpre-commit-ci[bot] 5695b7f58f chore: Update issue templates for bug reports and feature requests (#2052)
* chore: Update issue templates for bug reports and feature requests
* fix(pre_commit): 🎨 auto format pre-commit hooks

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-12 12:32:14 +00:00
Jirka Borovec a1c58a92e2 Update classifiers in pyproject.toml to reflect production status and add multimedia topics (#2047) 2026-01-12 11:04:00 +00:00
Jirka Borovec 886a44b102 Update authors and maintainers in pyproject.toml (#2046) 2026-01-12 12:00:27 +01:00
dependabot[bot] 9b91c779e5 ⬆️ Update pytest-cov requirement (#2071)
Updates the requirements on [pytest-cov](https://github.com/pytest-dev/pytest-cov) to permit the latest version.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.0.0...v7.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-version: 7.0.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-12 11:59:52 +01:00
Jirka Borovecandpre-commit-ci[bot] 3697b2298c chore: add pull request template for improved PR process (#2042)
* chore: add pull request template for improved submission process
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-12 11:58:57 +01:00
Jirka BorovecandCopilot Autofix powered by AI e861878a22 chore: Add shared build-package workflow for (pre)publishing (#2050)
* chore: Add shared build-package workflow for (pre)publishing
* Potential fix for code scanning alert no. 4: Workflow does not contain permissions

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-01-12 10:10:04 +01:00
Jirka Borovec 834fd8db05 ⬆️ Update dependabot config to group GH Actions bumps (#2034) 2026-01-12 10:01:13 +01:00
Jirka Borovec fba1713944 ci: add UV cache pruning step (#2067) 2026-01-12 09:53:15 +01:00
b143121859 Add pytest-cov dependency and integrate Codecov in CI workflow (#2066)
* Add pytest-cov dependency and integrate Codecov in CI workflow
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 09:41:44 +01:00
Jirka Borovec 132cc056f6 chore(pre_commit): remove exclusion for trailing-whitespace hook (#2049) 2026-01-12 09:30:54 +01:00
dependabot[bot] f6e0896278 ⬆️ Bump astral-sh/setup-uv from 7.1.6 to 7.2.0 (#2070)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 7.1.6 to 7.2.0.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/681c641aba71e4a1c380be3ab5e12ad51f415867...61cb8a9741eeb8a550a1b8544337180c0fc8476b)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-12 09:30:04 +01:00
dependabot[bot] de4f060d3b ⬆️ Update build requirement from <1.4,>=0.10 to >=0.10,<1.5 (#2069)
Updates the requirements on [build](https://github.com/pypa/build) to permit the latest version.
- [Release notes](https://github.com/pypa/build/releases)
- [Changelog](https://github.com/pypa/build/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/build/compare/0.10.0...1.4.0)

---
updated-dependencies:
- dependency-name: build
  dependency-version: 1.4.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-12 09:29:41 +01:00
Jirka Borovec 14b7f91c5c chore(pre_commit): remove duplicated pyupgrade hook (#2041) 2026-01-12 09:29:12 +01:00
Jirka BorovecandCopilot 5016ed3c8a chore(pre_commit): update Ruff rules with its references (#2040)
The `fixanle` they do not have any impact if they are not listed in selected.

In Ruff, the select list determines which rules are active (checked). The fixable list merely controls which of those active rules are allowed to automatically modify your code when running with --fix.

If a rule is listed in fixable but not in select, it is effectively disabled; Ruff won't look for it, so there will be no errors to fix. Listing extra items in fixable is harmless but redundant code clutter.

The default value for fixable in Ruff is ["ALL"].

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 08:23:49 +01:00
Jirka Borovec d570366fb4 chore(pre_commit): convert bandit into Ruff's S rule & add TODOs for security improvements (#2039) 2026-01-12 08:08:19 +01:00
95ef33a102 Add testing-guardian job to aggregate test results (#2037)
* Add testing-guardian job to aggregate test results
* Potential fix for code scanning alert no. 2: Workflow does not contain permissions
* Apply suggestions from code review

---------

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>
2026-01-06 17:28:33 +01:00
Jirka BorovecandCopilot fc11beac78 Add push triggers for main and develop branches in workflow files (#2033)
* Add push triggers for `main` and `develop` branches in workflow files
* Add conditional concurrency cancellation for PR vs push events (#2035)

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-06 15:39:28 +01:00
pre-commit-ci[bot] cb1fcecaf2 chore(pre_commit): ⬆ pre_commit autoupdate (#2032)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.13.3 → v0.14.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.3...v0.14.10)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-05 20:29:04 +01:00
Christian ClaussandJirka Borovec afdbdc55f7 pre-commit autoupdate 2025-10-04 (#1976)
* pre-commit autoupdate 2025-10-04
* Rename ruff hook to ruff-check in pre-commit config

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-01-05 17:27:28 +01:00
28dfc39c02 chore(pre_commit): ⬆ pre_commit autoupdate (#1928)
* chore(pre_commit): ⬆ pre_commit autoupdate

updates:
- [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0)
- [github.com/PyCQA/bandit: 1.8.6 → 1.9.2](https://github.com/PyCQA/bandit/compare/1.8.6...1.9.2)
- [github.com/astral-sh/ruff-pre-commit: v0.12.5 → v0.14.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.5...v0.14.10)
- [github.com/asottile/pyupgrade: v3.20.0 → v3.21.2](https://github.com/asottile/pyupgrade/compare/v3.20.0...v3.21.2)

* linting

---------

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: jirka <jirka.borovec@seznam.cz>
2026-01-05 17:21:58 +01:00
dependabot[bot] 793f246ebc ⬆️ Bump actions/create-github-app-token from 2.0.6 to 2.2.1 (#2024)
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 2.0.6 to 2.2.1.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/df432ceedc7162793a195dd1713ff69aefc7379e...29824e69f54612133e76f7eaac726eef6c875baf)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-version: 2.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-05 16:48:24 +01:00
dependabot[bot] 9aa9ef5bbe ⬆️ Bump actions/checkout from 4.2.2 to 6.0.1 (#2025)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 6.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/11bd71901bbe5b1630ceea73d27597364c9af683...8e8c483db84b4bee98b60c0593521ed34d9990e8)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-05 16:48:15 +01:00
dependabot[bot] 6e18804c55 ⬆️ Bump astral-sh/setup-uv from 7.1.2 to 7.1.6 (#2029)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 7.1.2 to 7.1.6.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41...681c641aba71e4a1c380be3ab5e12ad51f415867)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.1.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-05 16:48:02 +01:00
Jirka Borovec bca3c60bb3 resolve docs build / pin mkdocstrings-python<2.0.0 (#2031) 2026-01-05 15:48:18 +01:00
SkalskiP 7f7b25d7e7 bump version from 0.27.0rc6 to 0.27.0 2025-11-16 19:02:42 +01:00
SkalskiP 72506888c0 bump version from 0.27.0rc5 to 0.27.0rc6 2025-11-16 16:31:22 +01:00
Piotr Skalski c5cc24f22d Merge pull request #2017 from roboflow/0.27.0-changelog
supervision 0.27.0 changelog
2025-11-16 16:18:50 +01:00
SkalskiP 47574ed29d supervision 0.27.0 changelog 2025-11-16 16:15:10 +01:00
Piotr Skalski 6119f2017e Merge pull request #2016 from roboflow/feature/make_box_aspect_ratio_part_of_detections_api
add `box_aspect_ratio` property to `sv.Detections`
2025-11-16 13:39:49 +01:00
SkalskiP bbc37b4b6a fix failing tests 2025-11-16 13:34:51 +01:00
SkalskiP e12bfe263d add box_aspect_ratio property to sv.Detections 2025-11-16 13:27:29 +01:00
Piotr Skalski 373fbae1fa Merge pull request #2015 from roboflow/feature/support_for_qwen_3_vl
Qwen3-VL support
2025-11-16 01:02:29 +01:00
SkalskiP 790ccace2c Merge remote-tracking branch 'origin/feature/support_for_qwen_3_vl' into feature/support_for_qwen_3_vl 2025-11-15 22:54:34 +01:00
SkalskiP a99015ac2d more Qwen2.5-VL tests 2025-11-15 22:51:22 +01:00
pre-commit-ci[bot] 52c772d778 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-15 21:48:47 +00:00
SkalskiP 5af13c0f8c add Qwen3-VL prompting example 2025-11-15 22:48:20 +01:00
SkalskiP e0edb28ce6 Merge remote-tracking branch 'origin/feature/support_for_qwen_3_vl' into feature/support_for_qwen_3_vl 2025-11-15 22:27:20 +01:00
SkalskiP c35a35cefd plug Qwen3-VL into sv.Detections.from_vlm 2025-11-15 22:27:11 +01:00
pre-commit-ci[bot] 9bd8f71f26 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-15 21:19:57 +00:00
SkalskiP e29e3832fb plug Qwen3-VL into sv.Detections.from_vlm 2025-11-15 22:19:28 +01:00
SkalskiP a287e68c92 Merge remote-tracking branch 'origin/feature/support_for_qwen_3_vl' into feature/support_for_qwen_3_vl 2025-11-15 22:06:56 +01:00
SkalskiP 0422a66eaa plug Qwen3-VL into sv.Detections.from_vlm 2025-11-15 22:05:46 +01:00
pre-commit-ci[bot] 31db2ded11 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-15 20:40:07 +00:00
SkalskiP 9ab9650763 plug Qwen3-VL into sv.Detections.from_vlm 2025-11-15 21:39:23 +01:00
SkalskiP 353bd5336b Merge remote-tracking branch 'origin/feature/support_for_qwen_3_vl' into feature/support_for_qwen_3_vl 2025-11-15 21:37:05 +01:00
SkalskiP 7301156e46 plug Qwen3-VL into sv.Detections.from_vlm 2025-11-15 21:36:54 +01:00
pre-commit-ci[bot] e68c908077 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-15 20:29:38 +00:00
SkalskiP 2edcbdc487 initial commit with from_qwen_3_vl added, from_qwen_2_5_vl improved 2025-11-15 21:27:55 +01:00
Piotr Skalski 25c2f5cf0d Merge pull request #1997 from AnonymDevOSS/feat/threads-queues-video-process
feat: add threaded I/O pipeline for video processing
2025-11-15 02:40:10 +01:00
SkalskiP 316cb6271d make ruff happy 2025-11-15 02:33:11 +01:00
SkalskiP 70e9af9200 make ruff happy 2025-11-15 02:30:55 +01:00
pre-commit-ci[bot] 38f89125b1 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-15 01:10:49 +00:00
SkalskiP 80d76e712a style and docstring improvements 2025-11-15 02:10:04 +01:00
SkalskiP a296712000 improved InferenceSlicer docstring 2025-11-15 00:00:52 +01:00
Piotr Skalski 12d7c369db Merge pull request #2014 from roboflow/0.27.0-deprecations
remove 0.27.0 deprecations + InferenceSlicer improvements
2025-11-14 23:51:36 +01:00
pre-commit-ci[bot] c8223cbab2 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-14 22:15:39 +00:00
SkalskiP 2c522a9931 improved InferenceSlicer docstring 2025-11-14 23:14:34 +01:00
AnonymDevOSS fc0e133ea9 added example as it was delited by mistake 2025-11-14 21:53:14 +01:00
AnonymDevOSS 15364ac9a3 Rename process_video_threads to process_video and remove legacy implementation and redundant tests 2025-11-14 21:45:06 +01:00
pre-commit-ci[bot] e82b5b9d74 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-14 16:58:25 +00:00
SkalskiP c8f5c741fd reimplement crop_image to skip type casting when Pillow Image given
`get_image_resolution_wh` added
2025-11-14 17:55:07 +01:00
SkalskiP 8d464aa1b5 improve InferenceSlicer implementation lowering the count of generated boxes 2025-11-14 16:42:10 +01:00
SkalskiP ce28ab7fc7 fix uti tests for InferenceSlicer._generate_offset 2025-11-14 15:49:22 +01:00
SkalskiP fae1bc2661 bump version from 0.27.0rc4 to 0.27.0rc5 2025-11-14 14:52:57 +01:00
SkalskiP 4663fab4e4 update new docs page marks 2025-11-14 14:52:39 +01:00
SkalskiP db0892f3e9 remove unnecessary package-level import 2025-11-14 14:52:03 +01:00
Piotr Skalski d330bafaa7 Merge pull request #1926 from roboflow/dependabot/pip/develop/mkdocstrings-gte-0.25.2-and-lt-0.31.0
⬆️ Update mkdocstrings requirement from <0.30.0,>=0.25.2 to >=0.25.2,<0.31.0
2025-11-14 14:12:16 +01:00
Piotr Skalski 8b91d733af Merge pull request #1955 from roboflow/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.13.0
⬆️ Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0
2025-11-14 14:11:57 +01:00
Piotr Skalski 97bf652d90 Merge pull request #1927 from roboflow/dependabot/pip/develop/build-gte-0.10-and-lt-1.4
⬆️ Update build requirement from <1.3,>=0.10 to >=0.10,<1.4
2025-11-14 14:11:24 +01:00
Piotr Skalski b0bbb74558 Merge pull request #1965 from roboflow/dependabot/github_actions/develop/actions/github-script-8.0.0
⬆️ Bump actions/github-script from 7.0.1 to 8.0.0
2025-11-14 13:50:13 +01:00
Piotr Skalski 1d73468dc5 Merge pull request #2012 from jackiehimel/fix/bugs-1959-2000
fix: correct numpy indexing in denormalize_boxes and add ultralytics validation
2025-11-14 13:25:26 +01:00
SkalskiP dfd2a60855 update denormalize_boxes docstring and examples; update from_google_gemini_2_0, from_google_gemini_2_5 and from_moondream to use latest version of denormalize_boxes 2025-11-14 13:12:39 +01:00
SkalskiP f563c5a634 update denormalize_boxes docstring and examples 2025-11-14 12:53:58 +01:00
SkalskiP 35272b40d3 remove ultralytics tests 2025-11-14 12:38:55 +01:00
Piotr Skalski 9320be5d5b Merge pull request #2013 from dominikWin/docs/how-to-json-path
docs: Update JSONSink example path
2025-11-14 12:28:25 +01:00
Piotr Skalski d109fba9d8 Merge pull request #2001 from AnonymDevOSS/feat/speed-up-box-iou-batch
feat: speed up box iou batch using 2d in-place ops instead of 3d
2025-11-14 12:26:25 +01:00
SkalskiP 42d92ba913 making ruff happy 2025-11-14 12:00:45 +01:00
pre-commit-ci[bot] 1e2dc8f88b fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-14 10:58:01 +00:00
SkalskiP f716b7fa3b improve docstrings, examples, variable naming conventions and unit tests 2025-11-14 11:57:31 +01:00
Dominik Winecki f6d52b53db docs: Update JSONSink example path 2025-11-13 13:48:16 -05:00
pre-commit-ci[bot] 61cca76acc fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-13 02:10:25 +00:00
jackiehimel 9ad850af46 fix: correct numpy indexing in denormalize_boxes and add ultralytics validation
- Fix denormalize_boxes numpy indexing bug that caused IndexError with 3+ boxes
- Add validation for missing boxes attribute in from_ultralytics
- Add comprehensive test coverage (11 new tests)

Fixes #1959
Fixes #2000
2025-11-12 20:58:25 -05:00
AnonymDevOSS eee6a85eaa Merge branch 'feat/speed-up-box-iou-batch' of github.com:AnonymDevOSS/supervision into feat/speed-up-box-iou-batch 2025-11-06 23:01:49 +01:00
AnonymDevOSS bb87ab0a6e fixed autoformat errors 2025-11-06 23:00:33 +01:00
pre-commit-ci[bot] da7c5cd65a fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-06 21:57:29 +00:00
AnonymDevOSS ceefe0bab2 feat/ speed up box iou - replaced original function; added tests 2025-11-06 22:52:25 +01:00
Piotr Skalski 78439e03cc Merge pull request #1999 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-7.1.2
⬆️ Bump astral-sh/setup-uv from 6.4.3 to 7.1.2
2025-11-06 00:09:30 +01:00
Piotr Skalski b66416e074 Merge pull request #1993 from ernestlwt/fix/overlapmetric-to-upper
fix: Overlapmetric should check string using uppercase conversion
2025-11-06 00:07:20 +01:00
Piotr Skalski 6c7c49e051 Merge pull request #1974 from kshitijaucharmal/fix/add-pre-commit-in-pyproject
fix: added precommit under dev group
2025-11-05 23:58:32 +01:00
SkalskiP b1b69ad972 bump version from 0.27.0rc3 to 0.27.0rc4 2025-11-05 23:53:36 +01:00
SkalskiP 52be9dc818 fix filter_segments_by_distance docstring 2025-11-05 21:19:33 +01:00
Piotr Skalski c7e95483bf Merge pull request #2008 from roboflow/feature/filter_segments_by_distance
initial version of `filter_segments_by_distance`
2025-11-05 20:41:43 +01:00
SkalskiP 65f6e418a1 making flake8 happy 2025-11-05 20:34:22 +01:00
pre-commit-ci[bot] 1fef946a19 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-05 19:29:22 +00:00
SkalskiP 4c3d51f186 making flake8 happy 2025-11-05 20:28:55 +01:00
pre-commit-ci[bot] 9340cb962b fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-05 19:23:02 +00:00
SkalskiP 6578b4ea52 initial version of filter_segments_by_distance 2025-11-05 20:18:10 +01:00
SkalskiP 0bd60874ca bump version from 0.27.0rc2 to 0.27.0rc3 2025-11-05 13:39:13 +01:00
Piotr Skalski b02ec93b30 Merge pull request #2006 from roboflow/feature/xyxy_to_mask
Feature/xyxy to mask
2025-11-05 13:23:13 +01:00
pre-commit-ci[bot] 89ee57f519 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-05 12:14:45 +00:00
SkalskiP 1c8398942a docs and examples 2025-11-05 13:12:49 +01:00
pre-commit-ci[bot] 3e7e4caf3f fix(pre_commit): 🎨 auto format pre-commit hooks 2025-11-05 12:03:55 +00:00
SkalskiP a3ea8cdb1f bump version from 0.27.0rc1 to 0.27.0rc2 2025-11-05 13:01:30 +01:00
SkalskiP 32dca290ef xyxy_to_mask implementation + tests 2025-11-05 13:00:11 +01:00
AnonymDevOSS 03f623920a feat: tests for add threaded I/O pipeline for video processing 2025-10-28 14:05:52 +01:00
AnonymDevOSS 98476dfacf feat: add threaded I/O pipeline for video processing
Implements pipeline with bounded queues to overlap decode,
compute and encode. Reduces I/O stalls.
2025-10-28 14:05:37 +01:00
AnonymDevOSS 35ff87b08d feat: speed up box iou batch using 2d in-place ops instead of 3d
without creating intermediary (N, M, 2) arrays.
2025-10-28 13:51:28 +01:00
dependabot[bot] 03eed3fd64 ⬆️ Bump astral-sh/setup-uv from 6.4.3 to 7.1.2
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 6.4.3 to 7.1.2.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/e92bafb6253dcd438e0484186d7669ea7a8ca1cc...85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.1.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 00:05:24 +00:00
Ernest Lim 272d9ed5bf fix: Overlapmetric should check string using uppercase conversion 2025-10-16 16:12:28 +08:00
Kshitij Aucharmal 371f8ecc5b fix: added precommit under dev group 2025-10-03 19:46:46 +05:30
Piotr Skalski 171687f3ab Merge pull request #1968 from kshitijaucharmal/develop
Fixed: random print("hm") in merge_metadata
2025-09-25 17:22:01 +02:00
Kshitij Aucharmal 421ad21c98 Fixed: random print("hm") in merge_metadata 2025-09-24 23:25:12 +05:30
dependabot[bot] 50358e96b6 ⬆️ Bump actions/github-script from 7.0.1 to 8.0.0
Bumps [actions/github-script](https://github.com/actions/github-script) from 7.0.1 to 8.0.0.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/60a0d83039c74a4aee543508d2ffcb1c3799cdea...ed597411d8f924073f98dfc5c65a23a2325f34cd)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-22 00:11:46 +00:00
dependabot[bot] 86e10db19e ⬆️ Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.4 to 1.13.0.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/76f52bc884231f62b9a034ebfe128415bbaabdfc...ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 00:07:58 +00:00
Piotr Skalski deb1c9c4f4 Merge pull request #1945 from roboflow/docs/refactor_0.27.0
docs/refactor 0.27.0 missing commits
2025-08-07 16:49:03 +02:00
pre-commit-ci[bot] 6679b1f5a9 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-08-07 14:45:36 +00:00
Piotr Skalski c7de70ed20 Merge pull request #1943 from roboflow/docs/refactor_0.27.0
docs/refactor 0.27.0
2025-08-07 13:46:36 +02:00
SkalskiP 2cdb70eb91 Merge remote-tracking branch 'origin/docs/refactor_0.27.0' into docs/refactor_0.27.0
# Conflicts:
#	supervision/utils/image.py
2025-08-07 13:32:56 +02:00
SkalskiP 2ef029ef4b visualize examples 2025-08-07 13:32:44 +02:00
pre-commit-ci[bot] dce96d462e fix(pre_commit): 🎨 auto format pre-commit hooks 2025-08-07 10:36:03 +00:00
SkalskiP 3fcbef9482 Merge remote-tracking branch 'origin/docs/refactor_0.27.0' into docs/refactor_0.27.0
# Conflicts:
#	supervision/utils/image.py
2025-08-07 12:35:35 +02:00
SkalskiP c8b966be1a align new utils with naming conventions 2025-08-07 12:35:09 +02:00
pre-commit-ci[bot] 72621dce32 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-08-07 10:30:22 +00:00
SkalskiP 098d5e3eb1 Merge remote-tracking branch 'origin/docs/refactor_0.27.0' into docs/refactor_0.27.0
# Conflicts:
#	supervision/utils/image.py
2025-08-07 12:29:54 +02:00
SkalskiP 8c49465d49 align new utils with naming conventions 2025-08-07 12:29:05 +02:00
pre-commit-ci[bot] 4ad36db3bb fix(pre_commit): 🎨 auto format pre-commit hooks 2025-08-07 09:53:22 +00:00
SkalskiP a933b93234 update image utils docs; deprecate overlay_image image 2025-08-07 11:51:59 +02:00
SkalskiP cbb58a8c6f tint_image and grayscale_image functions added 2025-08-07 10:01:50 +02:00
SkalskiP 8fc22f0281 move ImageType to a more suitable location 2025-08-07 07:54:50 +02:00
SkalskiP 4b7b347aea drop create tiles from public API 2025-08-07 07:45:55 +02:00
SkalskiP 5c6745291b after few tests drop support for pycon in docs examples 2025-08-07 07:41:52 +02:00
SkalskiP 83d490dadc initial support for pycon docs examples 2025-08-06 23:19:21 +02:00
SkalskiP 005cdbd37a bump version from 0.27.0rc0 to 0.27.0rc1 2025-08-06 12:27:16 +02:00
Piotr Skalski ade2668ae3 Merge pull request #1932 from roboflow/fix/numpy.int64-object-has-no-attribute-splitlines
fix: AttributeError: 'numpy.int64' object has no attribute 'splitlines'
2025-08-06 12:25:46 +02:00
pre-commit-ci[bot] 46e5965680 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-08-06 10:17:35 +00:00
SkalskiP aab3160cd7 make ruff happy 2025-08-06 12:17:04 +02:00
pre-commit-ci[bot] 13ab215fdf fix(pre_commit): 🎨 auto format pre-commit hooks 2025-08-06 10:05:47 +00:00
SkalskiP a08cda30fb ready for review 2025-08-06 12:02:51 +02:00
dependabot[bot] 652b0a190f ⬆️ Update build requirement from <1.3,>=0.10 to >=0.10,<1.4
Updates the requirements on [build](https://github.com/pypa/build) to permit the latest version.
- [Release notes](https://github.com/pypa/build/releases)
- [Changelog](https://github.com/pypa/build/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/build/compare/0.10.0...1.3.0)

---
updated-dependencies:
- dependency-name: build
  dependency-version: 1.3.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-04 00:52:10 +00:00
dependabot[bot] 6f87e2639e ⬆️ Update mkdocstrings requirement
Updates the requirements on [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) to permit the latest version.
- [Release notes](https://github.com/mkdocstrings/mkdocstrings/releases)
- [Changelog](https://github.com/mkdocstrings/mkdocstrings/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/mkdocstrings/compare/0.25.2...0.30.0)

---
updated-dependencies:
- dependency-name: mkdocstrings
  dependency-version: 0.30.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-04 00:50:49 +00:00
SkalskiP e1393691a4 bump version from 0.26.1 to 0.27.0rc0 2025-07-31 17:49:06 +02:00
Piotr Skalski 90f8582e4f Merge pull request #1919 from Ashp116/feature/spline-tracer
FEATURE: Spline Annotations
2025-07-31 16:53:33 +02:00
Ashp116 0c9fea4d9f UPDATE: Change Smooth to bool 2025-07-30 18:24:14 -04:00
Ashp116 cdca2e6b51 UPDATE: Removed SplineAnnotator and added smooth flag for TraceAnnotator 2025-07-30 13:48:38 -04:00
pre-commit-ci[bot] 8407d5a692 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-30 07:15:02 +00:00
Ashp116 eaf6cdd477 Precommit 2025-07-30 03:14:00 -04:00
pre-commit-ci[bot] f447b6fa95 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-30 07:10:19 +00:00
Ashp116 8c6ac2dd29 UPDATE: Made smoothing and spline_order as hyperparameters 2025-07-30 02:53:58 -04:00
Ashp116 22b6d3d464 ADD: Added a spline annotator 2025-07-30 02:04:24 -04:00
Piotr Skalski dda3900943 Merge pull request #1917 from roboflow/feat/label-annotator-offset
add: support for an additional parameter `text_anchor_offset` in label annotators
2025-07-29 14:50:34 +02:00
Piotr Skalski ac0c367e81 Merge pull request #1914 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-6.4.3
⬆️ Bump astral-sh/setup-uv from 6.4.1 to 6.4.3
2025-07-29 14:48:27 +02:00
SkalskiP 6f2490cc23 fix formatting 2025-07-29 14:43:38 +02:00
Piotr Skalski 4a9d06eb50 Merge pull request #1918 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-07-29 14:40:38 +02:00
pre-commit-ci[bot] 21e311a319 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-29 12:40:11 +00:00
SkalskiP 71a14812fe LabelAnnotator and RichLabelAnnotator docs improvement 2025-07-29 14:39:41 +02:00
SkalskiP 35fdcb0a1a Merge branch 'develop' into feat/label-annotator-offset 2025-07-29 12:46:06 +02:00
Piotr Skalski 6d26a9766c Merge pull request #1915 from roboflow/feature/advanced_keypoints_indexing_and_slicing
advanced `sv.KeyPoints` filtering and slicing
2025-07-29 12:45:29 +02:00
SkalskiP 1cfaef9405 Merge branch 'develop' into feature/advanced_keypoints_indexing_and_slicing 2025-07-29 12:42:34 +02:00
pre-commit-ci[bot] 063e2092c8 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.4 → v0.12.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.4...v0.12.5)
2025-07-28 17:28:44 +00:00
soumik12345 cb215d26f3 add: support for an additional parameter text_anchor_offset in _BaseLabelAnnotator 2025-07-28 19:03:17 +05:30
Soumik Rakshit 8bbe80e683 Merge pull request #1916 from AlexBodner/fix/docs-vitpose
Corrected vitpose docstring
2025-07-28 18:38:22 +05:30
Alex Bodner 9a0483446a fixed docs 2025-07-28 09:53:44 -03:00
pre-commit-ci[bot] f4561f9ba7 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-28 06:29:08 +00:00
SkalskiP beaf89cb22 initial version of advanced key points filtering and slicing + some naming refactor 2025-07-28 08:24:43 +02:00
dependabot[bot] 96b58c2860 ⬆️ Bump astral-sh/setup-uv from 6.4.1 to 6.4.3
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 6.4.1 to 6.4.3.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/7edac99f961f18b581bbd960d59d049f04c0002f...e92bafb6253dcd438e0484186d7669ea7a8ca1cc)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-28 00:07:27 +00:00
Piotr Skalski 8873da4a30 Merge pull request #1902 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-6.4.1
⬆️ Bump astral-sh/setup-uv from 6.3.1 to 6.4.1
2025-07-26 17:57:44 +02:00
Piotr Skalski 1362850986 Merge pull request #1904 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-07-26 17:57:15 +02:00
Piotr Skalski 98a4391677 Merge pull request #1913 from roboflow/fix/pending_track_id
fix for #1911
2025-07-26 17:51:14 +02:00
SkalskiP 036a956473 fix for #1911 2025-07-26 17:46:04 +02:00
Piotr Skalski b381fa198f Merge pull request #1884 from roboflow/feat/from_deepseek_vl_2_support
feat: 🚀 from_vlm deepseek vl 2 support
2025-07-25 16:57:44 +02:00
pre-commit-ci[bot] 8ca2e9fe8d fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-25 14:44:15 +00:00
soumik12345 bc1d73a307 chore: address feedback 2025-07-25 20:13:28 +05:30
Piotr Skalski 9679cd5c4e Merge pull request #1912 from roboflow/feature/edit_distance_and_fuzzy_match
`edit_distance` and `fuzzy_match_index` that will allow to match faulty class name generated by VLMs with exact class names
2025-07-25 14:52:24 +02:00
pre-commit-ci[bot] 00817df9e2 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-25 11:41:30 +00:00
SkalskiP ec189bf388 new, more memory efficient edit_distance implementation 2025-07-25 13:41:03 +02:00
SkalskiP 58bdce5707 tests fixed 2025-07-24 15:13:46 +02:00
pre-commit-ci[bot] 8262b6e64b fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-24 13:06:48 +00:00
SkalskiP 72fe0bf47f initial version of edit_distance and fuzzy_match_index that will allow to match faulty class name generated by VLMs with exact class names 2025-07-24 15:05:19 +02:00
soumik12345 137078602b add: tests 2025-07-24 15:17:05 +05:30
soumik12345 8fa21dd165 update: from_deepseek_vl_2 2025-07-24 15:04:59 +05:30
soumik12345 da70389546 add: prompt engineering tip for deepseek-vl2 2025-07-24 14:23:24 +05:30
soumik12345 cc1525707a update: docstring for Detections.from_vlm 2025-07-24 13:11:06 +05:30
soumik12345 b3aee43c3b update: from_deepseek_vl_2 logic 2025-07-24 12:55:40 +05:30
Soumik Rakshit 932c1aa91e Merge pull request #1910 from rafaelpadilla/fix/import_box_iou_batch
exposing `box_iou_batch`  in `supervision/detection/utils__init__.py`
2025-07-23 22:00:55 +05:30
rcvsq 76ee05420d exposing box_iou_batch in supervision/detection/utils__init__.py 2025-07-23 14:58:09 +00:00
soumik12345 a470bc2976 chore: make pre-commit happy 2025-07-23 18:36:31 +05:30
Soumik Rakshit cf725dd4db Merge branch 'develop' into feat/from_deepseek_vl_2_support 2025-07-23 18:31:07 +05:30
Piotr Skalski 317ac0810e Merge pull request #1907 from roboflow/changelog/0.26.1
update: changelog for 0.26.1
2025-07-23 08:35:47 +02:00
SkalskiP cb6018ef04 final changes before supervision-0.26.1 2025-07-23 08:32:07 +02:00
pre-commit-ci[bot] 580fcdde4c fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-22 10:51:53 +00:00
soumik12345 ad4f44644c update: changelog for 0.26.1 2025-07-22 16:20:38 +05:30
Piotr Skalski 0c8a9d34a6 Merge pull request #1906 from roboflow/fix/border_thickness
fix: border thickness parameter usage for `PercentageBarAnnotator`
2025-07-22 12:27:26 +02:00
soumik12345 d067f32678 fix: border thickness parameter usage for PercentageBarAnnotator 2025-07-22 15:48:54 +05:30
Piotr Skalski d251677774 Merge pull request #1894 from roboflow/fix/mAP-area
fix: correct area handling in MeanAveragePrecision for size-specific mAP
2025-07-22 08:07:20 +02:00
pre-commit-ci[bot] b1780fbae5 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.3 → v0.12.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.3...v0.12.4)
2025-07-21 17:29:41 +00:00
SkalskiP e8cb962fcc bump version from 0.26.1 to 0.26.1rc0 2025-07-21 10:14:58 +02:00
dependabot[bot] 1e84351d60 ⬆️ Bump astral-sh/setup-uv from 6.3.1 to 6.4.1
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 6.3.1 to 6.4.1.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/bd01e18f51369d5a26f1651c3cb451d3417e3bba...7edac99f961f18b581bbd960d59d049f04c0002f)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 00:32:44 +00:00
Piotr Skalski baa0402d5a Merge pull request #1901 from roboflow/fix/inference-overlap-metric-fix
fix:  🐞 update inference_slicer.py for improved detection handling
2025-07-21 00:07:28 +02:00
pre-commit-ci[bot] c54d16c57e fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-20 22:02:42 +00:00
SkalskiP 1adb75520f bump version from 0.26.0 to 0.26.1; improve docstrings; unify naming; improve parsing 2025-07-21 00:02:14 +02:00
pre-commit-ci[bot] db51a9ff98 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-20 17:12:24 +00:00
Onuralp SEZER f044398c17 fix: 🐞 update inference_slicer.py for improved detection handling 2025-07-20 20:11:37 +03:00
pre-commit-ci[bot] 704652a0d2 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-18 15:19:38 +00:00
Balthasar 6e3001194d improve tests 2025-07-18 17:19:10 +02:00
Balthasar d7774381cc Merge branch 'develop' into fix/mAP-area 2025-07-18 12:11:05 +02:00
Soumik Rakshit 1c8ec0a287 Merge pull request #1898 from roboflow/fix/negative-mAP-values
fix: handle -1 sentinel values in mAP calculation to prevent negative results and mimic pycocotools behaviour
2025-07-18 15:32:21 +05:30
Balthasar 118e3a496c fix: line length 2025-07-18 10:09:53 +02:00
pre-commit-ci[bot] a139fb0b49 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-18 08:00:37 +00:00
Balthasar afdbb0a75c fix: keep it DRY 2025-07-18 09:41:06 +02:00
Balthasar 001a4254f8 fix: improve code, more fixes and add tests 2025-07-18 09:41:06 +02:00
Balthasar 2e72e70893 basic fix 2025-07-18 09:41:06 +02:00
pre-commit-ci[bot] 2907c40ecc fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-17 08:00:04 +00:00
Balthasar 2c67cee720 fix: tests and adjust comment 2025-07-17 09:57:55 +02:00
Balthasar 0ddbcb2010 fix: start id with 1 because 0 means no match 2025-07-17 09:49:21 +02:00
pre-commit-ci[bot] 40d4c6f554 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-16 18:07:52 +00:00
Balthasar bf88636487 Merge branch 'fix/mAP-area' of https://github.com/roboflow/supervision into fix/mAP-area 2025-07-16 20:07:30 +02:00
Balthasar a444b3bde8 fix: cleanup comment 2025-07-16 20:06:27 +02:00
pre-commit-ci[bot] 4009f9d886 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-16 18:00:47 +00:00
Balthasar 3f926c618a fix: cleanup comments 2025-07-16 19:51:59 +02:00
Balthasar 71d6670e7d fix(metrics): update area calculation in MeanAveragePrecision to use area property as fallback if it's not COCO 2025-07-16 19:50:37 +02:00
Piotr Skalski 08226e9199 Merge pull request #1893 from roboflow/main
Merge pull request #1742 from roboflow/develop
2025-07-16 02:50:11 +02:00
Piotr Skalski d8de58d7f3 Merge pull request #1742 from roboflow/develop
`supervision-0.26.0` release
2025-07-16 02:39:07 +02:00
SkalskiP a1e402987b bump version from 0.26.0rc8 to 0.26.0 2025-07-16 02:33:29 +02:00
Piotr Skalski 78e5cd56f3 Merge pull request #1891 from roboflow/docs/vlm-improvements
docs: 📝 enhance prompt engineering tips for Qwen2.5-VL and Moondream models
2025-07-16 02:32:39 +02:00
Onuralp SEZER 462146b34e docs: 📝 add prompt engineering tips for Qwen2.5-VL and Moondream models for from_lmm 2025-07-16 02:30:12 +02:00
Onuralp SEZER 12e38da1a0 docs: 📝 enhance prompt engineering tips for Qwen2.5-VL and Moondream models 2025-07-16 01:50:34 +02:00
Piotr Skalski 56a0ac5cbf Merge pull request #1888 from roboflow/docs/changelog-0.26.0
update(docs): changelog + deprecation for supervision 0.26.0
2025-07-16 01:07:51 +02:00
pre-commit-ci[bot] d1aa1726f5 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 23:05:19 +00:00
SkalskiP 0f56a405c6 updates before supervision-0.26.0 release 2025-07-16 01:04:51 +02:00
SkalskiP 4948612cd4 Merge branch 'develop' into docs/changelog-0.26.0 2025-07-16 00:06:50 +02:00
pre-commit-ci[bot] 6046e88eb1 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 22:01:32 +00:00
soumik12345 77c45355ff chore: address feedback 2025-07-16 03:31:03 +05:30
soumik12345 3ff1414fc2 update: changelog 2025-07-16 02:20:01 +05:30
SkalskiP 4e832b2cf4 bump version from 0.26.0rc7 to 0.26.0rc8 2025-07-15 22:12:22 +02:00
Piotr Skalski 5c1a5eab3a Merge pull request #1890 from roboflow/refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility
refactor: split utils across multiple files to increase utils visibility and prevent circular imports
2025-07-15 22:05:50 +02:00
Onuralp SEZER 5d6f5bfde3 fix(deprecated): change MeanAveragePrecision to frozen dataclass and enhance deprecated decorator for classes 2025-07-15 22:41:25 +03:00
SkalskiP 2b47d8e4cc fix double decorator bug 2025-07-15 21:28:58 +02:00
SkalskiP bbadfb3cbd Revert "fix double decorator bug"
This reverts commit 880a9e8eb5.
2025-07-15 21:27:48 +02:00
SkalskiP 880a9e8eb5 fix double decorator bug 2025-07-15 21:21:05 +02:00
pre-commit-ci[bot] 5397031cee fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 19:14:46 +00:00
SkalskiP c4ede20a2d add deprecation message to old mAP 2025-07-15 21:13:46 +02:00
SkalskiP a135bd6268 add deprecation message to old mAP 2025-07-15 21:12:50 +02:00
SkalskiP 0a3333474a Merge remote-tracking branch 'origin/refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility' into refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility
# Conflicts:
#	supervision/detection/utils/iou_and_nms.py
2025-07-15 20:55:52 +02:00
SkalskiP d854e23e9a fix latex problems 2025-07-15 20:55:12 +02:00
pre-commit-ci[bot] 1bc672afd3 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 18:47:25 +00:00
soumik12345 14d3b79387 fix: formula in box_iou docstring 2025-07-16 00:17:00 +05:30
pre-commit-ci[bot] facc64bb3a fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 18:38:12 +00:00
SkalskiP f9cdb93b87 Merge remote-tracking branch 'origin/refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility' into refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility 2025-07-15 20:37:47 +02:00
SkalskiP 2dca99d0dc added mask_non_max_merge to quick imports 2025-07-15 20:35:44 +02:00
Onuralp SEZER 334d8e6506 fix: 🐞 correct possessive form in docstring for LMM and VLM enums 2025-07-15 21:34:24 +03:00
Onuralp SEZER 8710bde5b2 docs: 📝 add docstring to validate_vlm_parameters 2025-07-15 21:31:29 +03:00
pre-commit-ci[bot] 3ba5c12211 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 18:26:17 +00:00
Onuralp SEZER b8d646ac98 fix: 🐞 type annotations for internal.py vars 2025-07-15 21:23:41 +03:00
SkalskiP ab9d128828 mark from_lmm as deprecated in docs 2025-07-15 20:21:27 +02:00
SkalskiP 873f249bf0 Merge remote-tracking branch 'origin/refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility' into refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility 2025-07-15 20:10:53 +02:00
SkalskiP 5b42be9b4a make sure only recently updated pages have new status 2025-07-15 20:10:35 +02:00
pre-commit-ci[bot] b507ed90dd fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 17:56:39 +00:00
SkalskiP a25039ff54 Merge remote-tracking branch 'origin/refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility' into refactor/split_detection_utils_to_prevent_circular_imports_and_increase_utils_visibility 2025-07-15 19:56:13 +02:00
SkalskiP 6b905f2d18 works with python 3.9; docs update 2025-07-15 19:56:04 +02:00
Onuralp SEZER d52fcf17a8 fix: 🐛 add future annotations import for compatibility and fix tests 2025-07-15 20:41:38 +03:00
pre-commit-ci[bot] 592a649b50 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 17:26:01 +00:00
SkalskiP fa5fcbb264 utils split across multiple files; internal and external imports working; utils tests split across multiple files; tests working locally 2025-07-15 19:23:55 +02:00
Piotr Skalski 9dc2785762 Merge pull request #1886 from roboflow/feat/upgrade-python-3-9
feat: 🚀 dropping python 3.8 support and upgrade all codes to python3.9 syntax style
2025-07-15 15:59:20 +02:00
Onuralp SEZER 212e69b5a4 refactor: 🧪 type hints to use the new union syntax for optional types
- Updated type hints across multiple files to replace `Optional[X]` with `X | None` for better readability and consistency.
- Added `from __future__ import annotations` to files to enable postponed evaluation of type annotations.
- Adjusted function signatures and variable types in various modules including `polygon_zone.py`, `smoother.py`, `transformers.py`, `vlm.py`, and others.
- Ensured compatibility with Python 3.10+ type hinting features.

Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-15 16:36:01 +03:00
Onuralp SEZER 7fde67ef75 Merge branch 'develop' into feat/upgrade-python-3-9 2025-07-15 16:26:55 +03:00
Piotr Skalski 8a7e2fedbc Merge pull request #1820 from hidara2000/develop
feat(annotators): enhance label annotators with frame boundary adjust…
2025-07-15 14:57:01 +02:00
Onuralp SEZER 3b2ca1b542 Merge branch 'develop' into feat/upgrade-python-3-9 2025-07-15 15:32:12 +03:00
Onuralp SEZER 8a000b93b0 Merge pull request #1889 from roboflow/docs/mathjax
docs(supervision): configure mkdocs to add mathjax support
2025-07-15 15:31:26 +03:00
Onuralp SEZER b6cd9dd3f3 chore: 🧹 clean up unused imports and optimize code structure and convert more List to list 2025-07-15 15:30:08 +03:00
pre-commit-ci[bot] a5155e23f2 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 12:27:38 +00:00
Onuralp SEZER 3dd1ce4e1c Merge branch 'develop' into feat/upgrade-python-3-9 2025-07-15 15:27:05 +03:00
Piotr Skalski 71e7c3e17c Merge pull request #1774 from SunHao-AI/develop
Support for IOS Matching Metric. Introduced the `mask_non_max_merge` function for handling non-maximum merging of masks
2025-07-15 14:11:40 +02:00
pre-commit-ci[bot] cf179b9dfe fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 11:48:01 +00:00
Soumik Rakshit 9f3ffdd26d fix: typo in utils.py 2025-07-15 17:17:39 +05:30
soumik12345 7c1168fbc6 chore: make pre-commit happy 2025-07-15 16:46:10 +05:30
soumik12345 af31b96199 update: docstring for box_iou to add formula 2025-07-15 16:41:54 +05:30
pre-commit-ci[bot] 9400270e34 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 11:05:31 +00:00
soumik12345 bcbbc57854 chore: configure mkdocs to add mathjax support 2025-07-15 16:34:22 +05:30
Onuralp SEZER b792db72fd chore: 🧹 update requirements.txt to remove version constraints for dependencies 2025-07-15 12:29:47 +02:00
soumik12345 84c9a34f92 update: docstring 2025-07-15 15:58:38 +05:30
soumik12345 c11a7de949 chore: refactor docs for 2025-07-15 15:58:26 +05:30
pre-commit-ci[bot] f68a6bc362 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 10:16:29 +00:00
soumik12345 7ea8c2e43c chore: remove excessive comments in group_overlapping_masks 2025-07-15 15:46:10 +05:30
Onuralp SEZER 2adb64b949 chore: 🧹 update requirements files to remove version constraints 2025-07-15 12:15:55 +02:00
pre-commit-ci[bot] 9a38ebd15e fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 10:14:09 +00:00
soumik12345 4977fd64b1 add: test_mask_non_max_merge 2025-07-15 15:43:44 +05:30
pre-commit-ci[bot] ae77077853 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 10:05:00 +00:00
soumik12345 007d8f5dad chore: make enum comparisons 2025-07-15 15:34:24 +05:30
soumik12345 b3024e780d chore: make pre-commit happy 2025-07-15 15:01:57 +05:30
soumik12345 ebf4b930b7 add: test for mask_non_max_merge 2025-07-15 15:01:36 +05:30
soumik12345 fd25f4bf81 add: docs for mask_non_max_merge 2025-07-15 15:01:25 +05:30
soumik12345 3fed5f9a25 update: docs 2025-07-15 14:18:00 +05:30
soumik12345 7849831e12 chore: make pre-commit happy 2025-07-15 14:18:00 +05:30
pre-commit-ci[bot] 42e9c5ffcb fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-15 07:37:28 +00:00
soumik12345 fb16bd9ee1 chore: change match_metric to overlap_metric 2025-07-15 13:07:01 +05:30
soumik12345 2c986abf5e add: remove_noisy_segments in the changelog 2025-07-15 12:20:23 +05:30
Onuralp SEZER 667e6491ac chore: 🧹 update uv lock file 2025-07-15 02:13:44 +02:00
Onuralp SEZER 1d3e887fca chore: 🧹 update requirements and change default weights file in ultralytics_example.py for count people example 2025-07-15 00:58:35 +03:00
Onuralp SEZER 63cc934cd4 chore: 🧹 remove unused pyupgrade configuration from pyproject.toml 2025-07-15 00:17:52 +03:00
Onuralp SEZER edfe0a944a refactor: 🛠️ update type hints to use built-in types in VLM and validation functions 2025-07-15 00:16:40 +03:00
Onuralp SEZER 25edd9be21 Merge branch 'develop' into feat/upgrade-python-3-9 2025-07-15 00:07:17 +03:00
Piotr Skalski daaadaa1f9 Merge pull request #1877 from roboflow/feat/gemini-2_5_segmentation
feat: 🚀 add support for Google Gemini 2.5 bounding box and mask parsing for "from_vlm"
2025-07-14 23:04:33 +02:00
Onuralp SEZER 9443a433fc fix: 🐞quick typo fix. 2025-07-14 22:03:00 +03:00
soumik12345 b2776cadf7 chore: make pre-commit happy 2025-07-15 00:32:03 +05:30
soumik12345 1337b7ffd5 update: changelog + deprecation for supervision 0.26.0 2025-07-15 00:28:23 +05:30
Onuralp SEZER efe59cb91c chore: 🧹 use same var name compare to other functions 2025-07-14 20:57:07 +03:00
Onuralp SEZER 13fa672d9e chore: 🧹formatting fix 2025-07-14 20:50:54 +03:00
Onuralp SEZER 85ec990aa4 docs: 📝 improve documentation for VLM parameters
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-14 20:48:35 +03:00
pre-commit-ci[bot] 6929f1b798 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-14 17:32:55 +00:00
SkalskiP 63519dd89c Merge remote-tracking branch 'origin/feat/gemini-2_5_segmentation' into feat/gemini-2_5_segmentation 2025-07-14 19:32:33 +02:00
SkalskiP 2b052430bd updated from_lmm docs 2025-07-14 19:32:14 +02:00
Onuralp SEZER 7b8560016e Merge pull request #1887 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-07-14 20:27:14 +03:00
pre-commit-ci[bot] 886bc16fd4 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-14 17:25:43 +00:00
pre-commit-ci[bot] 4ea79f3634 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.2 → v0.12.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.2...v0.12.3)
2025-07-14 17:24:59 +00:00
Onuralp SEZER 5d883447a3 docs: 📝 update Python version requirement to 3.9 in docs and clean up code 2025-07-14 20:21:35 +03:00
Onuralp SEZER 00fab37e58 feat: 🚀 dropping python 3.8 support and upgrade all codes to python3.9 syntax style as min
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-14 20:12:11 +03:00
Onuralp SEZER 328c34ab8b feat: ✨ add MOONDREAM enum and allowed arguments in VLM 2025-07-14 19:59:44 +03:00
Onuralp SEZER d29fb8ad05 test: 🧪 add test case for Google Gemini 2.5 with sample JSON output for 2 masks 2025-07-14 18:48:17 +03:00
Onuralp SEZER c2abb24c26 test: 🧪 add test case for gemini 2.5 segmentation 2025-07-14 18:38:32 +03:00
Onuralp SEZER 8c4a1e5a5e fix: 🐞 correct formatting and remove trailing whitespace in core.py 2025-07-14 17:59:48 +03:00
pre-commit-ci[bot] ff3c85d380 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-14 14:57:26 +00:00
Onuralp SEZER 2c63511af6 docs: ✏️ add usage tips and examples for Google Gemini 2.5 in core.py 2025-07-14 17:56:58 +03:00
soumik12345 9517987b7b chore: make pre-commit happy 2025-07-14 20:19:32 +05:30
Onuralp SEZER 129eb89c20 fix: 🐞 add missing newline at end of extra.css file 2025-07-14 17:29:25 +03:00
Onuralp SEZER e8ca201198 Merge branch 'develop' into feat/gemini-2_5_segmentation 2025-07-14 17:29:00 +03:00
Onuralp SEZER b87a504d22 fix: 🐞 remove GOOGLE_GEMINI_2_5 from gemini_2_0 check and only use new gemini_2_5 func 2025-07-14 17:26:59 +03:00
Onuralp SEZER 076f9e293f fix: 🐞 fix mask filtering in from_google_gemini_2_5 to detect properly 2025-07-14 17:18:03 +03:00
Onuralp SEZER 6c4a2a8d44 test: 🧪 add gemini_2_5 test and fix failed cases in gemini_2_5 function for better to handle different cases
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-14 16:50:41 +03:00
SkalskiP 1a83005a44 add docs table style 2025-07-14 15:12:27 +02:00
pre-commit-ci[bot] 74d5f0f9a6 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-14 13:07:22 +00:00
Soumik Rakshit 50c0d54dd5 Merge branch 'develop' into develop 2025-07-14 18:36:25 +05:30
Onuralp SEZER 377f7db0ad feat: ✨ add confidence field to the result of from_google_gemini_2_5 function 2025-07-14 15:22:10 +03:00
Onuralp SEZER 3b112ffb46 refactor: ✨ update from_google_gemini_2_5 function to include optional classes parameter and adjust return values 2025-07-14 15:11:12 +03:00
Piotr Skalski a192eed093 Merge pull request #1874 from Ashp116/single-iou
Feature: box_iou
2025-07-14 13:37:35 +02:00
soumik12345 18cd73f55a chore: import box_iou to supervision/__init__.py 2025-07-14 17:03:23 +05:30
Onuralp SEZER 4ed667da88 fix: 🐞 rename from_google_gemini to from_google_gemini_2_0 keep names consistent 2025-07-14 14:24:37 +03:00
Onuralp SEZER 5d866fd8a1 refactor: ✨ improve validate_resolution function to have type,value check similar to other validate functions 2025-07-14 14:14:03 +03:00
Onuralp SEZER ddf9a060ba Merge branch 'develop' into feat/gemini-2_5_segmentation 2025-07-14 14:10:12 +03:00
pre-commit-ci[bot] 8e437f89fa fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-14 10:49:36 +00:00
soumik12345 9ce4632f47 chore: add usage examples in docstrings 2025-07-14 16:18:04 +05:30
Piotr Skalski baa78fc4da Merge pull request #1882 from roboflow/feat/vlm-tests
Remove test file for from_florence_2 function and merge into main test_vlm file
2025-07-14 12:22:05 +02:00
Onuralp SEZER 2bf448f285 refactor: 🧹 remove test file for from_florence_2 function and merge into main test_vlm file
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-14 13:09:58 +03:00
Piotr Skalski 462468f3d8 Merge pull request #1878 from roboflow/feat/moondream-vlm-object-detection
feat: 🚀  Support for Moondream VLM for Object Detections
2025-07-14 11:46:57 +02:00
Onuralp SEZER 6bae8bc6e6 formatting: 🧹 code readability by formatting return statements and function signatures in Google Gemini 2.5 integration 2025-07-14 11:02:19 +03:00
Onuralp SEZER 3152f5f0ea docs: 📝 add docs to confidence scores parameter to from_google_gemini_2_5 function 2025-07-14 10:59:49 +03:00
Onuralp SEZER c7ebfeb4bc feat: 🚀 enhance Google Gemini 2.5 integration to include confidence scores in detection results 2025-07-14 10:58:59 +03:00
Ashp116 d1c27f2d2b FIX: Fixed docsstrings 2025-07-12 18:13:37 -04:00
Ashp116 92599ad497 UPDATE: Updated documentation 2025-07-12 15:59:59 -04:00
Ashp116 a118599233 Precommit 2025-07-12 14:57:18 -04:00
pre-commit-ci[bot] 2f44aab2b5 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-12 18:56:14 +00:00
Ashp116 0488abf083 Merge branch 'single-iou' of https://github.com/Ashp116/supervision into single-iou 2025-07-12 14:55:50 -04:00
Ashp116 d2ffd04aed Precommit 2025-07-12 14:54:26 -04:00
pre-commit-ci[bot] ee7782b551 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-12 18:52:14 +00:00
Ashp116 2378d8bdca UPDATE: Code review fix and docs updated 2025-07-12 14:50:43 -04:00
Onuralp SEZER 3218da8cbd test: 🧪 re-add parameterized tests for from_moondream function 2025-07-11 21:39:45 +03:00
Onuralp SEZER eb330ac1c1 Merge branch 'develop' into feat/moondream-vlm-object-detection 2025-07-11 21:13:34 +03:00
Onuralp SEZER 641b343c7f docs: 📝 update resolution parameter to fixed values in Detections class methods 2025-07-11 20:17:28 +03:00
Onuralp SEZER 0601a4157d refactor: simplify return statement in from_moondream function 2025-07-11 20:16:07 +03:00
SkalskiP 62e80b82ac update docstring examples 2025-07-11 19:05:18 +02:00
Piotr Skalski a352521c15 Merge pull request #1881 from roboflow/feat/pyproject-deps-groups
feat: 🚀 exclude all dev extras from pypi package and only available to dev installations #pep-0735
2025-07-11 18:49:33 +02:00
Piotr Skalski 8697fc0233 Merge pull request #1883 from roboflow/fix/gemini-vlm-support
chore: address feedback for google gemini support
2025-07-11 18:46:25 +02:00
soumik12345 fe0cefd1dc chore: add comments to testcase parameters 2025-07-11 21:44:14 +05:30
soumik12345 4d364885e9 update: docstring 2025-07-11 21:40:04 +05:30
Onuralp SEZER 535cb2a91b fix(vlm): 📝 correct formatting in docstring for from_deepseek_vl_2 function 2025-07-11 18:49:50 +03:00
pre-commit-ci[bot] 8e845caeeb fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-11 15:44:15 +00:00
Onuralp SEZER 9e2a535044 Merge branch 'develop' into feat/from_deepseek_vl_2_support 2025-07-11 18:43:02 +03:00
soumik12345 857aad66fc update: docstring 2025-07-11 21:10:19 +05:30
soumik12345 b860edd8f5 update: test_from_google_gemini 2025-07-11 21:04:50 +05:30
soumik12345 ca86f6e64d chore: address feedback 2025-07-11 21:00:42 +05:30
Onuralp SEZER d002b8afbf fix: 🐞 remove unused class_id references in Detections class from_vlm method 2025-07-11 18:14:35 +03:00
Onuralp SEZER c613005f69 fix: 🐞 update Detections class to remove class_id return from from_moondream function 2025-07-11 18:10:50 +03:00
Onuralp SEZER 99415f1da1 test: 🧪 add parameterized tests for from_moondream function in test_vlm.py 2025-07-11 18:08:43 +03:00
Onuralp SEZER 656b9c6c89 fix: 🐞 update from_moondream function to remove class_id return and adjust return type 2025-07-11 18:08:33 +03:00
Onuralp SEZER d34f050642 feat: 🚀 implement resolution validation function and refactor related code 2025-07-11 17:41:52 +03:00
Onuralp SEZER 89f4242e6f docs: 📝 add usage examples for from_lmm with Moondream results in Detections class
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-11 17:30:29 +03:00
Onuralp SEZER f7d4da9b1d ci: 👷 update CI installation commands to use --group instead of --extra because of pep rule "pep-0735" 2025-07-11 17:18:12 +03:00
Onuralp SEZER 1034313ac2 feat: 🚀 exclude all dev extras from pypi package and only available to dev installations #pep-0735 2025-07-11 17:13:11 +03:00
pre-commit-ci[bot] a6d9550a9a fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-11 13:51:24 +00:00
Onuralp SEZERandSoumik Rakshit fd1bb5b4b2 Update supervision/detection/vlm.py
Co-authored-by: Soumik Rakshit <19soumik.rakshit96@gmail.com>
2025-07-11 16:49:58 +03:00
Piotr Skalski 8c581e4855 Merge pull request #1880 from roboflow/docs/cookbook-updates
chore: 🧹 removal of version constraint, using latest bbox annotator and removal of asset extra from installations
2025-07-11 14:10:32 +02:00
Onuralp SEZER bf2a67b85b chore: 🧹 update cookbook.html notebook versions to v0.26.0 2025-07-11 02:18:43 +02:00
hidara2000 d3a2012750 Merge branch 'roboflow:develop' into develop 2025-07-11 10:16:58 +10:00
hidara2000 0b00edc526 Remove redundant duplicated calls to spread_out_boxes 2025-07-11 10:14:07 +10:00
Onuralp SEZER fa98266914 chore: 🧹 removal of version constraint, using latest bbox annotator and removal of asset extra from installations
- Removed specific version constraint for `supervision` package in installation command.
- Updated references from `sv.BoundingBoxAnnotator` to `sv.BoxAnnotator` for consistency with the latest library changes.
- Removed asset extension of package installation because it is has been included into main package

Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-11 02:10:08 +02:00
hidara2000 d7e0dedf74 pull from main 2025-07-11 09:57:06 +10:00
Onuralp SEZER f90a94be2e chore: 🧹 drop asset extra from installation and clean up import in video download duplicate 2025-07-11 01:56:42 +02:00
Onuralp SEZER 5206b6cbbb docs: 📝 update sv and ultralytics packages and remove old BoundingBox annotator from cookbook for count objects notebook
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-11 01:11:46 +02:00
Onuralp SEZER 58aacc788d fix: 🐞 update Moondream result format fix and doc example code block fixed
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-11 00:03:04 +03:00
Onuralp SEZER 0343db7d95 fix: 🐞 update Moondream result format to remove label requirement in Detections class 2025-07-10 23:57:27 +03:00
Onuralp SEZER 7076b4da0c docs: 📝 add examples for using from_vlm with Moondream results in Detections class
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-10 23:54:38 +03:00
Onuralp SEZER e17e7d712f fix: 🐞 remove class_name from from_moondream return in Detections class 2025-07-10 23:30:33 +03:00
Onuralp SEZER 399d2efa59 fix: 🐞 update from_moondream function to remove label requirement and improve box denormalization 2025-07-10 23:07:56 +03:00
Onuralp SEZER 300426ed41 fix: 📝 remove deprecated Google Gemini flash preview support from Detections class 2025-07-10 21:03:42 +03:00
Piotr Skalski 20066174e5 Merge pull request #1879 from roboflow/fix-utils-page 2025-07-10 20:01:34 +02:00
James 413db5a1e5 fix broken page 2025-07-10 18:39:38 +01:00
Onuralp SEZER 9855927597 feat: 🚀 add support for Moondream in Detections class
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-10 20:32:50 +03:00
Onuralp SEZER 72bff07498 fix: 📝 update docstring for from_moondream function to comply with style guide 2025-07-10 20:29:41 +03:00
Onuralp SEZER 409ff28200 feat: 🚀 add initial support for Moondream in VLM enum and implement from_moondream function for sv.Detections
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-07-10 20:21:41 +03:00
Onuralp SEZER 5d2616093d feat: 🚀 add support for Google Gemini 2.5 detection processing 2025-07-10 19:45:02 +03:00
Onuralp SEZER 74ba99479c chore: 🧹 clean up imports and improve formatting in Google Gemini functions 2025-07-10 19:44:48 +03:00
Onuralp SEZER 0e8ec18c20 fix: 🐞 remove not exist Google Gemini 2.0 and 2.5 flash preview mappings 2025-07-10 19:39:00 +03:00
Onuralp SEZER 7ca52da776 feat: 🚀 add support for Google Gemini 2.5 bounding box and mask parsing 2025-07-10 19:38:35 +03:00
Piotr Skalski 2dfadfe1b1 Merge pull request #1876 from roboflow/fix/google-gemini-support
update: google gemini support
2025-07-10 18:21:56 +02:00
SkalskiP 8b39478913 fix malfunctioned docstring 2025-07-10 18:18:38 +02:00
Soumik Rakshit 2c0eaa1059 update: docstrings 2025-07-10 14:02:01 +00:00
pre-commit-ci[bot] 4804d51de4 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-10 13:49:03 +00:00
soumik12345 097af2a38a add: qwen example 2025-07-10 19:18:24 +05:30
pre-commit-ci[bot] 9cc6d2d325 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-10 13:13:43 +00:00
soumik12345 b4f30b5ad6 update: docstrings 2025-07-10 18:41:59 +05:30
soumik12345 abb881c1a6 update: docstrings 2025-07-10 18:39:15 +05:30
soumik12345 6448fc7ea1 chore: address feedback on google gemini support 2025-07-10 18:32:18 +05:30
Piotr Skalski 98ba121b5c Merge pull request #1875 from roboflow/fix-wrapped-text
Fix wrapped `supervision` text in navigation bar
2025-07-10 12:43:44 +02:00
SkalskiP f50216eebf remove duplicated features from mkdocs.yaml 2025-07-10 12:10:10 +02:00
James 21a3584513 fix 2025-07-10 11:03:48 +01:00
pre-commit-ci[bot] 091559433a fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-10 09:55:06 +00:00
James b15a7ea005 fix wrapped text 2025-07-10 10:52:48 +01:00
Piotr Skalski 451b4b25d1 Merge pull request #1858 from roboflow/new-theme
New documentation theme
2025-07-10 11:39:23 +02:00
SkalskiP 4879ed38c8 include maestro link 2025-07-10 11:23:56 +02:00
Onuralp SEZER 096b9a5b99 Merge pull request #1792 from roboflow/feature/gemini-object-detection
🚀 from_vlm now has Google gemini 2D spatial understanding support for Detection class 🎯
2025-07-10 11:05:10 +03:00
pre-commit-ci[bot] 5467fbf7c2 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-10 07:08:54 +00:00
Ashp116 6e87237070 ADD: Added box_iou 2025-07-10 03:05:30 -04:00
James 796cc26fb9 fix version card alignment 2025-07-09 17:25:17 +01:00
Onuralp SEZER 174253715e fix: 🐞 update expected output in test_from_google_gemini for bbox coordinates 2025-07-09 19:23:18 +03:00
James 8373a38b35 fix conflict 2025-07-09 17:12:13 +01:00
Onuralp SEZER e608d8204f fix: 🐞 Google Gemini bbox order for normaliztion convert and add new enums for feature models to come 2025-07-09 19:04:19 +03:00
Onuralp SEZER ddfbaa3127 Merge pull request #1831 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-6.0.0
⬆️ Bump astral-sh/setup-uv from 5.4.2 to 6.3.1
2025-07-09 16:18:47 +03:00
Soumik Rakshit b5bf082a95 Merge pull request #1872 from roboflow/deprecate/DetectionDataset.images
deprecate(supervision): DetectionDataset.images
2025-07-09 18:46:47 +05:30
pre-commit-ci[bot] d48614d72b fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-09 13:13:54 +00:00
soumik12345 b736499fc9 deprecate: DetectionDataset.images 2025-07-09 18:35:04 +05:30
pre-commit-ci[bot] 031a0296f9 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-09 12:55:37 +00:00
Onuralp SEZER 84d7fb29e0 Merge branch 'develop' into feature/gemini-object-detection 2025-07-09 15:54:58 +03:00
Onuralp SEZER 0af46f6416 chore(setup-uv): 📦 update astral-sh/setup-uv to v6.3.1 across workflow files 2025-07-09 15:43:39 +03:00
Onuralp SEZER a64874f27d Merge pull request #1871 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-07-09 15:40:22 +03:00
pre-commit-ci[bot] e99fc921df fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-08 11:25:59 +00:00
James 0a7bf58905 respond to feedback 2025-07-08 12:25:35 +01:00
Piotr Skalski 334d0619e6 Merge pull request #1869 from roboflow/fix/docs/track_objects
fix(docs): Track Objects on Video example not retrieving class name correctly
2025-07-08 13:08:50 +02:00
Soumik Rakshit 1190ed2931 update: image.py 2025-07-08 16:35:59 +05:30
Soumik Rakshit ccf84d5653 update: image.py 2025-07-08 16:21:08 +05:30
Soumik Rakshit 8a905ce79a Merge branch 'develop' into fix/docs/track_objects 2025-07-08 16:12:17 +05:30
pre-commit-ci[bot] 724d851dcd chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/PyCQA/bandit: 1.8.5 → 1.8.6](https://github.com/PyCQA/bandit/compare/1.8.5...1.8.6)
- [github.com/astral-sh/ruff-pre-commit: v0.12.1 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.1...v0.12.2)
2025-07-07 17:34:37 +00:00
Piotr Skalski 95d7204ae8 Merge pull request #1834 from rafaelpadilla/fix/mAP
Fix/mAP
2025-07-07 15:43:44 +02:00
pre-commit-ci[bot] 5aa6b6f959 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-07 13:30:30 +00:00
SkalskiP fcb47f7226 mkdocs update + pre-commit fix 2025-07-07 15:30:05 +02:00
Hao Sun f47f032b23 Merge branch 'roboflow:develop' into develop 2025-07-07 15:27:29 +08:00
pre-commit-ci[bot] 0b120f1748 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-07 07:21:58 +00:00
AI-Hao 13e857cf00 refactor(detection): 重构合并检测对象的逻辑
- 移除 merge_inner_detections_objects 函数中的 threshold 和 match_metric 参数
- 新增 merge_inner_detections_objects_without_iou 函数,用于合并检测对象
- 优化非最大值抑制(NMM)的逻辑,提高效率
- 调整 mask_iou_batch 函数的实现,简化代码
2025-07-07 15:21:28 +08:00
rafaelpadilla b867968a10 breaking long lines, preventing E501. 2025-07-06 03:33:30 +00:00
rafaelpadilla a95a818441 Including function get_coco_class_index_mapping in supervision.__init__.py.
Unifying default value for parameter `use_iscrowd`.
Adding detailed docstrings to function `get_coco_class_index_mapping`.
2025-07-06 03:02:07 +00:00
rafaelpadilla 03430699f9 Expanded all test cases in test_coco_annotations_to_detections including use_iscrowd=True and use_iscrowd=False. 2025-07-06 02:07:52 +00:00
rafaelpadilla c7b4993721 Moving _jaccard and box_iou_batch_with_jaccard to supervision/detection/utils.py. 2025-07-06 01:31:30 +00:00
Rafael PadillaandPiotr Skalski d543be924f Update supervision/dataset/formats/coco.py
Co-authored-by: Piotr Skalski <piotr.skalski92@gmail.com>
2025-07-05 21:41:02 -03:00
soumik12345 2ef9d69e01 chore: make pre-commit happy 2025-07-04 17:07:53 +05:30
soumik12345 3786017424 fix: Track Objects on Video example not retrieving class name correctly 2025-07-04 17:01:05 +05:30
Onuralp SEZER a6f738d2d1 Merge pull request #1867 from JESUSROYETH/fix/typo-xyxy_to_xcycarh
fix: typo in __all__ (xyxy_to_xcycarh)
2025-07-03 23:11:12 +03:00
JESUSROYETH 1facc6b28b fix: correct export name xyxy_to_xyah -> xyxy_to_xcycarh in __all__ 2025-07-03 15:43:10 -04:00
pre-commit-ci[bot] 4414e15a00 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-07-01 23:19:27 +00:00
rafaelpadilla 49a8fd96d6 renaming iou_with_jaccard(...) to box_iou_batch_with_jaccard(...) and moving it to supervision.__init__.py 2025-07-01 23:18:47 +00:00
rafaelpadilla 0a55b3b3a2 making mean_average_precision.py have a lazy import of box_iou_batch_with_jaccard(...) 2025-07-01 23:17:48 +00:00
rafaelpadilla 5f9c55d9f3 keeping argument use_iscrowd in function load_coco_annotations(...) ; moving box_iou_batch_with_jaccard(...) to supervision/__init__.py 2025-07-01 23:16:27 +00:00
Onuralp SEZER 93c1b5f520 Merge pull request #1862 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-06-30 20:21:50 +03:00
pre-commit-ci[bot] 097614f2be chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/PyCQA/bandit: 1.8.4 → 1.8.5](https://github.com/PyCQA/bandit/compare/1.8.4...1.8.5)
- [github.com/astral-sh/ruff-pre-commit: v0.11.13 → v0.12.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.13...v0.12.1)
2025-06-30 17:21:08 +00:00
AI-Hao eb170bc393 ci:取消注释 GitHub App token 步骤
取消注释了 publish-docs.yml 文件中的 Create GitHub App token (mkdocs) 步骤。这个步骤现在将作为工作流程的一部分正常运行,不再被跳过。
2025-06-25 11:02:17 +08:00
AI-Hao d002858169 ci: 注释掉创建 GitHub App token 的步骤
暂时注释掉创建 GitHub App token 的步骤,可能是因为该步骤不再需要或出现了问题。这个修改不影响其他功能,只是减少了工作流中的一个步骤。
2025-06-25 10:56:50 +08:00
pre-commit-ci[bot] 646ac83bef fix(pre_commit): 🎨 auto format pre-commit hooks 2025-06-25 01:05:00 +00:00
Hao Sun 9a9324af9a Merge branch 'roboflow:develop' into develop 2025-06-25 09:04:37 +08:00
pre-commit-ci[bot] c2d0ed2365 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-06-18 21:23:04 +00:00
James 89ca7226b9 Merge branch 'develop' into new-theme 2025-06-18 17:20:33 -04:00
James 5313f479a4 fix kapa widget 2025-06-17 17:12:24 -04:00
James 568a94c0e1 fix kapa 2025-06-17 17:10:07 -04:00
James 463a54fb58 work on mobile styles 2025-06-17 16:08:45 -04:00
James d5f06eaf6f work on search styles 2025-06-17 14:55:56 -04:00
James 4255e63269 work on new theme 2025-06-17 09:34:23 -04:00
Onuralp SEZER 57975735b3 Merge pull request #1854 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-06-17 11:34:04 +03:00
pre-commit-ci[bot] 84d190a40c chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/PyCQA/bandit: 1.8.3 → 1.8.4](https://github.com/PyCQA/bandit/compare/1.8.3...1.8.4)
- [github.com/astral-sh/ruff-pre-commit: v0.11.11 → v0.11.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.11...v0.11.13)
2025-06-16 17:18:16 +00:00
rafaelpadilla fd3135145a renaming and reordering inputs of function to keep consistency with other functions 2025-06-01 17:21:45 +00:00
rafaelpadilla cff974555e 1) Simplifying the logic of use_iscrowd and compatibility with other datasets.
2) Making `get_coco_class_index_mapping` return the inversed mapping, to simplify its usage.
2025-06-01 15:52:01 +00:00
Onuralp SEZER 14b6d104df Merge pull request #1852 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-05-31 03:51:40 +03:00
pre-commit-ci[bot] d21ebc77cc chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.10 → v0.11.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.10...v0.11.11)
2025-05-26 17:24:02 +00:00
Onuralp SEZER 95f2b54cc8 Merge pull request #1848 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-05-20 23:14:03 +03:00
pre-commit-ci[bot] 9f67fb9f5e chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.9 → v0.11.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.9...v0.11.10)
2025-05-19 17:24:35 +00:00
Onuralp SEZER 3f99fde52d Merge pull request #1841 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-05-12 20:26:35 +03:00
pre-commit-ci[bot] bfe11b3f8e chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.8 → v0.11.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.8...v0.11.9)
2025-05-12 17:23:07 +00:00
pre-commit-ci[bot] 52980a6aa7 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-05-08 01:52:48 +00:00
rafaelpadilla 8f72e49080 Moving iou_with_jaccard and jaccard from mean_average_precision.py to detection/utils.py 2025-05-08 01:46:46 +00:00
rafaelpadilla 19c4e44e2c removing unnecessary flag 2025-05-07 22:10:15 +00:00
rafaelpadilla 790baa615f Removing spaces 2025-05-07 22:05:04 +00:00
rafaelpadilla bba43ecdf4 Updating docstring to reflect newly added arguments 2025-05-07 20:31:05 +00:00
rafaelpadilla 688d987765 replacing __str__ implementation with to_pycocotools_output 2025-05-07 20:28:39 +00:00
Onuralp SEZER 8b92485b6a Merge pull request #1837 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-05-06 12:55:01 +03:00
pre-commit-ci[bot] 2a3c9c9164 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.7 → v0.11.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.7...v0.11.8)
2025-05-05 17:27:00 +00:00
Onuralp SEZER 5e3573cf84 Merge pull request #1835 from roboflow/dependabot/github_actions/develop/actions/create-github-app-token-2.0.6
⬆️ Bump actions/create-github-app-token from 2.0.2 to 2.0.6
2025-05-05 03:37:37 +03:00
dependabot[bot] 4031a7f3df ⬆️ Bump actions/create-github-app-token from 2.0.2 to 2.0.6
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 2.0.2 to 2.0.6.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5...df432ceedc7162793a195dd1713ff69aefc7379e)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-version: 2.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-05 00:07:03 +00:00
rafaelpadilla 15cd445108 Removing unnecessary comments and including references. 2025-04-28 23:28:26 +00:00
Onuralp SEZER ed3186c506 Merge pull request #1833 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-04-29 02:11:04 +03:00
rafaelpadilla 157ed3af06 fix data default value 2025-04-28 23:08:37 +00:00
rafaelpadilla 36a21717eb pre-commit (lint) fixes 2025-04-28 22:11:32 +00:00
rafaelpadilla 232916a8eb implementing mean average precision using COCO approach 2025-04-28 20:16:07 +00:00
rafaelpadilla 317cbd3fc4 preparing coco dataset with tags area and iscrowd 2025-04-28 20:12:06 +00:00
pre-commit-ci[bot] 1bfc67bed7 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.6 → v0.11.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.6...v0.11.7)
2025-04-28 17:22:17 +00:00
Onuralp SEZER 1c795e4a9f ci(env): 🐞 astral-sh/setup-uv new parameter activate-environment: true added
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-04-28 16:14:16 +03:00
dependabot[bot] 087dc939b2 ⬆️ Bump astral-sh/setup-uv from 5.4.2 to 6.0.0
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5.4.2 to 6.0.0.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86...c7f87aa956e4c323abf06d5dec078e358f6b4d04)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 01:00:17 +00:00
SkalskiP 86a13d0f87 bump version from 0.26.0rc6 to 0.26.0rc7 2025-04-25 14:56:18 +02:00
Piotr Skalski 21fc9afbdf Merge pull request #1829 from roboflow/fix/process_video
fix: `UnboundLocalError` in `process_video`
2025-04-25 14:55:29 +02:00
hidara2000 0c2aae6bd2 refactor(snap_boxes): enhance docstring and improve bounding box shifting logic 2025-04-25 09:48:47 +10:00
pre-commit-ci[bot] a6aa9b7d3b fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-24 23:33:17 +00:00
hidara2000 29695055d2 refactor(annotators): streamline label handling and improve box snapping logic 2025-04-25 09:32:54 +10:00
soumik12345 00df1cbb04 fix: UnboundLocalError 2025-04-25 02:29:08 +05:30
Piotr Skalski 1876019faf Merge branch 'develop' into develop 2025-04-23 09:13:08 +02:00
pre-commit-ci[bot] 95a2ecc49b fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-17 01:02:48 +00:00
hidara2000 5c35af99d0 fix long comment lines 2025-04-17 11:02:25 +10:00
pre-commit-ci[bot] c68218a07e fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-17 00:48:27 +00:00
hidara2000 0539ec9d1f feat(annotators): add max_line_length parameter and text wrapping functionality 2025-04-17 10:48:02 +10:00
hidara2000 c4dce2752d fix(annotators): add missing comma in annotate method signature 2025-04-15 22:09:51 +10:00
hidara2000andOnuralp SEZER 474c8bc478 Update supervision/annotators/core.py
Co-authored-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-04-15 21:58:31 +10:00
hidara2000andOnuralp SEZER a5c833b80f Update supervision/annotators/core.py
Co-authored-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-04-15 21:58:20 +10:00
hidara2000andOnuralp SEZER a1e43f8e93 Update supervision/annotators/core.py
Co-authored-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-04-15 21:58:06 +10:00
pre-commit-ci[bot] ca5596ceb2 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-15 08:30:30 +00:00
hidara2000 f2e900171e feat(annotators): enhance label annotators with frame boundary adjustments and new base class
- ensures labels are within frame
- May have a few overlaps at edges,in very busy frames, when smart_pos is enabled. but running smart_pos  first yields better results
2025-04-15 18:09:08 +10:00
SkalskiP f737782ae8 initial commit 2025-04-07 14:56:58 +02:00
Onuralp SEZER 1f692a043f Merge branch 'develop' into feature/gemini-object-detection 2025-03-22 21:33:56 +03:00
Onuralp SEZER 7f1e0ea36b Merge branch 'develop' into feature/gemini-object-detection 2025-02-24 06:37:26 +03:00
Onuralp SEZER 0c4a156662 feat: ✨ implement normalized_xyxy_to_absolute_xyxy function and integrate into Google Gemini processing 2025-02-19 18:14:17 +03:00
Onuralp SEZER 766467ab78 docs(refactor): ♻️ rename variables for clarity in detection module 2025-02-19 08:44:51 +03:00
Onuralp SEZER 0cec129cf0 style: 💄 improve code formatting and readability in various files 2025-02-19 08:29:41 +03:00
Onuralp SEZER 65b48f6b4a feat: ✨ add support for Google Gemini model in detection module
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-02-19 08:29:05 +03:00
SunHao-AI 39766f4c0a Merge branch 'roboflow:develop' into develop 2025-01-16 11:09:47 +08:00
pre-commit-ci[bot] 4679334d86 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-01-09 12:22:20 +00:00
AI-Hao 8d29796810 Merge remote-tracking branch 'origin/develop' into develop 2025-01-09 20:03:57 +08:00
AI-Hao 9cd6549cdc feat(detection): Support for IOS Matching Metric
- Added the `match_metric` parameter to the `with_nms` and `with_nmm` methods in the `Detections` class.
- Modified the `box_non_max_suppression` and `box_non_max_merge` functions to support IOS calculation.
- Introduced the `mask_non_max_merge` function for handling non-maximum merging of masks.
- Updated the `box_iou_batch` and `mask_iou_batch` functions to support both IOU and IOS calculations.
- Enhanced the `InferenceSlicer` class to accommodate the IOS matching metric.

Notes
- IOS (Intersection over Smaller): A variation of IOU that compares intersection over the smaller area, useful in scenarios with varying object sizes.
- Refinements: Improved terminology for clarity and consistency, ensuring technical accuracy.
2025-01-09 20:03:31 +08:00
AI-Hao e4b5a8e0f9 ### feat(detection): Support for IOS Matching Metric**
- Added the `match_metric` parameter to the `with_nms` and `with_nmm` methods in the `Detections` class.
- Modified the `box_non_max_suppression` and `box_non_max_merge` functions to support IOS calculation.
- Introduced the `mask_non_max_merge` function for handling non-maximum merging of masks.
- Updated the `box_iou_batch` and `mask_iou_batch` functions to support both IOU and IOS calculations.
- Enhanced the `InferenceSlicer` class to accommodate the IOS matching metric.

### Notes
- IOS (Intersection over Smaller): A variation of IOU that compares intersection over the smaller area, useful in scenarios with varying object sizes.
- Refinements: Improved terminology for clarity and consistency, ensuring technical accuracy.
2025-01-09 20:00:32 +08:00
442 changed files with 94499 additions and 30425 deletions
+41
View File
@@ -0,0 +1,41 @@
# see https://docs.codecov.io/docs/codecov-yaml
# Validation check:
# $ curl --data-binary @.codecov.yml https://codecov.io/validate
# https://docs.codecov.io/docs/codecovyml-reference
codecov:
bot: "codecov-io"
strict_yaml_branch: "yaml-config"
require_ci_to_pass: yes
notify:
# after_n_builds: 2
wait_for_ci: yes
coverage:
precision: 0 # 2 = xx.xx%, 0 = xx%
round: nearest # how coverage is rounded: down/up/nearest
range: 40...100 # custom range of coverage colors from red -> yellow -> green
status:
project:
default:
informational: true
target: 95% # specify the target coverage for each commit status
threshold: 10% # allow this little decrease on project
# branches: master
if_ci_failed: error
patch:
default:
informational: true
target: 95% # enforce same coverage target for new/changed code as the project
threshold: 10% # allow only a small decrease on patch coverage
changes: false
# https://docs.codecov.com/docs/github-checks#disabling-github-checks-patch-annotations
github_checks:
annotations: false
comment:
layout: header, diff
require_changes: false
behavior: default # update if exists else create new
# branches: *
+1 -1
View File
@@ -1,4 +1,4 @@
# These owners will be the default owners for everything in
# the repo. They will be requested for review when someone
# opens a pull request.
* @SkalskiP @onuralpszr
* @SkalskiP @soumik12345
+85
View File
@@ -0,0 +1,85 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at community-reports@roboflow.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][mozilla coc].
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][faq]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
[faq]: https://www.contributor-covenant.org/faq
[homepage]: https://www.contributor-covenant.org
[mozilla coc]: https://github.com/mozilla/diversity
[translations]: https://www.contributor-covenant.org/translations
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+506
View File
@@ -0,0 +1,506 @@
# Contributing to Supervision 🛠️
Thank you for your interest in contributing to Supervision!
We are actively improving this library to reduce the amount of work you need to do to solve common computer vision problems.
## Code of Conduct
Please read and adhere to our [Code of Conduct](https://supervision.roboflow.com/latest/code_of_conduct/). This document outlines the expected behavior for all participants in our project.
## Table of Contents
- [Contribution Guidelines](#contribution-guidelines)
- [Contributing Features](#contributing-features)
- [API Design Principles](#api-design-principles)
- [How to Contribute Changes](#how-to-contribute-changes)
- [Installation for Contributors](#installation-for-contributors)
- [Code Style and Quality](#code-style-and-quality)
- [Pre-commit tool](#pre-commit-tool)
- [Docstrings](#docstrings)
- [Type checking](#type-checking)
- [Documentation](#documentation)
- [Cookbooks](#cookbooks)
- [Tests](#tests)
- [License](#license)
## Contribution Guidelines
We welcome contributions to:
1. Add a new feature to the library (guidance below).
2. Improve our documentation and add examples to make it clear how to leverage the supervision library.
3. Report bugs and issues in the project.
4. Submit a request for a new feature.
5. Improve our test coverage.
### Contributing Features ✨
Supervision is designed to provide generic utilities to solve problems. Thus, we focus on contributions that can have an impact on a wide range of projects.
For example, counting objects that cross a line anywhere on an image is a common problem in computer vision, but counting objects that cross a line 75% of the way through is less useful.
Before you contribute a new feature, consider submitting an Issue to discuss the feature so the community can weigh in and assist.
### API Design Principles
Supervision APIs should remain generic, composable, and predictable across model families. Before adding a new integration, annotator option, or data conversion method, check the existing `sv.Detections`, `sv.KeyPoints`, and annotator patterns and follow these principles:
1. **Model integrations normalize raw external outputs into existing Supervision containers.** Use `sv.Detections` for detection, segmentation, and other instance-level predictions that include boxes, masks, class ids, confidence scores, or extra per-instance fields. Use `sv.KeyPoints` for standalone keypoint or pose predictions when keypoints exist independently of detection boxes (e.g. pure pose estimation, landmark detection on pre-cropped images). Use `Detections.keypoints` when keypoints are always co-incident with boxes from the same model — the field stores an `(n, K, 2)` or `(n, K, 3)` array where the optional third channel is per-point confidence in `[0, 1]`.
2. **Do not add a `from_<model>` method when the model already returns a Supervision object.** `from_*` methods are for converting raw outputs from external packages such as Ultralytics, Transformers, Inference, or MediaPipe. If a model's `predict()` method already returns `sv.Detections`, keep that result type and store additional structured payloads in `detections.data` or `detections.metadata` using documented keys.
3. **Annotators render data; filtering and visibility are container state.** Filtering by confidence, class id, tracker id, geometry, or custom data should happen before annotation through the container slicing APIs, for example `detections[detections.confidence > 0.7]` or `key_points[key_points.confidence > 0.5]`. Per-point presentation state, such as a `KeyPoints.visible` mask, may live on the container and be honored consistently by annotators.
4. **Annotator constructor arguments should describe visual presentation, not model-quality gates.** Use constructor arguments for color, thickness, opacity, text, position, style, and generic visualization parameters such as sigma levels. Annotators may skip invalid geometry defensively, including missing points, zero-area boxes, non-finite coordinates, or points marked invisible on the container. They should not introduce confidence thresholds or model-specific quality gates as rendering options.
## How to Contribute Changes
First, fork this repository to your own GitHub account. Click "fork" in the top corner of the `supervision` repository to get started:
![Forking the repository](https://media.roboflow.com/fork.png)
![Creating a repository fork](https://media.roboflow.com/create_fork.png)
Then, run `git clone` to download the project code to your computer.
You should also set up `roboflow/supervision` as an "upstream" remote (that is, tell git that the reference Supervision repository was the source of your fork of it):
```bash
git remote add upstream https://github.com/roboflow/supervision.git
git fetch upstream
```
Move to a new branch using the `git checkout` command:
```bash
git checkout -b <scope>/<your_branch_name> upstream/develop
```
The name you choose for your branch should describe the change you want to make and start with an appropriate prefix:
- `feat/`: for new features (e.g., `feat/line-counter`)
- `fix/`: for bug fixes (e.g., `fix/memory-leak`)
- `docs/`: for documentation changes (e.g., `docs/update-readme`)
- `chore/`: for routine tasks, maintenance, or tooling changes (e.g., `chore/update-dependencies`)
- `test/`: for adding or modifying tests (e.g., `test/add-unit-tests`)
- `refactor/`: for code refactoring (e.g., `refactor/simplify-algorithm`)
Make any changes you want to the project code, then run the following commands to commit your changes:
```bash
git add -A
git commit -m "feat: add line counter functionality"
git push -u origin <your_branch_name>
```
Use conventional commit messages to clearly describe your changes. The format is:
```
<type>[optional scope]: <description>
```
Common types include:
- `feat`: A new feature
- `fix`: A bug fix
- `docs`: Documentation only changes
- `style`: Changes that do not affect the meaning of the code (white-space, formatting, etc)
- `refactor`: A code change that neither fixes a bug nor adds a feature
- `perf`: A code change that improves performance
- `test`: Adding missing tests or correcting existing tests
- `chore`: Changes to the build process or auxiliary tools and libraries
Then, go back to your fork of the `supervision` repository, click "Pull Requests", and click "New Pull Request".
![Opening a pull request](https://media.roboflow.com/open_pr.png)
Make sure the `base` branch is `develop` before submitting your PR.
On the next page, review your changes then click "Create pull request":
![Configuring a pull request](https://media.roboflow.com/create_pr_submit.png)
Next, write a description for your pull request, and click "Create pull request" again to submit it for review:
![Submitting a pull request](https://media.roboflow.com/write_pr.png)
When creating new functions, please ensure you have the following:
1. Docstrings for the function and all parameters.
2. Unit tests for the function.
3. Examples in the documentation for the function.
4. Created an entry in our docs to autogenerate the documentation for the function.
5. Please share a Google Colab with minimal code to test a new feature or reproduce the issue whenever possible. Please ensure that Google Colab can be accessed without any restrictions.
When you submit your Pull Request, you will be asked to sign a Contributor License Agreement (CLA) by the `cla-assistant` GitHub bot. We can only respond to PRs from contributors who have signed the project CLA.
All pull requests will be reviewed by the maintainers of the project. We will provide feedback and ask for changes if necessary.
PRs must pass all tests and linting requirements before they can be merged.
## Installation for Contributors
Before starting your work on the project, set up your development environment:
1. **Clone your fork of the project:**
**Option A: Recommended for most contributors (shallow clone of develop branch):**
```bash
git clone --depth 1 -b develop https://github.com/YOUR_USERNAME/supervision.git
cd supervision
```
Replace `YOUR_USERNAME` with your GitHub username.
> **Note**: Using `--depth 1` creates a shallow clone with minimal history and `-b develop` ensures you start with the development branch. This significantly reduces download size while providing everything needed to contribute.
**Option B: Full repository clone (if you need complete history):**
```bash
git clone https://github.com/YOUR_USERNAME/supervision.git
cd supervision
git checkout develop
```
2. **Set up the upstream remote:**
```bash
git remote add upstream https://github.com/roboflow/supervision.git
git fetch upstream
```
3. **Create and activate a virtual environment:**
**On Linux/macOS:**
```bash
python3 -m venv .venv
source .venv/bin/activate
```
**On Windows:**
```cmd
python -m venv .venv
.venv\Scripts\activate
```
4. **Install `uv`:**
Follow the instructions on the [uv installation page](https://docs.astral.sh/uv/getting-started/installation/).
5. **Install project dependencies:**
```bash
uv pip install -r pyproject.toml --group dev --group docs --extra metrics
```
6. **Verify the setup:**
```bash
uv run pytest
```
## 🎨 Code Style and Quality
### Pre-commit tool
This project uses the [pre-commit](https://pre-commit.com/) tool to maintain code quality and consistency. Before submitting a pull request or making any commits, it is important to run the pre-commit tool to ensure that your changes meet the project's guidelines.
Furthermore, we have integrated a pre-commit GitHub Action into our workflow. This means that with every pull request opened, the pre-commit checks will be automatically enforced, streamlining the code review process and ensuring that all contributions adhere to our quality standards.
To run the pre-commit tool, follow these steps:
1. **Install pre-commit** (already included if you followed the installation steps above):
```bash
uv sync --group dev
```
2. **Navigate to the project's root directory** (if not already there).
3. **Run pre-commit checks**:
```bash
uv run pre-commit run --all-files
```
This will execute the pre-commit hooks configured for this project. If any issues are found, the pre-commit tool will provide feedback on how to resolve them. Make the necessary changes and re-run the command until all issues are resolved.
4. **Install pre-commit as a git hook** (optional but recommended):
```bash
uv run pre-commit install
```
This will automatically run pre-commit checks every time you make a `git commit`.
### Docstrings
All new functions and classes in `supervision` should include docstrings. This is a prerequisite for any new functions and classes to be added to the library.
`supervision` adheres to the [Google Python docstring style](https://google.github.io/styleguide/pyguide.html#383-functions-and-methods). Please refer to the style guide while writing docstrings for your contribution.
Every docstring should include a usage example. When the example only uses `supervision`, NumPy, and the standard library — no optional extras, no external files or network access — strongly prefer `>>>` doctest format so it is automatically verified by the test suite. See [Doctests](#doctests) below for syntax guidance and for when fenced ```` ```python ```` blocks are appropriate instead.
### Type checking
Type hints are required on all new code. mypy is enforced by the pre-commit hook configured in `.pre-commit-config.yaml` — your PR will fail CI if mypy reports errors.
### Readability
Avoid multi-branch conditional expressions inside function or constructor arguments. If an argument needs more than a simple `a if condition else b`, assign it to a named local variable before the call.
### Performance
- Avoid unnecessary copies of NumPy arrays.
- Prefer vectorized operations over Python loops in hot paths.
- Lazy-import heavy framework dependencies (`torch`, `transformers`, `ultralytics`) inside the function that needs them — never at module top level.
### Deprecation policy
**Minimum window**: deprecated APIs must remain for at least **3 minor releases** before removal. Example: deprecated in `0.29.0` → removed in `0.32.0`.
Use the appropriate mechanism depending on what is being deprecated:
- **Module-level alias**: `supervision.utils.internal.warn_deprecated` in the deprecated module's `__init__.py`
- **Renamed parameter**: `supervision.utils.internal.deprecated_parameter` decorator
- **Public function, method, or class**: `@deprecated` from `pydeprecate`
Always specify both the deprecation version and the planned removal version in the message or decorator arguments.
### Deprecated module aliases
`supervision.keypoint` is deprecated since `0.27.0` and will be removed in `0.30.0`. Always import from `supervision.key_points`:
```python
from supervision.key_points import KeyPoints # correct
```
## 📝 Documentation
The `supervision` documentation is stored in a folder called `docs`. The project documentation is built using `mkdocs`.
To run the documentation locally:
1. **Install documentation dependencies** (if not already installed):
```bash
uv sync --group docs
```
2. **Start the documentation server**:
```bash
uv run mkdocs serve
```
3. **Access the documentation** at `http://127.0.0.1:8000` in your browser.
You can learn more about mkdocs on the [mkdocs website](https://www.mkdocs.org/).
## 🧑‍🍳 Cookbooks
We are always looking for new examples and cookbooks to add to the `supervision` documentation. If you have a use case that you think would be helpful to others, please submit a PR with your example. Here are some guidelines for submitting a new example:
- Create a new notebook in the [`docs/notebooks`](https://github.com/roboflow/supervision/tree/develop/docs/notebooks) folder.
- Add a link to the new notebook in [`docs/theme/cookbooks.html`](https://github.com/roboflow/supervision/blob/develop/docs/theme/cookbooks.html). Make sure to add the path to the new notebook, as well as a title, labels, author and supervision version.
- Use the [Count Objects Crossing the Line](https://supervision.roboflow.com/develop/notebooks/count-objects-crossing-the-line/) example as a template for your new example.
- Pin the version of `supervision` you are using in the notebook.
- Place an appropriate "Open in Colab" button at the top of the notebook. You can find an example of such a button in the aforementioned `Count Objects Crossing the Line` cookbook.
- **Notebook should be self-contained**. If you rely on external data (videos, images, etc.) or libraries, include download and installation commands in the notebook.
- Annotate the code with appropriate comments, including links to the documentation describing each of the tools you have used.
## 🧪 Tests
[`pytest`](https://docs.pytest.org/en/7.1.x/) is used to run our tests.
To run tests:
```bash
uv run pytest
```
To run tests with coverage:
```bash
uv run pytest --cov=supervision
```
### Test Structure
Follow **Arrange-Act-Assert (AAA)**: one setup block, one action, one assertion group per test. Never put two independent actions in the same test.
**Class grouping:** Group related tests into a class. The class name carries the unit under test; method names describe the expected outcome only — not the mechanism.
```python
class TestDetectionsWithNms:
def test_keeps_highest_confidence_detection(self): ...
def test_suppresses_lower_score_when_overlap_exceeds_threshold(self): ...
def test_raises_when_confidence_missing(self): ...
```
**Parametrize aggressively:** Three or more structurally identical tests should become a single `@pytest.mark.parametrize` case. Use `pytest.param(..., id="slug")` per case — not `ids=[...]` on the decorator — so the ID stays co-located with its arguments and survives reordering.
```python
@pytest.mark.parametrize(
("overlap_metric", "expected_keep"),
[
pytest.param(OverlapMetric.IOU, [True, True], id="iou-keeps-both"),
pytest.param(OverlapMetric.IOS, [True, False], id="ios-suppresses-small"),
],
)
def test_overlap_metric_determines_suppression(
overlap_metric: OverlapMetric, expected_keep: list[bool]
) -> None:
"""Small box inside large: IOU keeps both; IOS suppresses small."""
...
```
**Docstrings:** Every test function/method requires at minimum a one-line docstring (within the project line length configured in `pyproject.toml`). Describe the scenario, not the implementation.
### Doctests
**Guidance:** when an example uses only `supervision`, NumPy, and the standard library — no optional extras (e.g. no `--extra metrics` packages), no external files, no network, no devices — prefer `>>>` doctest format so it is automatically verified by the test suite. Fenced ```` ```python ```` blocks are appropriate when the example cannot reasonably be executed (e.g. loading a third-party model, reading a video file) or when the primary purpose is demonstrating error/exception behaviour rather than return values.
Doctests run automatically as part of the test suite via `--doctest-modules` in `pyproject.toml`. The `ELLIPSIS` and `NORMALIZE_WHITESPACE` flags are enabled globally, so `...` matches any output fragment and minor whitespace differences are ignored.
```bash
uv run pytest --doctest-modules src/
```
**Writing a doctest**
Use the `Example:` section of a Google-style docstring. Prefix each input line with `>>>` and each continuation line with `...`. Place expected output immediately after the last input line with no blank line between them.
```python
def clip_boxes(xyxy: np.ndarray, resolution_wh: tuple) -> np.ndarray:
"""Clip bounding boxes to frame boundaries.
Args:
xyxy: Box coordinates as (N, 4) float array.
resolution_wh: Frame size as (width, height).
Returns:
Clipped boxes as (N, 4) float array.
Example:
>>> import numpy as np
>>> import supervision as sv
>>> boxes = np.array([[-10, -5, 120, 80]], dtype=np.float32)
>>> sv.clip_boxes(boxes, resolution_wh=(100, 60))
array([[ 0., 0., 100., 60.]], dtype=float32)
"""
```
### Key rules
- **Single-line expression** — write the repr as expected output: `>>> len(result)` → `1`
- **Multi-line statement** — use `...` continuation: `>>> arr = np.array([` / `... [1, 2],` / `... ])`
- **Print output** — write the printed string as expected output (no quotes).
- **`None` return** — no output line needed (suppress with assignment or `_ =`).
- **Large/variable arrays** — use `ELLIPSIS`: `array([...])` matches any content.
- **`# doctest: +SKIP`** — use only as a last resort for genuinely non-runnable lines (e.g. a GPU-only call inside an otherwise runnable example). Prefer splitting the example into two blocks instead.
Fenced ```` ```python ```` blocks remain appropriate for:
- Examples that import optional extras (`supervision[metrics]`, `torch`, `ultralytics`).
- Examples that read files, capture video, or require a running service.
- Illustrative pseudocode that is intentionally incomplete.
## 🔍 PR Review Guidelines
These guidelines help reviewers provide consistent, actionable feedback efficiently. Your goals: validate completeness, identify risks, provide actionable feedback, and highlight quality gaps.
### Overall Recommendation
Start with a clear recommendation using these levels:
- 🟢 **Approve** — Ready to merge
- 🟡 **Minor Suggestions** — Improvements recommended but not blocking
- 🟠 **Request Changes** — Must address issues before merge
- 🔴 **Block** — Critical issues require major rework
Example: `🟠 Request Changes — Missing unit tests for PolygonMerger and no mkdocs entry.`
### PR Completeness
Verify requirements are met (✅ Complete / ⚠️ Incomplete / ❌ Missing / 🔵 N/A):
- [ ] Clear description of what changed and why
- [ ] Tests added/updated for new functionality or bug fixes
- [ ] Docstrings follow [Google-style](https://google.github.io/styleguide/pyguide.html#383-functions-and-methods)
- [ ] Docs entry added to mkdocs (new functions/classes only)
- [ ] Google Colab provided (if demonstrating feature/fix)
- [ ] Screenshots/videos included (visual changes only)
Call out missing items explicitly in your review.
### Quality Scores
Use **n/5 scoring** with inline code comments for specifics:
**Code Quality (n/5):**
- 5/5 🟢 Excellent — 4/5 🟢 Good — 3/5 🟡 Acceptable — 2/5 🟠 Needs Work — 1/5 🔴 Poor
- Check: correctness (edge cases, None checks, bounds), Python best practices (idiomatic patterns, error handling, type hints), project conventions (docstrings, linting, import order, PEP 8 naming)
**Testing (n/5):**
- 5/5 🟢 Comprehensive — 4/5 🟢 Good — 3/5 🟡 Adequate — 2/5 🟠 Insufficient — 1/5 🔴 Missing
- Verify: unit tests for new code, edge cases covered, specific assertions, realistic scenarios, clear test names
**Documentation (n/5):**
- 5/5 🟢 Excellent — 4/5 🟢 Good — 3/5 🟡 Adequate — 2/5 🟠 Insufficient — 1/5 🔴 Missing
- Confirm: docstrings for public functions/classes, parameters/returns/exceptions documented, usage examples, mkdocs integration, changelog entry for user-facing changes
### Risk Assessment
Flag risks with severity (5/5 🔴 Critical — 4/5 🟠 High — 3/5 🟡 Medium — 2/5 🟢 Low — 1/5 🟢 Negligible):
**Common risk categories:**
1. **Breaking changes** — API changes, removed features, behavior modifications (must include migration guide)
2. **Performance** — Inefficient algorithms, memory-intensive operations, bottlenecks
3. **Compatibility** — New Python/dependency requirements, platform-specific code
4. **Security** — Unvalidated input, code execution risks, data exposure
### Review Summary Template
```markdown
## Review Summary
**Recommendation:** [emoji] [Status] — [justification]
**PR Completeness:**
- ✅ Complete: [items]
- ❌ Missing: [gaps]
**Quality Scores:**
- Code: n/5 [emoji] — [reason]
- Testing: n/5 [emoji] — [reason]
- Documentation: n/5 [emoji] — [reason]
**Risk Level:** n/5 [emoji] — [description]
**Critical Issues (Must Fix):**
1. [Issue] — See comment on `file.py`
**Suggestions (Optional):**
1. [Improvement] — See suggestion on `file.py`
**Next Steps:**
1. [Action item]
```
### Review Best Practices
**DO:** Use inline GitHub comments with suggestions, explain *why* (not just *what*), distinguish blocking vs. nice-to-have, acknowledge good work, run linter if needed (`uv run pre-commit run --all-files`)
**DON'T:** Mention line numbers in summary (use inline comments), give vague feedback, nitpick style (defer to tools), assume knowledge of conventions, block on minor issues
**Tone:** Be respectful, specific, pragmatic, and consistent. Focus on actionable feedback that moves PRs toward merge.
## 📄 License
By contributing, you agree that your contributions will be licensed under an [MIT license](../LICENSE.md).
+33 -30
View File
@@ -1,65 +1,68 @@
name: 🐞 Bug Report
# title: " "
description: Problems with Supervision
title: "[Bug]: "
description: Report a bug or unexpected behavior in Supervision
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thank you for submitting a Supervision 🐞 Bug Report!
- type: checkboxes
attributes:
label: Search before asking
description: >
Please search the [issues](https://github.com/roboflow/supervision/issues) to see if a similar bug report already exists.
description: Please search [issues](https://github.com/roboflow/supervision/issues) and [discussions](https://github.com/roboflow/supervision/discussions) first.
options:
- label: >
I have searched the Supervision [issues](https://github.com/roboflow/supervision/issues) and found no similar bug report.
- label: I have searched the issues and discussions and found no similar bug report.
required: true
- type: textarea
attributes:
label: Bug
description: Provide console output with error messages and/or screenshots of the bug.
description: Describe the bug, what you expected, and what actually happened.
placeholder: |
💡 ProTip! Include as much information as possible (screenshots, logs, tracebacks etc.) to receive the most helpful response.
**What's the bug?**
Brief description...
**Expected behavior:**
What should happen...
**Actual behavior:**
What actually happens...
**Error/Traceback (if any):**
```python
# Paste error messages here
```
validations:
required: true
- type: textarea
attributes:
label: Environment
description: Please specify the software and hardware you used to produce the bug.
description: Your setup details
placeholder: |
- Supervision: 0.1.0
- OS: Ubuntu 20.04
- Python: 3.8.10
- Supervision: 0.23.0
- Python: 3.10.12
- OS: Ubuntu 22.04
value: |
- Supervision:
- Python:
- OS:
validations:
required: false
required: true
- type: textarea
attributes:
label: Minimal Reproducible Example
description: >
When asking a question, people will be better able to provide help if you provide code that they can easily understand and use to **reproduce** the problem.
This is referred to by community members as creating a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example).
description: Code to reproduce the bug ([guide](https://stackoverflow.com/help/minimal-reproducible-example))
placeholder: |
```
# Code to reproduce your issue here
```python
import supervision as sv
# Your code here
```
validations:
required: false
- type: textarea
attributes:
label: Additional
description: Anything else you would like to share?
- type: checkboxes
attributes:
label: Are you willing to submit a PR?
description: >
(Optional) We encourage you to submit a [Pull Request](https://github.com/roboflow/supervision/pulls) (PR) to help improve Supervision for everyone, especially if you have a good understanding of how to implement a fix or feature.
description: (Optional) We encourage community contributions!
options:
- label: Yes I'd like to help by submitting a PR!
+17
View File
@@ -0,0 +1,17 @@
blank_issues_enabled: false
contact_links:
- name: ❓ Ask a Question
url: https://github.com/roboflow/supervision/discussions/new?category=q-a
about: Ask questions about using Supervision in GitHub Discussions
- name: 📚 Documentation
url: https://supervision.roboflow.com/
about: Check the official Supervision documentation for guides and API references
- name: 💬 GitHub Discussions
url: https://github.com/roboflow/supervision/discussions
about: Join community discussions, share ideas, and get help
- name: 🌟 Show and Tell
url: https://github.com/roboflow/supervision/discussions/categories/show-and-tell
about: Share your projects and creations built with Supervision
- name: 🗣️ Roboflow Discord
url: https://discord.com/invite/GbfgXGJ8Bk
about: Join our Discord to collaborate with other community members
+20 -19
View File
@@ -1,6 +1,6 @@
name: 🤩 Feature Request
description: Suggest a Supervision idea
# title: " "
title: "[Feature]: "
description: Suggest a new feature or improvement
labels: [enhancement]
body:
- type: markdown
@@ -11,39 +11,40 @@ body:
- type: checkboxes
attributes:
label: Search before asking
description: >
Please search the [issues](https://github.com/roboflow/supervision/issues) to see if a similar feature request already exists.
description: Please search [issues](https://github.com/roboflow/supervision/issues) and [discussions](https://github.com/roboflow/supervision/discussions) first.
options:
- label: >
I have searched the Supervision [issues](https://github.com/roboflow/supervision/issues) and found no similar feature requests.
- label: I have searched the issues and discussions and found no similar feature request.
required: true
- type: textarea
attributes:
label: Description
description: A short description of your feature.
label: Feature Description
description: What feature would you like and why?
placeholder: |
What new feature would you like to see in Supervision?
**What:** Describe the feature...
**Why:** What problem does it solve? Who would benefit?
**How (optional):** Any ideas on implementation?
validations:
required: true
- type: textarea
attributes:
label: Use case
description: |
Describe the use case of your feature request. It will help us understand and prioritize the feature request.
label: Example Usage
description: (Optional) Show how you'd like to use this feature
placeholder: |
How would this feature be used, and who would use it?
```python
import supervision as sv
- type: textarea
attributes:
label: Additional
description: Anything else you would like to share?
# Your example usage here
```
validations:
required: false
- type: checkboxes
attributes:
label: Are you willing to submit a PR?
description: >
(Optional) We encourage you to submit a [Pull Request](https://github.com/roboflow/supervision/pulls) (PR) to help improve Supervision for everyone, especially if you have a good understanding of how to implement a fix or feature.
description: (Optional) We encourage community contributions!
options:
- label: Yes I'd like to help by submitting a PR!
-33
View File
@@ -1,33 +0,0 @@
name: ❓ Question
description: Ask a Supervision question
# title: " "
labels: [question]
body:
- type: markdown
attributes:
value: |
Thank you for asking a Supervision ❓ Question!
- type: checkboxes
attributes:
label: Search before asking
description: >
Please search the [issues](https://github.com/roboflow/supervision/issues) to see if a similar feature request already exists.
options:
- label: >
I have searched the Supervision [issues](https://github.com/roboflow/supervision/issues) and found no similar feature requests.
required: true
- type: textarea
attributes:
label: Question
description: What is your question?
placeholder: |
💡 ProTip! Include as much information as possible (screenshots, logs, tracebacks etc.) to receive the most helpful response.
validations:
required: true
- type: textarea
attributes:
label: Additional
description: Anything else you would like to share?
+67
View File
@@ -0,0 +1,67 @@
<details>
<summary>Before submitting</summary>
- [ ] Self-reviewed the code
- [ ] Updated documentation, follow [Google-style](https://google.github.io/styleguide/pyguide.html#383-functions-and-methods)
- [ ] Added docs entry for autogeneration (if new functions/classes)
- [ ] Added/updated tests
- [ ] All tests pass locally
</details>
## Description
<!-- Provide a clear and concise description of your changes -->
## Type of Change
<!-- Mark the relevant option with an "x" and delete the others -->
- 🐛 Bug fix (non-breaking change which fixes an issue)
- ✨ New feature (non-breaking change which adds functionality)
- 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
- 📝 Documentation update
- 🧪 Test update
- 🔨 Refactoring (no functional changes)
- ⚡ Performance improvement
- 🔧 Chore (dependencies, configs, etc.)
## Motivation and Context
<!-- Why is this change required? What problem does it solve? -->
<!-- If it fixes an open issue, please link to the issue here -->
Closes #(issue)
## Changes Made
<!-- List the main changes made in this PR -->
-
-
-
## Testing
<!-- Describe the tests you ran and how to reproduce them -->
- [ ] I have tested this code locally
- [ ] I have added unit tests that prove my fix is effective or that my feature works
- [ ] All new and existing tests pass
## Google Colab (optional)
<!-- If applicable, provide a link to a Google Colab notebook demonstrating the feature/fix -->
<!-- Ensure the notebook is publicly accessible -->
Colab link:
## Screenshots/Videos (optional)
<!-- If applicable, add screenshots or videos to demonstrate the changes -->
## Additional Notes
<!-- Any additional information that reviewers should know -->
+146
View File
@@ -0,0 +1,146 @@
# GitHub Copilot Instructions for Supervision
This file provides context-aware guidance for GitHub Copilot when working in the Supervision repository.
______________________________________________________________________
## 📚 Repository Overview
**Supervision** is a Python library providing reusable computer vision utilities for working with object detection models (YOLO, SAM, etc.). It offers tools for detections processing, tracking, annotation, and dataset management.
- **Languages**: Python 3.10+
- **Key Dependencies**: NumPy, OpenCV, SciPy
- **License**: MIT
______________________________________________________________________
## 🏗️ Project Structure
```
supervision/
├── src/
│ └── supervision/ # Main library code
│ ├── detection/ # Detection utilities
│ ├── draw/ # Annotation and visualization
│ ├── tracker/ # Object tracking
│ ├── dataset/ # Dataset management
│ └── utils/ # Shared utilities
├── tests/ # Test suite (mirrors src/supervision/)
├── docs/ # MkDocs documentation
└── examples/ # Usage examples
```
______________________________________________________________________
## 🔧 Development Commands
**Setup:**
```bash
# Install dependencies
uv sync --group dev --group docs --extra metrics
# Install pre-commit hooks
uv run pre-commit install
```
**Quality Checks:**
```bash
# Run all pre-commit hooks (formatting, linting, type checking)
uv run pre-commit run --all-files
# Run tests with coverage
uv run pytest --cov=supervision
```
**Documentation:**
```bash
# Serve docs locally at http://127.0.0.1:8000
uv run mkdocs serve
```
______________________________________________________________________
## 💻 Code Conventions
### General Guidelines
- Follow **[AGENTS.md](../AGENTS.md)** for task-based development workflows
- Reference **[CONTRIBUTING.md](CONTRIBUTING.md)** for detailed contribution guidelines
- All code must pass `pre-commit` hooks before committing
### Code Style
- **Formatting**: Enforced by `ruff-format`, `prettier` (pre-commit)
- **Linting**: Enforced by `ruff-check` (pre-commit)
- **Type Hints**: Required on all new code
- **Docstrings**: Required using [Google Python style](https://google.github.io/styleguide/pyguide.html#383-functions-and-methods)
- Must include usage examples with primitive values
- Serve as runnable documentation
### Performance
- Avoid unnecessary NumPy array copies
- Prefer vectorized operations over Python loops
- Use OpenCV operations efficiently
### API Design
- Follow existing naming patterns for consistency
- Maintain backward compatibility unless explicitly breaking
- Prefer functional utilities over complex classes
______________________________________________________________________
## 🧪 Testing Requirements
All new features must include:
- Unit tests covering happy path and edge cases
- Tests for `None`, empty inputs, large arrays, boundary conditions
- Clear test names describing what they validate
- Proper assertions (not just "no exception raised")
______________________________________________________________________
## 📝 Documentation Requirements
For new public functions/classes:
- Google-style docstrings with parameters, returns, exceptions
- Usage examples in docstrings
- Entry in appropriate `docs/*.md` file
- Reference in `mkdocs.yml` navigation
______________________________________________________________________
## 🔍 Pull Request Reviews
**When reviewing PRs, follow the comprehensive [PR Review Guidelines](CONTRIBUTING.md#pr-review-guidelines).**
Quick checklist:
- Tests included and passing
- Docstrings follow Google style with examples
- Pre-commit hooks pass
- Breaking changes documented
- Score code quality, testing, docs (n/5 scale)
- Use inline comments + GitHub suggestion format
______________________________________________________________________
## 🌿 Branching & Commits
- Branch from `develop` using prefixes: `feat/`, `fix/`, `docs/`, `refactor/`, `perf/`, `test/`, `chore/`
- Use **conventional commits**: `feat:`, `fix:`, `docs:`, `refactor:`, `perf:`, `test:`, `chore:`
- All PRs target `develop` branch
______________________________________________________________________
## 🎯 Context-Aware Behavior
- **For general development tasks**: Follow [AGENTS.md](../AGENTS.md)
- **For pull request reviews**: Follow [PR Review Guidelines](CONTRIBUTING.md#pr-review-guidelines)
- **For detailed processes**: Consult [CONTRIBUTING.md](CONTRIBUTING.md)
+8
View File
@@ -5,14 +5,22 @@ updates:
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
commit-message:
prefix: ⬆️
target-branch: "develop"
groups:
github-actions:
patterns:
- "*"
# Python
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
commit-message:
prefix: ⬆️
target-branch: "develop"
+35
View File
@@ -0,0 +1,35 @@
verbose = "info"
no_progress = true
include_verbatim = true
retry_wait_time = 10
max_retries = 3
max_concurrency = 8
cache = false
accept = [
200, # OK
408, # Request Timeout
# 429 means the server received the request and is actively rate-limiting — the URL is
# reachable. Real dead links return 404, 410, or fail to connect/resolve; none of
# those produce a 429, so accepting it here does not hide broken links.
429, # Too Many Requests (rate-limited but reachable; does not mask dead links)
# CI regularly sees momentary 502/503/504 from large, healthy hosts (github.com,
# supervision.roboflow.com), and in-run retries tend to land inside the same
# incident window. Genuinely dead links surface as 404, 410, or connection/DNS
# failures, which remain rejected.
502, # Bad Gateway (transient upstream hiccup)
503, # Service Unavailable (transient overload or maintenance)
504, # Gateway Timeout (transient upstream hiccup)
]
exclude = [
"https://github.com/YOUR_USERNAME/supervision.git", # hint for forking contributors
"http://127.0.0.1:8000", # hint for local docs server
"https://sam2.metademolab.com/", # returns 403 Forbidden
"https://snyk.io/advisor/python/supervision/badge.svg", # badge URL
"https://trendshift.io", # badge API times out in CI
"https://universe.roboflow.com/",
"https://universe.roboflow.com/model-examples/segmented-animals-basic",
# fixme: this page returns 401 Unauthorized when accessed and 404 Not Found when accessed with browser,
# which is weird and should be investigated
"https://huggingface.co/spaces/Roboflow/Annotators",
]
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env python3
"""
Script to augment relative links in markdown files to GitHub URLs.
"""
import argparse
import os
import re
from re import Match
def get_repo_root() -> str:
"""Get the repository root path."""
script_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.dirname(os.path.dirname(script_dir))
def augment_links_in_file(file_path: str, branch: str = "main") -> None:
"""
Augment relative links in a markdown file to GitHub URLs.
Args:
file_path: Path to the markdown file.
branch: Branch name, default "main".
"""
repo_root = get_repo_root()
if not file_path.endswith(".md"):
return
with open(file_path) as f:
content = f.read()
def replace_link(match: Match[str]) -> str:
full_match = match.group(0)
text = match.group(2)
url = match.group(3)
if not url.startswith("http"):
# Resolve relative to an absolute path
abs_path = os.path.normpath(os.path.join(os.path.dirname(file_path), url))
if os.path.exists(abs_path):
# Use 'tree' for directories and 'blob' for files
ref = "tree" if os.path.isdir(abs_path) else "blob"
rel_to_root = os.path.relpath(abs_path, repo_root)
new_url = f"https://github.com/roboflow/supervision/{ref}/{branch}/{rel_to_root}"
if full_match.startswith("!"):
return f"![{text}]({new_url})"
else:
return f"[{text}]({new_url})"
return full_match
new_content = re.sub(r"(!?)\[([^\]]+)\]\(([^)]+)\)", replace_link, content)
with open(file_path, "w") as f:
f.write(new_content)
def main() -> None:
parser = argparse.ArgumentParser(
description="Augment relative links to GitHub URLs."
)
parser.add_argument("--branch", default="main", help="Branch name")
parser.add_argument("files", nargs="+", help="Files to process")
args = parser.parse_args()
for file in args.files:
augment_links_in_file(file, args.branch)
if __name__ == "__main__":
main()
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/env python3
"""Validate doctest prompt formatting in source docstrings."""
from __future__ import annotations
import argparse
import re
import sys
from pathlib import Path
DOCTEST_PROMPT_RE = re.compile(r"^\s*>>>")
FENCE_RE = re.compile(r"^\s*```(?P<language>[A-Za-z0-9_-]*)\s*$")
def _check_content(content: str, path: Path) -> list[str]:
r"""Return doctest fence violations for file content.
Examples:
```pycon
>>> from pathlib import Path
>>> _check_content('```pycon\n>>> len([1])\n1\n\n```\n', Path('src/a.py'))
[]
>>> _check_content('>>> len([1])\n1\n', Path('src/a.py'))
['src/a.py:1: doctest prompt must be inside a ```pycon fenced block']
>>> violations = _check_content(
... '```pycon\n>>> len([1])\n1\n```\n', Path('src/a.py')
... )
>>> violations == [
... 'src/a.py:4: pycon doctest block must include exactly one blank line '
... 'before the closing fence'
... ]
True
```
"""
violations: list[str] = []
active_fence_language: str | None = None
in_invalid_doctest_block = False
line_before_previous = ""
previous_line = ""
for line_number, line in enumerate(content.splitlines(), start=1):
fence_match = FENCE_RE.match(line)
if fence_match is not None:
in_invalid_doctest_block = False
if active_fence_language is None:
active_fence_language = fence_match.group("language")
else:
has_exactly_one_blank_line = (
previous_line.strip() == "" and line_before_previous.strip() != ""
)
if active_fence_language == "pycon" and not has_exactly_one_blank_line:
violations.append(
f"{path}:{line_number}: pycon doctest block must include "
"exactly one blank line before the closing fence"
)
active_fence_language = None
line_before_previous = previous_line
previous_line = line
continue
if not line.strip():
in_invalid_doctest_block = False
if (
DOCTEST_PROMPT_RE.match(line)
and active_fence_language != "pycon"
and not in_invalid_doctest_block
):
violations.append(
f"{path}:{line_number}: doctest prompt must be inside a "
"```pycon fenced block"
)
in_invalid_doctest_block = True
line_before_previous = previous_line
previous_line = line
return violations
def check_file(path: Path) -> list[str]:
"""Return doctest fence violations for a single source file."""
if not path.is_file() or path.suffix != ".py" or "src" not in path.parts:
return []
return _check_content(content=path.read_text(encoding="utf-8"), path=path)
def main() -> int:
"""Run the doctest fence check for pre-commit supplied files."""
parser = argparse.ArgumentParser(
description="Validate doctest prompts in src/ are fenced as pycon blocks."
)
parser.add_argument("files", nargs="*", type=Path)
args = parser.parse_args()
violations = [
violation for path in args.files for violation in check_file(path=path)
]
if violations:
print("\n".join(violations))
return 1
return 0
if __name__ == "__main__":
sys.exit(main())
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/env python3
"""Verify a built Supervision wheel works without OpenCV."""
from __future__ import annotations
import argparse
import subprocess
import zipfile
from email import message_from_bytes
from email.message import Message
from pathlib import Path
_MANIFEST_CHECKS = {
"import-supervision",
"no-cv2-module",
"fallback-backend",
"bgr-to-gray",
"draw-rectangle",
"required-pyav",
}
def _wheel_metadata(wheel: Path) -> Message:
"""Read the core metadata embedded in a wheel archive."""
with zipfile.ZipFile(wheel) as archive:
metadata_paths = [
name for name in archive.namelist() if name.endswith("/METADATA")
]
if len(metadata_paths) != 1:
raise ValueError(
f"expected one METADATA file in {wheel}, found {metadata_paths}"
)
return message_from_bytes(archive.read(metadata_paths[0]))
def _validate_metadata(wheel: Path) -> None:
"""Reject wheels that retain an OpenCV runtime requirement or extra."""
metadata = _wheel_metadata(wheel)
requirements = metadata.get_all("Requires-Dist", [])
extras = metadata.get_all("Provides-Extra", [])
if any("opencv" in requirement.lower() for requirement in requirements):
raise ValueError(
f"OpenCV runtime requirement remains in {wheel}: {requirements}"
)
if any("opencv" in extra.lower() for extra in extras):
raise ValueError(f"OpenCV extra remains in {wheel}: {extras}")
def _validate_manifest(manifest: Path) -> None:
"""Keep the installed-wheel fallback smoke contract explicit and complete."""
checks = {
s
for line in manifest.read_text(encoding="utf-8").splitlines()
if (s := line.strip()) and not s.startswith("#")
}
if checks != _MANIFEST_CHECKS:
raise ValueError(
f"unexpected fallback manifest {checks}; expected {_MANIFEST_CHECKS}"
)
def _run_installed_wheel_probe(python: Path) -> None:
"""Exercise the installed fallback without allowing the source tree on sys.path."""
source = """
import importlib.util
from importlib import metadata
from pathlib import Path
import av
import numpy as np
import supervision
from supervision import _cv2
package_path = Path(supervision.__file__).resolve()
if "site-packages" not in package_path.parts:
raise AssertionError(
f"supervision did not import from site-packages: {package_path}"
)
if importlib.util.find_spec("cv2") is not None:
raise AssertionError("cv2 is installed in the clean-wheel environment")
opencv_distributions = [
distribution.metadata["Name"]
for distribution in metadata.distributions()
if "opencv" in distribution.metadata["Name"].lower()
]
if opencv_distributions:
raise AssertionError(
"OpenCV distributions remain in the clean-wheel environment: "
f"{opencv_distributions}"
)
if _cv2.BACKEND_NAME != "fallback":
raise AssertionError(f"expected fallback backend, got {_cv2.BACKEND_NAME!r}")
image = np.array([[[0, 0, 255]]], dtype=np.uint8)
assert _cv2.cvtColor(image, _cv2.COLOR_BGR2GRAY).tolist() == [[76]]
canvas = np.zeros((3, 3, 3), dtype=np.uint8)
assert _cv2.rectangle(canvas, (0, 0), (2, 2), (1, 2, 3), -1) is canvas
assert canvas.tolist() == [[[1, 2, 3]] * 3] * 3
assert av.__version__
"""
subprocess.run( # noqa: S603 - the caller passes the clean CI interpreter explicitly.
[str(python), "-c", source],
check=True,
cwd=Path.cwd().parent,
)
subprocess.run( # noqa: S603 - the caller passes the clean CI interpreter explicitly.
[str(python), "-m", "pip", "check"], check=True
)
def main() -> None:
"""Validate one wheel against a previously prepared clean environment."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--wheel", type=Path, required=True)
parser.add_argument("--python", type=Path, required=True)
parser.add_argument("--manifest", type=Path, required=True)
args = parser.parse_args()
_validate_metadata(args.wheel)
_validate_manifest(args.manifest)
_run_installed_wheel_probe(args.python)
if __name__ == "__main__":
main()
+56
View File
@@ -0,0 +1,56 @@
name: Build Package
permissions:
contents: read
on:
workflow_call:
inputs:
python-version:
required: false
type: string
default: "3.10"
link-check:
required: false
type: boolean
default: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: 🐍 Install uv and set Python version ${{ inputs.python-version }}
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ inputs.python-version }}
activate-environment: true
- name: 🎨 Augment paths in README
run: |
python .github/scripts/augment_links.py README.md --branch ${{ github.head_ref || github.ref_name }}
cat README.md
- name: 🔗 Link Checker
if: inputs.link-check
uses: lycheeverse/lychee-action@v2
with:
lycheeVersion: v0.22.0
args: |
--config .github/lychee.toml
README.md
fail: true
- name: 🏗️ Build source and wheel distributions
run: |
uv sync --frozen --group build
uv build
twine check --strict dist/*
- name: 📤 Upload distribution artifacts
uses: actions/upload-artifact@v7
with:
name: dist
path: dist/
+37
View File
@@ -0,0 +1,37 @@
name: Docs/Test Workflow
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
concurrency:
group: docs-test-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
# Restrict permissions by default
permissions:
contents: read # Required for checkout
checks: write # Required for test reporting
jobs:
docs-build:
name: Test docs build
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: 🐍 Install uv and set Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.10"
activate-environment: true
- name: 🏗️ Install dependencies
run: uv sync --frozen --group docs
- name: 🧪 Test Docs Build
run: mkdocs build --verbose
+37
View File
@@ -0,0 +1,37 @@
name: Check links & references
permissions:
contents: read
on:
push:
branches: [main, develop]
pull_request:
schedule:
# Run once a week on Sundays
- cron: "0 9 * * 0"
concurrency:
group: ci-check-links-${{ github.ref }}
cancel-in-progress: true
jobs:
links-check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7.0.1
- name: 🔗 Link Checker
uses: lycheeverse/lychee-action@v2
with:
lycheeVersion: v0.22.0
args: |
--config .github/lychee.toml
'./**/*.md'
# TODO: enable also following file types
# './**/*.toml'
# './**/*.yml'
# './**/*.yaml'
# './**/*.py'
fail: true
token: ${{ secrets.GITHUB_TOKEN }}
+159
View File
@@ -0,0 +1,159 @@
name: Pytest/Test Workflow
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
permissions:
contents: read
concurrency:
group: pytest-test-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
build-pkg:
name: Build this Package
uses: ./.github/workflows/build-package.yml
with:
# only run link check on PRs from the same repo
link-check: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
run-tests:
name: Pytest Run
# needs: build # todo: consider using this build package for testing
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
cv2: ["none"]
include:
- { os: "ubuntu-latest", python-version: "3.13", cv2: "opencv-python" }
- { os: "windows-latest", python-version: "3.13", cv2: "opencv-python" }
- { os: "macos-latest", python-version: "3.13", cv2: "opencv-python" }
- { os: "ubuntu-latest", python-version: "3.13", cv2: "opencv-python-headless" }
- { os: "windows-latest", python-version: "3.13", cv2: "opencv-python-headless" }
- { os: "macos-latest", python-version: "3.13", cv2: "opencv-python-headless" }
runs-on: ${{ matrix.os }}
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ matrix.python-version }}
activate-environment: true
- name: 🚀 Install Packages
run: uv sync --frozen --group dev --extra metrics
- name: 📷 Install selected OpenCV package
if: matrix.cv2 != 'none'
run: uv pip install ${{ matrix.cv2 }}
- name: 🧭 Confirm selected cv2 backend
env:
EXPECTED_BACKEND: ${{ matrix.cv2 == 'none' && 'fallback' || 'opencv' }}
run: |
import os
from supervision import _cv2
expected = os.environ["EXPECTED_BACKEND"]
assert _cv2.BACKEND_NAME == expected, f"expected {expected!r}, got {_cv2.BACKEND_NAME!r}"
shell: python
- name: 📦 Run the Import test
run: python -c "import supervision; from supervision import assets; from supervision import metrics; print(supervision.__version__)"
- name: 📋 Print installed packages
run: uv pip list
- name: 🧪 Run the Test
run: pytest src/ tests/ --cov=supervision --cov-report=xml
- name: Generate Coverage Report
run: |
coverage xml
coverage report
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: "coverage.xml"
flags: cpu,${{ runner.os }},python${{ matrix.python-version }}
env_vars: OS,PYTHON
name: codecov-umbrella
fail_ci_if_error: false
- name: Minimize uv cache
run: uv cache prune --ci
clean-wheel:
name: Clean Wheel on ${{ matrix.os }} / Python ${{ matrix.python-version }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
python-version: ["3.10", "3.13"]
runs-on: ${{ matrix.os }}
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ matrix.python-version }}
activate-environment: true
- name: 🏗️ Build the wheel
run: |
uv sync --frozen --group build
uv build --wheel
- name: 🧼 Create an isolated wheel environment
shell: bash
run: |
uv venv --clear --seed .clean-wheel
if [ "$RUNNER_OS" = "Windows" ]; then
echo "CLEAN_PYTHON=$PWD/.clean-wheel/Scripts/python.exe" >> "$GITHUB_ENV"
else
echo "CLEAN_PYTHON=$PWD/.clean-wheel/bin/python" >> "$GITHUB_ENV"
fi
- name: 📦 Install and verify the wheel without OpenCV
shell: bash
run: |
uv pip install --python "$CLEAN_PYTHON" --strict dist/*.whl
"$CLEAN_PYTHON" .github/scripts/verify_clean_wheel.py \
--wheel dist/*.whl \
--python "$CLEAN_PYTHON" \
--manifest tests/cv2/installed_wheel_fallback_manifest.txt
testing-guardian:
runs-on: ubuntu-latest
needs: [run-tests, clean-wheel]
if: always()
steps:
- name: 📋 Display test result
run: echo "tests=${{ needs.run-tests.result }}, clean-wheel=${{ needs.clean-wheel.result }}"
- name: ❌ Fail guardian on test failure
if: needs.run-tests.result == 'failure' || needs.clean-wheel.result == 'failure'
run: exit 1
# Ensure that cancelled or skipped test runs still cause this guardian job to fail,
# using an explicit exit code instead of relying on timeout behavior.
- name: ⚠️ cancelled or skipped...
if: contains(fromJSON('["cancelled", "skipped"]'), needs.run-tests.result) || contains(fromJSON('["cancelled", "skipped"]'), needs.clean-wheel.result)
run: |
echo "run-tests job result is '${{ needs.run-tests.result }}'; failing explicitly."
exit 1
- name: ✅ tests succeeded
if: needs.run-tests.result == 'success'
run: echo "All tests completed successfully."
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Clear cache
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
console.log("Starting cache cleanup...")
@@ -1,22 +0,0 @@
name: Combine Dependabot PRs
on:
schedule:
- cron: "0 1 * * 3" # Wednesday at 01:00
workflow_dispatch: # allows you to manually trigger the workflow
permissions:
contents: write
pull-requests: write
checks: read
jobs:
combine-prs:
name: Combine
runs-on: ubuntu-latest
steps:
- name: combine-prs
id: combine-prs
uses: github/combine-prs@2909f404763c3177a456e052bdb7f2e85d3a7cb3 # v5.2.0
with:
labels: combined-pr
+26
View File
@@ -0,0 +1,26 @@
name: PR Conflict Labeler
on:
# So that PRs touching the same files as the push are updated
push:
branches:
- main
- develop
# So that the `dirtyLabel` is removed if conflicts are resolved
# We recommend `pull_request_target` so that github secrets are available.
# In `pull_request` we wouldn't be able to change labels of fork PRs
pull_request_target:
types: [synchronize]
permissions:
pull-requests: write
issues: write
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: check if prs are dirty
uses: eps1lon/actions-label-merge-conflict@v3
with:
dirtyLabel: "has conflicts"
repoToken: "${{ secrets.GITHUB_TOKEN }}"
+129 -28
View File
@@ -1,9 +1,15 @@
name: Build and Publish Docs
name: Docs/Build and Publish
# Deploy matrix:
# push develop -> mike deploy develop
# push release/latest -> mike deploy latest
# release published -> mike deploy <tag> only; does not move /latest/
on:
push:
branches:
- develop
- release/latest
workflow_dispatch:
release:
types: [published]
@@ -20,51 +26,146 @@ permissions:
pull-requests: write # Required for PR comments
jobs:
deploy:
docs-build-deploy:
name: Publish Docs
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
python-version: ["3.10"]
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: 🐍 Install uv and set Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
- name: 🐍 Install uv and set Python
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ matrix.python-version }}
- name: 🔑 Create GitHub App token (mkdocs)
id: mkdocs_token
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with:
app-id: ${{ secrets.MKDOCS_APP_ID }}
private-key: ${{ secrets.MKDOCS_PEM }}
owner: roboflow
repositories: mkdocs-material-insiders
python-version: "3.10"
activate-environment: true
- name: 🏗️ Install dependencies
run: |
uv pip install -r pyproject.toml --extra docs
# Install mkdocs-material-insiders using the GitHub App token
uv pip install "git+https://roboflow:${{ steps.mkdocs_token.outputs.token }}@github.com/roboflow/mkdocs-material-insiders.git@9.5.49-insiders-4.53.14#egg=mkdocs-material[imaging]"
run: uv sync --frozen --group docs
- name: ⚙️ Configure git for github-actions
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "${{ github.actor }}"
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
- name: 🚀 Deploy Development Docs
if: (github.event_name == 'push' && github.ref == 'refs/heads/develop') || github.event_name == 'workflow_dispatch'
env:
MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }}
run: |
MKDOCS_GIT_COMMITTERS_APIKEY=${{ secrets.GITHUB_TOKEN }} uv run mike deploy --push develop
mike deploy --push develop
- name: 🚀 Deploy Latest Docs
if: github.event_name == 'push' && github.ref == 'refs/heads/release/latest'
env:
MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }}
run: |
if mike list | grep -Eq '^latest(\s|$)'; then mike delete latest; fi
mike deploy --push latest
- name: 🏷️ Determine release deployment metadata
id: release_metadata
run: |
is_rc=false
release_tag=""
if [[ "$GITHUB_EVENT_NAME" == "release" ]]; then
release_tag="${GITHUB_REF_NAME#v}"
release_tag="${release_tag%.post*}"
release_tag_lower="${release_tag,,}"
# Match RC suffixes with separators (1.0-rc1, 1.0.rc1) or compact form (1.0rc1).
if [[ "$release_tag_lower" =~ (^|[._-])rc[0-9]+$ ]] || [[ "$release_tag_lower" =~ [0-9]rc[0-9]+$ ]]; then
is_rc=true
fi
fi
echo "is_rc=$is_rc" >> "$GITHUB_OUTPUT"
echo "release_tag=$release_tag" >> "$GITHUB_OUTPUT"
- name: 🚀 Deploy Release Docs
if: github.event_name == 'release' && github.event.action == 'published'
if: github.event_name == 'release' && github.event.action == 'published' && steps.release_metadata.outputs.is_rc != 'true'
env:
MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }}
run: |
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
MKDOCS_GIT_COMMITTERS_APIKEY=${{ secrets.GITHUB_TOKEN }} uv run mike deploy --push --update-aliases $latest_tag latest
mike deploy --push "${{ steps.release_metadata.outputs.release_tag }}"
# IndexNow key: 0d5d9799b1cc4a39825146388c6781eb
# This key must stay in sync across three files:
# docs/0d5d9799b1cc4a39825146388c6781eb.txt (key file served at site root)
# docs/theme/main.html (indexnow-key meta tag)
# this workflow (inject step + notify step below)
# Bing/Yandex fetch https://supervision.roboflow.com/<key>.txt to verify ownership.
# Do NOT rename or delete the .txt file or change the key string without updating all three.
- name: 🌐 Inject GEO root files into gh-pages
if: >
(github.event_name == 'push' && github.ref == 'refs/heads/develop') ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/release/latest') ||
(github.event_name == 'release' && github.event.action == 'published' && steps.release_metadata.outputs.is_rc != 'true')
run: |
cp docs/robots.txt /tmp/robots.txt
cp docs/llms.txt /tmp/llms.txt
cp docs/llms.full.txt /tmp/llms.full.txt
cp docs/llms-100k.txt /tmp/llms-100k.txt
cp docs/_headers /tmp/headers.txt
cp docs/0d5d9799b1cc4a39825146388c6781eb.txt /tmp/indexnow.txt
if [[ "$GITHUB_REF" == "refs/heads/release/latest" ]]; then
version_dir="latest"
else
version_dir=""
fi
git fetch origin gh-pages
git checkout gh-pages
cp /tmp/robots.txt robots.txt
cp /tmp/llms.txt llms.txt
cp /tmp/llms.full.txt llms.full.txt
cp /tmp/llms-100k.txt llms-100k.txt
cp /tmp/headers.txt _headers
cp /tmp/indexnow.txt 0d5d9799b1cc4a39825146388c6781eb.txt
if [[ -n "$version_dir" && -f "$version_dir/sitemap.xml" ]]; then
cp "$version_dir/sitemap.xml" sitemap.xml
gzip -9 -c sitemap.xml > sitemap.xml.gz
fi
files_to_add=(
robots.txt
llms.txt
llms.full.txt
llms-100k.txt
_headers
0d5d9799b1cc4a39825146388c6781eb.txt
)
if [[ -f "sitemap.xml" ]]; then
files_to_add+=(sitemap.xml)
fi
if [[ -f "sitemap.xml.gz" ]]; then
files_to_add+=(sitemap.xml.gz)
fi
git add "${files_to_add[@]}"
git diff --cached --quiet || git commit -m "chore: update GEO root files"
git push origin gh-pages
- name: 📡 Notify IndexNow
if: >
(github.event_name == 'push' && github.ref == 'refs/heads/develop') ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.ref == 'refs/heads/release/latest')
run: |
curl -s -o /dev/null -w "%{http_code}" -X POST "https://api.indexnow.org/IndexNow" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"host": "supervision.roboflow.com",
"key": "0d5d9799b1cc4a39825146388c6781eb",
"keyLocation": "https://supervision.roboflow.com/0d5d9799b1cc4a39825146388c6781eb.txt",
"urlList": [
"https://supervision.roboflow.com/",
"https://supervision.roboflow.com/latest/",
"https://supervision.roboflow.com/latest/how_to/detect_and_annotate/",
"https://supervision.roboflow.com/latest/how_to/track_objects/",
"https://supervision.roboflow.com/latest/how_to/detect_small_objects/",
"https://supervision.roboflow.com/latest/how_to/filter_detections/",
"https://supervision.roboflow.com/latest/how_to/save_detections/",
"https://supervision.roboflow.com/latest/how_to/count_in_zone/",
"https://supervision.roboflow.com/latest/how_to/benchmark_a_model/",
"https://supervision.roboflow.com/latest/how_to/process_datasets/"
]
}' || true
+25 -19
View File
@@ -3,16 +3,30 @@ name: Publish Supervision Pre-Releases to PyPI
on:
push:
tags:
- "[0-9]+.[0-9]+[0-9]+.[0-9]+a[0-9]"
- "[0-9]+.[0-9]+[0-9]+.[0-9]+b[0-9]"
- "[0-9]+.[0-9]+[0-9]+.[0-9]+rc[0-9]"
- "[0-9]+.[0-9]+.[0-9]+a[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+b[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+.a[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+.b[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+.rc[0-9]+"
workflow_dispatch:
pull_request:
branches: [main, develop]
paths:
- ".github/workflows/build-package.yml"
- ".github/workflows/publish-pre-release.yml"
permissions: {} # Explicitly remove all permissions by default
jobs:
build:
permissions:
contents: read
uses: ./.github/workflows/build-package.yml
publish-pre-release:
name: Publish Pre-release Package
needs: build
runs-on: ubuntu-latest
environment:
name: test
@@ -21,25 +35,17 @@ jobs:
permissions:
id-token: write # Required for PyPI publishing
contents: read # Required for checkout
strategy:
matrix:
python-version: ["3.10"]
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
- name: 📥 Download distribution artifacts
uses: actions/download-artifact@v8
with:
python-version: ${{ matrix.python-version }}
- name: 🏗️ Build source and wheel distributions
run: |
uv pip install -r pyproject.toml --extra build
uv build
uv run twine check --strict dist/*
name: dist
path: dist/
- name: List distribution artifacts
run: ls -lh dist/
- name: 🚀 Publish to PyPi
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
if: github.event_name != 'pull_request'
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
with:
attestations: true
+29 -19
View File
@@ -1,16 +1,26 @@
name: Publish Supervision Releases to PyPI
on:
push:
tags:
- "[0-9]+.[0-9]+[0-9]+.[0-9]"
release:
types: [published]
workflow_dispatch:
pull_request:
branches: [main, develop]
paths:
- ".github/workflows/build-package.yml"
- ".github/workflows/publish-release.yml"
permissions: {} # Explicitly remove all permissions by default
jobs:
build:
permissions:
contents: read
uses: ./.github/workflows/build-package.yml
publish-release:
name: Publish Release Package
needs: build
runs-on: ubuntu-latest
environment:
name: release
@@ -18,26 +28,26 @@ jobs:
timeout-minutes: 10
permissions:
id-token: write # Required for PyPI publishing
contents: read # Required for checkout
strategy:
matrix:
python-version: ["3.10"]
contents: write # Required for checkout and upload assets
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
- name: 📥 Download distribution artifacts
uses: actions/download-artifact@v8
with:
python-version: ${{ matrix.python-version }}
name: dist
path: dist/
- name: List distribution artifacts
run: ls -lh dist/
- name: 🏗️ Build source and wheel distributions
run: |
uv pip install -r pyproject.toml --extra build
uv build
uv run twine check --strict dist/*
- name: 📦 Upload assets to Release
if: github.event_name == 'release'
uses: AButler/upload-release-assets@v4.0
with:
files: "dist/*"
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: 🚀 Publish to PyPi
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
# We only want to publish to PyPi if the event is a release and it's not a pre-release.
if: (github.event_name == 'release' && github.event.release.prerelease != true) || github.event_name == 'workflow_dispatch'
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
with:
attestations: true
+19 -16
View File
@@ -2,12 +2,23 @@ name: Publish Supervision Releases to TestPyPI
on:
workflow_dispatch:
pull_request:
branches: [main, develop]
paths:
- ".github/workflows/build-package.yml"
- ".github/workflows/publish-testpypi.yml"
permissions: {} # Explicitly remove all permissions by default
jobs:
build:
permissions:
contents: read
uses: ./.github/workflows/build-package.yml
publish-testpypi:
name: Publish Release Package
needs: build
runs-on: ubuntu-latest
environment:
name: release
@@ -16,26 +27,18 @@ jobs:
permissions:
id-token: write # Required for PyPI publishing
contents: read # Required for checkout
strategy:
matrix:
python-version: ["3.10"]
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
- name: 📥 Download distribution artifacts
uses: actions/download-artifact@v8
with:
python-version: ${{ matrix.python-version }}
- name: 🏗️ Build source and wheel distributions
run: |
uv pip install -r pyproject.toml --extra build
uv build
uv run twine check --strict dist/*
name: dist
path: dist/
- name: List distribution artifacts
run: ls -lh dist/
- name: 🚀 Publish to Test-PyPi
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
if: github.event_name != 'pull_request'
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
with:
repository-url: https://test.pypi.org/legacy/
attestations: true
-37
View File
@@ -1,37 +0,0 @@
name: 🧪 Docs Test WorkFlow 📚
on:
pull_request:
branches: [main, develop]
# Restrict permissions by default
permissions:
contents: read # Required for checkout
checks: write # Required for test reporting
jobs:
docs-build-test:
name: Test docs build
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
python-version: ["3.10"]
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: 🐍 Install uv and set Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
- name: 🏗️ Install dependencies
run: |
uv pip install -r pyproject.toml --extra docs
- name: 🧪 Test Docs Build
run: uv run mkdocs build --verbose
-33
View File
@@ -1,33 +0,0 @@
name: 🔧 Pytest/Test Workflow
on:
pull_request:
branches: [main, develop]
jobs:
run-tests:
name: Import Test and Pytest Run
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
runs-on: ${{ matrix.os }}
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
- name: 🚀 Install Packages
run: uv pip install -r pyproject.toml --extra dev --extra docs --extra metrics
- name: 🧪 Run the Import test
run: uv run python -c "import supervision; from supervision import assets; from supervision import metrics; print(supervision.__version__)"
- name: 🧪 Run the Test
run: uv run pytest
+36
View File
@@ -153,3 +153,39 @@ Desktop.ini
*~
.directory
.Trash-*
# local data
data/
examples/*/outputs/
!src/supervision/_cv2/data/
!src/supervision/_cv2/data/*
*.mp4
*.pt
# some artifacts
/*.py
/*.jpg
/*.png
/*.tif
/*.json
# Claude working scratchpad (plans, lessons, ephemeral artefacts)
.claude/logs/
.claude/state/
.claude/worktrees/
.developments/
.plans/
.notes/
.reports/
.temp/
.tmp/
_outputs/
_resolutions/
_reviews/
tasks/
*.local.md
output/
notebooks/
releases/
+75 -26
View File
@@ -1,3 +1,5 @@
default_language_version:
python: python3.10
ci:
autofix_prs: true
@@ -6,50 +8,97 @@ ci:
autoupdate_commit_msg: "chore(pre_commit): ⬆ pre_commit autoupdate"
repos:
- repo: local
hooks:
- id: check-doctest-fences
name: check doctest fences
entry: python .github/scripts/check_doctest_fences.py
language: python
files: ^src/.*\.py$
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v6.0.0
hooks:
- id: trailing-whitespace
exclude: test/.*\.py
- id: check-yaml
exclude: mkdocs.yml
args: ["--unsafe"]
- id: check-executables-have-shebangs
- id: check-json
- id: check-toml
- id: check-case-conflict
- id: check-added-large-files
args: ["--maxkb=500", "--enforce-all"]
exclude: uv.lock|.*\.ipynb$
- id: detect-private-key
- id: pretty-format-json
exclude: demo.ipynb
args: ['--autofix', '--no-sort-keys', '--indent=4']
args: ["--autofix", "--no-sort-keys", "--indent=4"]
- id: end-of-file-fixer
- id: mixed-line-ending
- repo: https://github.com/PyCQA/bandit
rev: '1.8.3'
hooks:
- id: bandit
args: ["-c", "pyproject.toml"]
additional_dependencies: ["bandit[toml]"]
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.9.6
hooks:
- id: prettier
files: \.(ya?ml|toml)$
# https://prettier.io/docs/en/options.html#print-width
args: ["--print-width=120"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.6
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
types_or: [ python, pyi, jupyter ]
- repo: https://github.com/tox-dev/pyproject-fmt
rev: v2.26.0
hooks:
- id: pyproject-fmt
additional_dependencies:
- "tomli>=2.0.1"
# - repo: https://github.com/executablebooks/mdformat
# rev: 0.7.17
# hooks:
# - id: mdformat
# additional_dependencies:
# - "mdformat-mkdocs[recommended]>=2.1.0"
# args: ["--number"]
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.25
hooks:
- id: validate-pyproject
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.1
hooks:
- id: ruff-check
args: ["--fix"]
- id: ruff-format
types_or: [python, pyi, jupyter]
- repo: https://github.com/executablebooks/mdformat
rev: 1.0.0
hooks:
- id: mdformat
name: mdformat (gfm)
exclude: ^docs/
additional_dependencies:
- "mdformat-frontmatter"
- "mdformat-gfm"
- "mdformat-ruff"
args: ["--number", "--wrap=no"]
- id: mdformat
name: mdformat (mkdocs)
files: ^docs/
additional_dependencies:
- "mdformat-frontmatter"
- "mdformat-mkdocs[recommended]>=2.1.0"
- "mdformat-ruff"
args: ["--number", "--wrap=no"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v2.3.0
hooks:
- id: mypy
language_version: python3.11
additional_dependencies:
- "numpy>=2.0"
- "types-PyYAML"
- "types-requests"
- "types-tqdm"
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
rev: v2.4.3
hooks:
- id: codespell
exclude: ^src/supervision/_cv2/data/hershey_fonts\.json$
additional_dependencies:
- tomli
- "tomli>=2.0.1"
+153
View File
@@ -0,0 +1,153 @@
# Agent Guidelines for `supervision`
Behave like a senior contributor: precise, efficient, maintainable. When this file and [CONTRIBUTING.md](.github/CONTRIBUTING.md) conflict, **CONTRIBUTING.md wins**.
______________________________________________________________________
## 1. Before You Code
- Read the task thoroughly; group clarifications into one ask.
- Outline a plan before making changes.
- Check whether the feature already exists under a different name.
- Confirm alignment with `src/supervision/` architecture.
______________________________________________________________________
## 2. Repository Architecture
**Package root**: `src/supervision/` — all library code. **Tests**: `tests/` — mirrors `src/supervision/`. **Public API**: `src/supervision/__init__.py`.
```
src/supervision/
├── detection/
│ ├── core.py — Detections dataclass; all model connectors as classmethods
│ ├── compact_mask.py — compact mask representation
│ ├── vlm.py — VLM connectors (Florence-2, Gemini, Qwen, PaliGemma)
│ ├── utils/ — pure NumPy helpers: boxes, converters, iou_and_nms, masks, polygons
│ ├── line_zone.py — LineZone
│ └── tools/ — InferenceSlicer, PolygonZone, CSVSink, JSONSink, DetectionsSmoother
├── annotators/core.py — BoxAnnotator, MaskAnnotator, LabelAnnotator, … each: .annotate(scene, detections)
├── key_points/ — KeyPoints, EdgeAnnotator, VertexAnnotator (use this, NOT keypoint/ — see §4)
├── tracker/ — DEPRECATED
├── dataset/core.py — DetectionDataset / ClassificationDataset (YOLO / COCO / Pascal VOC)
├── geometry/core.py — Point, Rect, Vector, Position
├── metrics/ — mAP, confusion matrix (requires --extra metrics)
├── utils/internal.py — warn_deprecated, deprecated_parameter, internal helpers
└── config.py — string constants; always import from here, never use literals
```
### Key design patterns
- **`Detections` is the lingua franca** — every connector, tracker, and annotator speaks `Detections`. New connector = `@classmethod from_<framework>(cls, result) -> Detections`.
- **Annotators are composable** — receive `scene` (BGR `np.ndarray`) + `detections`, return annotated copy.
- **`data` dict extensibility** — per-detection metadata in `detections.data` as `np.ndarray` aligned with `xyxy`. Keys are constants from `config.py`.
- **Vectorized throughout** — NumPy arrays, no Python loops in hot paths. Never write `for det in detections`.
- **Lazy-import heavy deps** — `torch`, `transformers`, `ultralytics` must be imported inside the function that needs them, never at module top level.
______________________________________________________________________
## 3. Agent-Critical Rules
These supplement [CONTRIBUTING.md](.github/CONTRIBUTING.md) — covering gaps or agent-specific failure modes.
**Doc headings**: `###` max in docstrings and docs. `####` renders identically to bold in mkdocs — use `**bold**` instead.
**Type hints**: required on all new code. mypy is enforced by pre-commit (`.pre-commit-config.yaml`).
**Function docstrings**: every new or modified function, including private helpers and tests, must have a succinct docstring explaining its purpose. Put function-level why/what/how context inside the function docstring, not in a comment before the function. Public APIs still require the full Google-style structure described below.
**Readable argument lists**: do not put multi-branch conditional expressions inside function or constructor arguments. If an argument needs more than a simple `a if condition else b`, assign it to a named local variable before the call.
**Inline comments**: write code so the intent is clear from names, small helpers, and straightforward control flow. For non-trivial logic inside a function that still needs context, add concise inline comments explaining why the code exists, what invariant it protects, and how the tricky part works. Do not put comments before functions; use the function docstring instead. Do not comment obvious assignments, mechanical plumbing, lint-only changes, typing-only changes, or pure docs edits.
**Doctest determinism** — output must be reproducible across platforms:
- Use `# doctest: +ELLIPSIS` for floats that vary by platform.
- Seed any RNG before calling it.
- Never assert `dict` or `set` iteration order.
- No network or filesystem access outside `supervision/assets/`.
**⚠ Test structure** — agents frequently fail here; read [CONTRIBUTING.md §Tests](.github/CONTRIBUTING.md#-tests) carefully: AAA structure, class grouping, parametrize with `pytest.param(..., id="slug")`, one-line docstring per test.
For branching, commit, code style, and API design conventions see [CONTRIBUTING.md](.github/CONTRIBUTING.md).
______________________________________________________________________
## 4. Deprecated Module Aliases
`supervision.keypoint` deprecated since `0.27.0`, removed in `0.31.0`. Always import from `supervision.key_points`, not `supervision.keypoint`.
______________________________________________________________________
## 5. Deprecating APIs
**Minimum window**: deprecated APIs must remain for at least **3 minor releases** before removal. Example: deprecated in `0.29.0` → removed in `0.32.0`.
- Module-level: `supervision.utils.internal.warn_deprecated` in the deprecated module's own `__init__.py`
- Parameter renamed (old→new): `supervision.utils.internal.deprecated_parameter` decorator
- Public function, method, or class: `@deprecated` from `pydeprecate`
Always name the version introduced and the removal version:
```python
warn_deprecated("'foo' deprecated in `0.29.0`, removed in `0.32.0`. Use 'bar'.")
```
______________________________________________________________________
## 6. Implementing Features
- Minimal implementation; type hints and Google docstrings with usage examples.
- Tests covering new functionality and edge cases (see [CONTRIBUTING.md §Tests](.github/CONTRIBUTING.md#-tests)).
- Update docstrings and mkdocs entries as needed.
- Update [docs/changelog.md](docs/changelog.md) for every functional change or bug fix, including user-visible behavior changes. Skip changelog entries for lint-only, type-only, formatting-only, and pure documentation-only changes.
**Extending `Detections`**: store metadata in `detections.data` as `np.ndarray` aligned with `xyxy`; define the key as a constant in `config.py` (e.g. `CLASS_NAME_DATA_FIELD`, `ORIENTED_BOX_COORDINATES`).
**New model connector** (`detection/core.py`):
```python
@classmethod
def from_myframework(cls, result) -> "Detections":
import myframework # noqa: F401 — lazy import
xyxy = ... # (N, 4)
return cls(
xyxy=xyxy,
confidence=...,
class_id=...,
data={CLASS_NAME_DATA_FIELD: np.array([...])},
)
```
VLM connectors go in `detection/vlm.py`, not `core.py`.
______________________________________________________________________
## 7. Bugs & Refactoring
**Bugs**: reproduce → write failing test → minimal fix → verify no regressions.
**Refactoring**: preserve behavior and API; reduce duplication; avoid sweeping changes unless requested; apply §5 deprecation when removing public API.
______________________________________________________________________
## 8. Before You Commit
```bash
uv run pytest --cov=supervision
uv run pre-commit run --all-files
```
Capture a baseline before changes to avoid introducing new failures:
```bash
STASH_BEFORE=$(git rev-parse refs/stash 2>/dev/null)
git stash push --include-untracked
uv run pytest -q 2>&1 | tee /tmp/baseline.txt
[ "$(git rev-parse refs/stash 2>/dev/null)" != "$STASH_BEFORE" ] && git stash pop
uv run pytest -q 2>&1 | tee /tmp/after.txt
diff /tmp/baseline.txt /tmp/after.txt
```
Any test passing in baseline but failing after = blocker.
+5
View File
@@ -0,0 +1,5 @@
# Claude Code Project Instructions
<!-- Imports AGENTS.md, which contains agent roles, behavioral rules, and coding constraints for this project. -->
@AGENTS.md
-133
View File
@@ -1,133 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socioeconomic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of
any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
community-reports@roboflow.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][mozilla coc].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][faq]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[faq]: https://www.contributor-covenant.org/faq
[homepage]: https://www.contributor-covenant.org
[mozilla coc]: https://github.com/mozilla/diversity
[translations]: https://www.contributor-covenant.org/translations
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
-230
View File
@@ -1,230 +0,0 @@
# Contributing to Supervision 🛠️
Thank you for your interest in contributing to Supervision!
We are actively improving this library to reduce the amount of work you need to do to solve common computer vision problems.
## Code of Conduct
Please read and adhere to our [Code of Conduct](https://supervision.roboflow.com/latest/code_of_conduct/). This document outlines the expected behavior for all participants in our project.
## Table of Contents
- [Contribution Guidelines](#contribution-guidelines)
- [Contributing Features](#contributing-features)
- [How to Contribute Changes](#how-to-contribute-changes)
- [Installation for Contributors](#installation-for-contributors)
- [Code Style and Quality](#code-style-and-quality)
- [Pre-commit tool](#pre-commit-tool)
- [Docstrings](#docstrings)
- [Type checking](#type-checking)
- [Documentation](#documentation)
- [Cookbooks](#cookbooks)
- [Tests](#tests)
- [License](#license)
## Contribution Guidelines
We welcome contributions to:
1. Add a new feature to the library (guidance below).
2. Improve our documentation and add examples to make it clear how to leverage the supervision library.
3. Report bugs and issues in the project.
4. Submit a request for a new feature.
5. Improve our test coverage.
### Contributing Features ✨
Supervision is designed to provide generic utilities to solve problems. Thus, we focus on contributions that can have an impact on a wide range of projects.
For example, counting objects that cross a line anywhere on an image is a common problem in computer vision, but counting objects that cross a line 75% of the way through is less useful.
Before you contribute a new feature, consider submitting an Issue to discuss the feature so the community can weigh in and assist.
## How to Contribute Changes
First, fork this repository to your own GitHub account. Click "fork" in the top corner of the `supervision` repository to get started:
![Forking the repository](https://media.roboflow.com/fork.png)
![Creating a repository fork](https://media.roboflow.com/create_fork.png)
Then, run `git clone` to download the project code to your computer.
You should also set up `roboflow/supervision` as an "upstream" remote (that is, tell git that the reference Supervision repository was the source of your fork of it):
```bash
git remote add upstream https://github.com/roboflow/supervision.git
git fetch upstream
```
Move to a new branch using the `git checkout` command:
```bash
git checkout -b <scope>/<your_branch_name> upstream/develop
```
The name you choose for your branch should describe the change you want to make and start with an appropriate prefix:
- `feat/`: for new features (e.g., `feat/line-counter`)
- `fix/`: for bug fixes (e.g., `fix/memory-leak`)
- `docs/`: for documentation changes (e.g., `docs/update-readme`)
- `chore/`: for routine tasks, maintenance, or tooling changes (e.g., `chore/update-dependencies`)
- `test/`: for adding or modifying tests (e.g., `test/add-unit-tests`)
- `refactor/`: for code refactoring (e.g., `refactor/simplify-algorithm`)
Make any changes you want to the project code, then run the following commands to commit your changes:
```bash
git add -A
git commit -m "feat: add line counter functionality"
git push -u origin <your_branch_name>
```
Use conventional commit messages to clearly describe your changes. The format is:
<type>\[optional scope\]: <description>
Common types include:
- feat: A new feature
- fix: A bug fix
- docs: Documentation only changes
- style: Changes that do not affect the meaning of the code (white-space, formatting, etc)
- refactor: A code change that neither fixes a bug nor adds a feature
- perf: A code change that improves performance
- test: Adding missing tests or correcting existing tests
- chore: Changes to the build process or auxiliary tools and libraries
Then, go back to your fork of the `supervision` repository, click "Pull Requests", and click "New Pull Request".
![Opening a pull request](https://media.roboflow.com/open_pr.png)
Make sure the `base` branch is `develop` before submitting your PR.
On the next page, review your changes then click "Create pull request":
![Configuring a pull request](https://media.roboflow.com/create_pr_submit.png)
Next, write a description for your pull request, and click "Create pull request" again to submit it for review:
![Submitting a pull request](https://media.roboflow.com/write_pr.png)
When creating new functions, please ensure you have the following:
1. Docstrings for the function and all parameters.
2. Unit tests for the function.
3. Examples in the documentation for the function.
4. Created an entry in our docs to autogenerate the documentation for the function.
5. Please share a Google Colab with minimal code to test new feature or reproduce PR whenever it is possible. Please ensure that Google Colab can be accessed without any issue.
When you submit your Pull Request, you will be asked to sign a Contributor License Agreement (CLA) by the `cla-assistant` GitHub bot. We can only respond to PRs from contributors who have signed the project CLA.
All pull requests will be reviewed by the maintainers of the project. We will provide feedback and ask for changes if necessary.
PRs must pass all tests and linting requirements before they can be merged.
## Installation for Contributors
Before starting your work on the project, set up your development environment:
1. Clone your fork of the project (recommended to use shallow clone of develop branch):
**Option A: Recommended for most contributors (shallow clone of develop branch):**
```bash
git clone --depth 1 -b develop https://github.com/YOUR_USERNAME/supervision.git
cd supervision
```
Replace `YOUR_USERNAME` with your GitHub username.
> Note: Using `--depth 1` creates a shallow clone with minimal history and `-b develop` ensures you start with the development branch. This significantly reduces download size while providing everything needed to contribute.
**Option B: Full repository clone (if you need complete history):**
```bash
git clone https://github.com/YOUR_USERNAME/supervision.git
cd supervision
```
2. Create and activate a virtual environment:
```bash
python3 -m venv .venv
source .venv/bin/activate
```
3. Install `uv`:
Follow the instructions on the [uv installation page](https://docs.astral.sh/uv/getting-started/installation/).
4. Install project dependencies:
```bash
uv pip install -r pyproject.toml --extra dev --extra docs --extra metrics
```
5. Run pytest to verify the setup:
```bash
uv run pytest
```
## 🎨 Code Style and Quality
### Pre-commit tool
This project uses the [pre-commit](https://pre-commit.com/) tool to maintain code quality and consistency. Before submitting a pull request or making any commits, it is important to run the pre-commit tool to ensure that your changes meet the project's guidelines.
Furthermore, we have integrated a pre-commit GitHub Action into our workflow. This means that with every pull request opened, the pre-commit checks will be automatically enforced, streamlining the code review process and ensuring that all contributions adhere to our quality standards.
To run the pre-commit tool, follow these steps:
1. Install pre-commit by running the following command: `uv pip install -r pyproject.toml --extra dev`. It will not only install pre-commit but also install all the deps and dev-deps of project
2. Once pre-commit is installed, navigate to the project's root directory.
3. Run the command `pre-commit run --all-files`. This will execute the pre-commit hooks configured for this project against the modified files. If any issues are found, the pre-commit tool will provide feedback on how to resolve them. Make the necessary changes and re-run the pre-commit command until all issues are resolved.
4. You can also install pre-commit as a git hook by executing `pre-commit install`. Every time you do a `git commit` pre-commit run automatically for you.
### Docstrings
All new functions and classes in `supervision` should include docstrings. This is a prerequisite for any new functions and classes to be added to the library.
`supervision` adheres to the [Google Python docstring style](https://google.github.io/styleguide/pyguide.html#383-functions-and-methods). Please refer to the style guide while writing docstrings for your contribution.
### Type checking
So far, **there is no type checking with mypy**. See [issue](https://github.com/roboflow-ai/template-python/issues/4).
## 📝 Documentation
The `supervision` documentation is stored in a folder called `docs`. The project documentation is built using `mkdocs`.
To run the documentation, install the project requirements with `uv pip install -r pyproject.toml --extra dev --extra docs`. Then, run `mkdocs serve` to start the documentation server.
You can learn more about mkdocs on the [mkdocs website](https://www.mkdocs.org/).
## 🧑‍🍳 Cookbooks
We are always looking for new examples and cookbooks to add to the `supervision`
documentation. If you have a use case that you think would be helpful to others, please
submit a PR with your example. Here are some guidelines for submitting a new example:
- Create a new notebook in the [`docs/notebooks`](https://github.com/roboflow/supervision/tree/develop/docs/notebooks) folder.
- Add a link to the new notebook in [`docs/theme/cookbooks.html`](https://github.com/roboflow/supervision/blob/develop/docs/theme/cookbooks.html). Make sure to add the path to the new notebook, as well as a title, labels, author and supervision version.
- Use the [Count Objects Crossing the Line](https://supervision.roboflow.com/develop/notebooks/count-objects-crossing-the-line/) example as a template for your new example.
- Freeze the version of `supervision` you are using.
- Place an appropriate Open in Colab button at the top of the notebook. You can find an example of such a button in the aforementioned `Count Objects Crossing the Line` cookbook.
- Notebook should be self-contained. If you rely on external data ( videos, images, etc.) or libraries, include download and installation commands in the notebook.
- Annotate the code with appropriate comments, including links to the documentation describing each of the tools you have used.
## 🧪 Tests
[`pytests`](https://docs.pytest.org/en/7.1.x/) is used to run our tests.
## 📄 License
By contributing, you agree that your contributions will be licensed under an [MIT license](https://github.com/roboflow/supervision/blob/develop/LICENSE.md).
+3 -15
View File
@@ -2,20 +2,8 @@ MIT License
Copyright (c) 2022 Roboflow
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+65 -58
View File
@@ -1,6 +1,6 @@
<div align="center">
<p>
<a align="center" href="" target="https://supervision.roboflow.com">
<a align="center" href="https://supervision.roboflow.com" target="_blank">
<img
width="100%"
src="https://media.roboflow.com/open-source/supervision/rf-supervision-banner.png?updatedAt=1678995927529"
@@ -14,30 +14,39 @@
<br>
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision)
[![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision)
[![snyk](https://snyk.io/advisor/python/supervision/badge.svg)](https://snyk.io/advisor/python/supervision)
[![license](https://img.shields.io/pypi/l/supervision)](https://github.com/roboflow/supervision/blob/main/LICENSE.md)
[![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
[![colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/roboflow/supervision/blob/main/demo.ipynb)
[![gradio](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue)](https://huggingface.co/spaces/Roboflow/Annotators)
[![discord](https://img.shields.io/discord/1159501506232451173?logo=discord&label=discord&labelColor=fff&color=5865f2&link=https%3A%2F%2Fdiscord.gg%2FGbfgXGJ8Bk)](https://discord.gg/GbfgXGJ8Bk)
[![built-with-material-for-mkdocs](https://img.shields.io/badge/Material_for_MkDocs-526CFE?logo=MaterialForMkDocs&logoColor=white)](https://squidfunk.github.io/mkdocs-material/)
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision) [![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision) [![license](https://img.shields.io/pypi/l/supervision)](LICENSE.md) [![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision) [![codecov](https://codecov.io/gh/roboflow/supervision/graph/badge.svg?token=HMNJ5FVZ36)](https://codecov.io/gh/roboflow/supervision)
<div align="center">
[![snyk](https://snyk.io/advisor/python/supervision/badge.svg)](https://snyk.io/advisor/python/supervision) [![colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/roboflow/supervision/blob/main/demo.ipynb) [![gradio](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue)](https://huggingface.co/spaces/Roboflow/Annotators) [![discord](https://img.shields.io/discord/1159501506232451173?logo=discord&label=discord&labelColor=fff&color=5865f2&link=https%3A%2F%2Fdiscord.gg%2FGbfgXGJ8Bk)](https://discord.gg/GbfgXGJ8Bk)
<div align="center">
<a href="https://trendshift.io/repositories/124" target="_blank"><img src="https://trendshift.io/api/badge/repositories/124" alt="roboflow%2Fsupervision | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>
</div>
## 👋 hello
<details>
<summary><strong>📑 Table of Contents</strong></summary>
**We write your reusable computer vision tools.** Whether you need to load your dataset from your hard drive, draw detections on an image or video, or count how many detections are in a zone. You can count on us! 🤝
- [👋 Hello](#-hello)
- [💻 Install](#-install)
- [🔥 Quickstart](#-quickstart)
- [Models](#models)
- [Annotators](#annotators)
- [Datasets](#datasets)
- [🎬 Tutorials](#-tutorials)
- [💜 Built with Supervision](#-built-with-supervision)
- [📚 Documentation](#-documentation)
- [🏆 Contribution](#-contribution)
## 💻 install
</details>
Pip install the supervision package in a
[**Python>=3.8**](https://www.python.org/) environment.
## 👋 Hello
**We are your essential toolkit for computer vision.** From data loading to real-time zone counting, we provide the building blocks so you can focus on building applications around your models. 🤝
## 💻 Install
Pip install the supervision package in a [**Python>=3.10**](https://www.python.org/) environment.
```bash
pip install supervision
@@ -45,21 +54,22 @@ pip install supervision
Read more about conda, mamba, and installing from source in our [guide](https://roboflow.github.io/supervision/).
## 🔥 quickstart
## 🔥 Quickstart
### models
### Models
Supervision was designed to be model agnostic. Just plug in any classification, detection, or segmentation model. For your convenience, we have created [connectors](https://supervision.roboflow.com/latest/detection/core/#detections) for the most popular libraries like Ultralytics, Transformers, or MMDetection.
Supervision was designed to be model agnostic. Just plug in any classification, detection, or segmentation model. For your convenience, we have created [connectors](https://supervision.roboflow.com/latest/detection/core/#detections) for the most popular libraries like Ultralytics, Transformers, MMDetection, or Inference. Other integrations, like `rfdetr`, already return `sv.Detections` directly.
Install the optional dependencies for this example with `pip install pillow rfdetr`.
```python
import cv2
import supervision as sv
from ultralytics import YOLO
from PIL import Image
from rfdetr import RFDETRSmall
image = cv2.imread(...)
model = YOLO("yolov8s.pt")
result = model(image)[0]
detections = sv.Detections.from_ultralytics(result)
image = Image.open("path/to/image.jpg")
model = RFDETRSmall()
detections = model.predict(image, threshold=0.5)
len(detections)
# 5
@@ -73,12 +83,12 @@ len(detections)
Running with [Inference](https://github.com/roboflow/inference) requires a [Roboflow API KEY](https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key).
```python
import cv2
import supervision as sv
from PIL import Image
from inference import get_model
image = cv2.imread(...)
model = get_model(model_id="yolov8s-640", api_key=<ROBOFLOW API KEY>)
image = Image.open("path/to/image.jpg")
model = get_model(model_id="rfdetr-small", api_key="ROBOFLOW_API_KEY")
result = model.infer(image)[0]
detections = sv.Detections.from_inference(result)
@@ -88,7 +98,7 @@ len(detections)
</details>
### annotators
### Annotators
Supervision offers a wide range of highly customizable [annotators](https://supervision.roboflow.com/latest/detection/annotators/), allowing you to compose the perfect visualization for your use case.
@@ -96,18 +106,17 @@ Supervision offers a wide range of highly customizable [annotators](https://supe
import cv2
import supervision as sv
image = cv2.imread(...)
image = cv2.imread("path/to/image.jpg")
# Assuming detections are obtained from a model
detections = sv.Detections(...)
box_annotator = sv.BoxAnnotator()
annotated_frame = box_annotator.annotate(
scene=image.copy(),
detections=detections)
annotated_frame = box_annotator.annotate(scene=image.copy(), detections=detections)
```
https://github.com/roboflow/supervision/assets/26109316/691e219c-0565-4403-9218-ab5644f39bce
### datasets
### Datasets
Supervision provides a set of [utils](https://supervision.roboflow.com/latest/datasets/core/) that allow you to load, split, merge, and save datasets in one of the supported formats.
@@ -115,8 +124,8 @@ Supervision provides a set of [utils](https://supervision.roboflow.com/latest/da
import supervision as sv
from roboflow import Roboflow
project = Roboflow().workspace(<WORKSPACE_ID>).project(<PROJECT_ID>)
dataset = project.version(<PROJECT_VERSION>).download("coco")
project = Roboflow().workspace("WORKSPACE_ID").project("PROJECT_ID")
dataset = project.version("PROJECT_VERSION").download("coco")
ds = sv.DetectionDataset.from_coco(
images_directory_path=f"{dataset.location}/train",
@@ -124,13 +133,14 @@ ds = sv.DetectionDataset.from_coco(
)
path, image, annotation = ds[0]
# loads image on demand
# loads image on demand
for path, image, annotation in ds:
# loads image on demand
pass
```
<details close>
<details>
<summary>👉 more dataset utils</summary>
- load
@@ -139,17 +149,17 @@ for path, image, annotation in ds:
dataset = sv.DetectionDataset.from_yolo(
images_directory_path=...,
annotations_directory_path=...,
data_yaml_path=...
data_yaml_path=...,
)
dataset = sv.DetectionDataset.from_pascal_voc(
images_directory_path=...,
annotations_directory_path=...
annotations_directory_path=...,
)
dataset = sv.DetectionDataset.from_coco(
images_directory_path=...,
annotations_path=...
annotations_path=...,
)
```
@@ -191,17 +201,17 @@ for path, image, annotation in ds:
dataset.as_yolo(
images_directory_path=...,
annotations_directory_path=...,
data_yaml_path=...
data_yaml_path=...,
)
dataset.as_pascal_voc(
images_directory_path=...,
annotations_directory_path=...
annotations_directory_path=...,
)
dataset.as_coco(
images_directory_path=...,
annotations_path=...
annotations_path=...,
)
```
@@ -211,23 +221,23 @@ for path, image, annotation in ds:
sv.DetectionDataset.from_yolo(
images_directory_path=...,
annotations_directory_path=...,
data_yaml_path=...
data_yaml_path=...,
).as_pascal_voc(
images_directory_path=...,
annotations_directory_path=...
annotations_directory_path=...,
)
```
</details>
## 🎬 tutorials
## 🎬 Tutorials
Want to learn how to use Supervision? Explore our [how-to guides](https://supervision.roboflow.com/develop/how_to/detect_and_annotate/), [end-to-end examples](https://github.com/roboflow/supervision/tree/develop/examples), [cheatsheet](https://roboflow.github.io/cheatsheet-supervision/), and [cookbooks](https://supervision.roboflow.com/develop/cookbooks/)!
Want to learn how to use Supervision? Explore our [how-to guides](https://supervision.roboflow.com/develop/how_to/detect_and_annotate/), [end-to-end examples](./examples), [cheatsheet](https://roboflow.github.io/cheatsheet-supervision/), and [cookbooks](https://supervision.roboflow.com/develop/cookbooks/)!
<br/>
<p align="left">
<a href="https://youtu.be/hAWpsIuem10" title="Dwell Time Analysis with Computer Vision | Real-Time Stream Processing"><img src="https://github.com/SkalskiP/SkalskiP/assets/26109316/a742823d-c158-407d-b30f-063a5d11b4e1" alt="Dwell Time Analysis with Computer Vision | Real-Time Stream Processing" width="300px" align="left" /></a>
<a href="https://youtu.be/hAWpsIuem10" title="Dwell Time Analysis with Computer Vision | Real-Time Stream Processing"><img src="https://github.com/user-attachments/assets/014cffc7-72b3-4c0a-bb89-6de265b2c06b" alt="Dwell Time Analysis with Computer Vision | Real-Time Stream Processing" width="300px" align="left" /></a>
<a href="https://youtu.be/hAWpsIuem10" title="Dwell Time Analysis with Computer Vision | Real-Time Stream Processing"><strong>Dwell Time Analysis with Computer Vision | Real-Time Stream Processing</strong></a>
<div><strong>Created: 5 Apr 2024</strong></div>
<br/>Learn how to use computer vision to analyze wait times and optimize processes. This tutorial covers object detection, tracking, and calculating time spent in designated zones. Use these techniques to improve customer experience in retail, traffic management, or other scenarios.</p>
@@ -235,12 +245,12 @@ Want to learn how to use Supervision? Explore our [how-to guides](https://superv
<br/>
<p align="left">
<a href="https://youtu.be/uWP6UjDeZvY" title="Speed Estimation & Vehicle Tracking | Computer Vision | Open Source"><img src="https://github.com/SkalskiP/SkalskiP/assets/26109316/61a444c8-b135-48ce-b979-2a5ab47c5a91" alt="Speed Estimation & Vehicle Tracking | Computer Vision | Open Source" width="300px" align="left" /></a>
<a href="https://youtu.be/uWP6UjDeZvY" title="Speed Estimation & Vehicle Tracking | Computer Vision | Open Source"><img src="https://github.com/user-attachments/assets/b16b8e21-dc6c-4a73-a678-2f7d5d374793" alt="Speed Estimation & Vehicle Tracking | Computer Vision | Open Source" width="300px" align="left" /></a>
<a href="https://youtu.be/uWP6UjDeZvY" title="Speed Estimation & Vehicle Tracking | Computer Vision | Open Source"><strong>Speed Estimation & Vehicle Tracking | Computer Vision | Open Source</strong></a>
<div><strong>Created: 11 Jan 2024</strong></div>
<br/>Learn how to track and estimate the speed of vehicles using YOLO, ByteTrack, and Roboflow Inference. This comprehensive tutorial covers object detection, multi-object tracking, filtering detections, perspective transformation, speed estimation, visualization improvements, and more.</p>
## 💜 built with supervision
## 💜 Built with Supervision
Did you build something cool using supervision? [Let us know!](https://github.com/roboflow/supervision/discussions/categories/built-with-supervision)
@@ -250,13 +260,13 @@ https://github.com/roboflow/supervision/assets/26109316/c9436828-9fbf-4c25-ae8c-
https://github.com/roboflow/supervision/assets/26109316/3ac6982f-4943-4108-9b7f-51787ef1a69f
## 📚 documentation
## 📚 Documentation
Visit our [documentation](https://roboflow.github.io/supervision) page to learn how supervision can help you build computer vision applications faster and more reliably.
## 🏆 contribution
## 🏆 Contribution
We love your input! Please see our [contributing guide](https://github.com/roboflow/supervision/blob/main/CONTRIBUTING.md) to get started. Thank you 🙏 to all our contributors!
We love your input! Please see our [contributing guide](.github/CONTRIBUTING.md) to get started. Thank you 🙏 to all our contributors!
<p align="center">
<a href="https://github.com/roboflow/supervision/graphs/contributors">
@@ -266,8 +276,6 @@ We love your input! Please see our [contributing guide](https://github.com/robof
<br>
<div align="center">
<div align="center">
<a href="https://youtube.com/roboflow">
<img
@@ -302,6 +310,7 @@ We love your input! Please see our [contributing guide](https://github.com/robof
src="https://media.roboflow.com/notebooks/template/icons/purple/forum.png?ik-sdk-version=javascript-1.4.3&updatedAt=1672949633584"
width="3%"
/>
</a>
<img src="https://raw.githubusercontent.com/ultralytics/assets/main/social/logo-transparent.png" width="3%"/>
<a href="https://blog.roboflow.com">
<img
@@ -309,6 +318,4 @@ We love your input! Please see our [contributing guide](https://github.com/robof
width="3%"
/>
</a>
</a>
</div>
</div>
@@ -0,0 +1 @@
0d5d9799b1cc4a39825146388c6781eb
+6
View File
@@ -0,0 +1,6 @@
/*
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; img-src 'self' https: data:; media-src 'self' https: data:; font-src 'self' https: data:; style-src 'self'; script-src 'self'; connect-src 'self' https:;
+27
View File
@@ -0,0 +1,27 @@
---
comments: true
description: About Supervision, Roboflow's open-source Python library for building reusable computer vision workflows.
---
# About Supervision
Supervision is an open-source Python library by Roboflow for building computer vision applications. It gives developers a model-agnostic toolkit for loading predictions, annotating images and video, tracking objects, counting detections in zones, processing datasets, and evaluating model performance.
The project centers on a unified `Detections` API with converters for supported outputs from Ultralytics, Roboflow Inference, Hugging Face Transformers, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers such as Florence-2, PaliGemma, Qwen VL, Gemini, DeepSeek VL 2, and Moondream. That common representation lets teams change models without rewriting annotation, filtering, tracking, dataset, or metrics code.
Supervision is maintained by Roboflow and an open-source contributor community. The library is MIT licensed, developed in public on GitHub, and published on PyPI.
## Project Links
- Source code: [github.com/roboflow/supervision](https://github.com/roboflow/supervision)
- Package: [pypi.org/project/supervision](https://pypi.org/project/supervision/)
- Community: [Roboflow Discord](https://discord.gg/GbfgXGJ8Bk)
- Roboflow: [roboflow.com](https://roboflow.com/)
## Maintainers and Contributors
Supervision has been shaped by Roboflow engineers and community contributors, including Piotr Skalski, Borda, onuralpszr, Soumik Mandal, and many others. The complete contributor history is available in the GitHub repository.
## Citation
If Supervision helps your research or production system, cite the project using the citation block in [llms.txt](https://supervision.roboflow.com/llms.txt) or link to the GitHub repository.
+8 -2
View File
@@ -1,11 +1,11 @@
---
comments: true
description: API reference for supervision's assets module — download sample video and image files for demos, testing, and tutorials.
---
# Assets
Supervision offers an assets download utility that allows you to download video files
that you can use in your demos.
Supervision offers an assets download utility that allows you to download image and video files that you can use in your demos.
<div class="md-typeset">
<h2><a href="#supervision.assets.downloader.download_assets.download_assets">download_assets</a></h2>
@@ -18,3 +18,9 @@ that you can use in your demos.
</div>
:::supervision.assets.list.VideoAssets
<div class="md-typeset">
<h2><a href="#supervision.assets.list.ImageAssets">ImageAssets</a></h2>
</div>
:::supervision.assets.list.ImageAssets
+1261 -695
View File
File diff suppressed because it is too large Load Diff
+1 -5
View File
@@ -1,5 +1 @@
# Code of conduct
```
--8<-- "CODE_OF_CONDUCT.md"
```
--8<-- ".github/CODE_OF_CONDUCT.md"
+29
View File
@@ -0,0 +1,29 @@
---
comments: true
description: Contact and support channels for Supervision documentation, bugs, feature requests, security reports, and community help.
---
# Contact
Use the channel that matches the kind of request you have.
## Bugs and Feature Requests
Open a GitHub issue for reproducible bugs, API requests, documentation fixes, and feature proposals:
[github.com/roboflow/supervision/issues](https://github.com/roboflow/supervision/issues)
## Community Support
Join the Roboflow Discord for community questions, examples, and implementation discussion:
[discord.gg/GbfgXGJ8Bk](https://discord.gg/GbfgXGJ8Bk)
## Package and Source
- PyPI package: [pypi.org/project/supervision](https://pypi.org/project/supervision/)
- GitHub repository: [github.com/roboflow/supervision](https://github.com/roboflow/supervision)
## Security Reports
For security-sensitive reports, avoid posting public exploit details in an issue. Use GitHub's private vulnerability reporting flow for the repository when available, or contact Roboflow through the security and support channels listed on [roboflow.com](https://roboflow.com/).
+1 -1
View File
@@ -1 +1 @@
--8<-- "CONTRIBUTING.md"
--8<-- ".github/CONTRIBUTING.md"
+1
View File
@@ -1,6 +1,7 @@
---
template: cookbooks.html
comments: true
description: Collection of practical computer vision cookbooks — object tracking, zero-shot detection, SAHI small object detection, occupancy analytics, and more.
hide:
- navigation
- toc
+3 -2
View File
@@ -1,12 +1,13 @@
---
comments: true
description: API reference for supervision's DetectionDataset and ClassificationDataset — load, merge, split, and convert datasets in YOLO, COCO, VOC, CreateML, and LabelMe formats.
---
# Datasets
!!! warning
Dataset API is still fluid and may change. If you use Dataset API in your project until further notice, freeze the
`supervision` version in your `requirements.txt` or `setup.py`.
Dataset API is still fluid and may change. If you use Dataset API in your project until further notice, freeze the `supervision` version in your `requirements.txt` or `setup.py`.
<div class="md-typeset">
<h2>DetectionDataset</h2>
-17
View File
@@ -1,17 +0,0 @@
---
comments: true
---
# Datasets Utils
<div class="md-typeset">
<h2><a href="#supervision.dataset.utils.rle_to_mask">rle_to_mask</a></h2>
</div>
:::supervision.dataset.utils.rle_to_mask
<div class="md-typeset">
<h2><a href="#supervision.dataset.utils.mask_to_rle">mask_to_rle</a></h2>
</div>
:::supervision.dataset.utils.mask_to_rle
+29 -21
View File
@@ -5,23 +5,31 @@ status: deprecated
# Deprecated
These features are phased out due to better alternatives or potential issues in future versions. Deprecated functionalities are supported for **five subsequent releases**, providing time for users to transition to updated methods.
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.
- Constructing [`DetectionDataset`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset) and [`ClassificationDataset`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.ClassificationDataset) with parameter `images` as `Dict[str, np.ndarray]` will be removed in `supervision-0.26.0`. Please pass a list of paths `List[str]` instead.
- The `DetectionDataset.images` property will be removed in `supervision-0.26.0`. Please loop over images with `for path, image, annotation in dataset:`, as that does not require loading all images into memory.
- `BoundingBoxAnnotator` has been renamed to `BoxAnnotator` after the old implementation of [`BoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator) has been removed. `BoundingBoxAnnotator` will be removed in `supervision-0.26.0`.
- `overlap_filter_strategy` in [`InferenceSlicer.__init__`](https://supervision.roboflow.com/latest/detection/tools/inference_slicer/) is deprecated and will be removed in `supervision-0.27.0`. Use `overlap_strategy` instead.
- `overlap_ratio_wh` in [`InferenceSlicer.__init__`](https://supervision.roboflow.com/latest/detection/tools/inference_slicer/) is deprecated and will be removed in `supervision-0.27.0`. Use `overlap_wh` instead.
- [`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
### 0.25.0
### 0.27.0
No removals in this version!
- `overlap_ratio_wh` parameter in [`sv.InferenceSlicer`](https://supervision.roboflow.com/latest/detection/tools/inference_slicer/) has been removed. Use the pixel-based `overlap_wh` parameter instead.
- `overlap_filter_strategy` parameter in [`sv.InferenceSlicer`](https://supervision.roboflow.com/latest/detection/tools/inference_slicer/) has been removed. Use `overlap_strategy` instead.
### 0.26.0
- The `sv.DetectionDataset.images` property has been removed in `supervision-0.26.0`. Please loop over images with `for path, image, annotation in dataset:`, as that does not require loading all images into memory. Also, constructing `sv.DetectionDataset` with parameter `images` as `Dict[str, np.ndarray]` is deprecated and has been removed in `supervision-0.26.0`. Please pass a list of paths `List[str]` instead.
- The name `sv.BoundingBoxAnnotator` is deprecated and has been removed in `supervision-0.26.0`. It has been renamed to [`sv.BoxAnnotator`](https://supervision.roboflow.com/0.22.0/detection/annotators/#supervision.annotators.core.BoxAnnotator).
### 0.24.0
@@ -35,12 +43,12 @@ No removals in this version!
### 0.22.0
- `Detections.from_roboflow` is removed as of `supervision-0.22.0`. Use [`Detections.from_inference`](detection/core.md/#supervision.detection.core.Detections.from_inference) instead.
- The method `Color.white()` was removed as of `supervision-0.22.0`. Use the constant `Color.WHITE` instead.
- The method `Color.black()` was removed as of `supervision-0.22.0`. Use the constant `Color.BLACK` instead.
- The method `Color.red()` was removed as of `supervision-0.22.0`. Use the constant `Color.RED` instead.
- The method `Color.green()` was removed as of `supervision-0.22.0`. Use the constant `Color.GREEN` instead.
- The method `Color.blue()` was removed as of `supervision-0.22.0`. Use the constant `Color.BLUE` instead.
- The method `ColorPalette.default()` was removed as of `supervision-0.22.0`. Use the constant [`ColorPalette.DEFAULT`](/utils/draw/#supervision.draw.color.ColorPalette.DEFAULT) instead.
- `BoxAnnotator` was removed as of `supervision-0.22.0`, however `BoundingBoxAnnotator` was immediately renamed to `BoxAnnotator`. Use [`BoxAnnotator`](detection/annotators.md/#supervision.annotators.core.BoxAnnotator) and [`LabelAnnotator`](detection/annotators.md/#supervision.annotators.core.LabelAnnotator) instead of the old `BoxAnnotator`.
- The method `FPSMonitor.__call__` was removed as of `supervision-0.22.0`. Use the attribute [`FPSMonitor.fps`](utils/video.md/#supervision.utils.video.FPSMonitor.fps) instead.
- `sv.Detections.from_roboflow` is removed as of `supervision-0.22.0`. Use [`Detections.from_inference`](detection/core.md/#supervision.detection.core.Detections.from_inference) instead.
- The method `sv.Color.white()` was removed as of `supervision-0.22.0`. Use the constant `sv.Color.WHITE` instead.
- The method `sv.Color.black()` was removed as of `supervision-0.22.0`. Use the constant `sv.Color.BLACK` instead.
- The method `sv.Color.red()` was removed as of `supervision-0.22.0`. Use the constant `sv.Color.RED` instead.
- The method `sv.Color.green()` was removed as of `supervision-0.22.0`. Use the constant `sv.Color.GREEN` instead.
- The method `sv.Color.blue()` was removed as of `supervision-0.22.0`. Use the constant `sv.Color.BLUE` instead.
- The method `sv.ColorPalette.default()` was removed as of `supervision-0.22.0`. Use the constant [`ColorPalette.DEFAULT`](utils/draw.md/#supervision.draw.color.ColorPalette.DEFAULT) instead.
- `sv.BoxAnnotator` was removed as of `supervision-0.22.0`, however `sv.BoundingBoxAnnotator` was immediately renamed to `sv.BoxAnnotator`. Use [`BoxAnnotator`](detection/annotators.md/#supervision.annotators.core.BoxAnnotator) and [`LabelAnnotator`](detection/annotators.md/#supervision.annotators.core.LabelAnnotator) instead of the old `sv.BoxAnnotator`.
- The method `sv.FPSMonitor.__call__` was removed as of `supervision-0.22.0`. Use the attribute [`sv.FPSMonitor.fps`](utils/video.md/#supervision.utils.video.FPSMonitor.fps) instead.
+343 -335
View File
@@ -1,34 +1,35 @@
---
comments: true
status: new
description: API reference for supervision's annotator classes — draw bounding boxes, masks, labels, tracks, and heatmaps on images with one method call.
---
# Annotators
Annotators accept detections and apply box or mask visualizations to the detections. Annotators have many available styles.
=== "Box"
=== "Outlines"
```python
import supervision as sv
=== "Box"
image = ...
detections = sv.Detections(...)
```python
import supervision as sv
box_annotator = sv.BoxAnnotator()
annotated_frame = box_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
image = ...
detections = sv.Detections(...)
<div class="result" markdown>
box_annotator = sv.BoxAnnotator()
annotated_frame = box_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
![bounding-box-annotator-example](https://media.roboflow.com/supervision-annotator-examples/bounding-box-annotator-example-purple.png){ align=center width="800" }
<div class="result" markdown>
</div>
![bounding-box-annotator-example](https://media.roboflow.com/supervision-annotator-examples/bounding-box-annotator-example-purple.png){ align=center width="800" }
</div>
<!--
=== "RoundBox"
```python
@@ -40,7 +41,7 @@ Annotators accept detections and apply box or mask visualizations to the detecti
round_box_annotator = sv.RoundBoxAnnotator()
annotated_frame = round_box_annotator.annotate(
scene=image.copy(),
detections=detections
detections=detections,
)
```
@@ -49,310 +50,312 @@ Annotators accept detections and apply box or mask visualizations to the detecti
![round-box-annotator-example](https://media.roboflow.com/supervision-annotator-examples/round-box-annotator-example-purple.png){ align=center width="800" }
</div>
-->
=== "BoxCorner"
=== "BoxCorner"
```python
import supervision as sv
```python
import supervision as sv
image = ...
detections = sv.Detections(...)
image = ...
detections = sv.Detections(...)
corner_annotator = sv.BoxCornerAnnotator()
annotated_frame = corner_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
corner_annotator = sv.BoxCornerAnnotator()
annotated_frame = corner_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
<div class="result" markdown>
<div class="result" markdown>
![box-corner-annotator-example](https://media.roboflow.com/supervision-annotator-examples/box-corner-annotator-example-purple.png){ align=center width="800" }
![box-corner-annotator-example](https://media.roboflow.com/supervision-annotator-examples/box-corner-annotator-example-purple.png){ align=center width="800" }
</div>
</div>
=== "Color"
=== "Circle"
```python
import supervision as sv
```python
import supervision as sv
image = ...
detections = sv.Detections(...)
image = ...
detections = sv.Detections(...)
color_annotator = sv.ColorAnnotator()
annotated_frame = color_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
circle_annotator = sv.CircleAnnotator()
annotated_frame = circle_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
<div class="result" markdown>
<div class="result" markdown>
![box-mask-annotator-example](https://media.roboflow.com/supervision-annotator-examples/box-mask-annotator-example-purple.png){ align=center width="800" }
![circle-annotator-example](https://media.roboflow.com/supervision-annotator-examples/circle-annotator-example-purple.png){ align=center width="800" }
</div>
</div>
=== "Circle"
=== "Ellipse"
```python
import supervision as sv
```python
import supervision as sv
image = ...
detections = sv.Detections(...)
image = ...
detections = sv.Detections(...)
circle_annotator = sv.CircleAnnotator()
annotated_frame = circle_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
ellipse_annotator = sv.EllipseAnnotator()
annotated_frame = ellipse_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
<div class="result" markdown>
<div class="result" markdown>
![circle-annotator-example](https://media.roboflow.com/supervision-annotator-examples/circle-annotator-example-purple.png){ align=center width="800" }
![ellipse-annotator-example](https://media.roboflow.com/supervision-annotator-examples/ellipse-annotator-example-purple.png){ align=center width="800" }
</div>
</div>
=== "Dot"
=== "Polygon"
```python
import supervision as sv
```python
import supervision as sv
image = ...
detections = sv.Detections(...)
image = ...
detections = sv.Detections(...)
dot_annotator = sv.DotAnnotator()
annotated_frame = dot_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
polygon_annotator = sv.PolygonAnnotator()
annotated_frame = polygon_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
<div class="result" markdown>
<div class="result" markdown>
![dot-annotator-example](https://media.roboflow.com/supervision-annotator-examples/dot-annotator-example-purple.png){ align=center width="800" }
![polygon-annotator-example](https://media.roboflow.com/supervision-annotator-examples/polygon-annotator-example-purple.png){ align=center width="800" }
</div>
</div>
=== "Triangle"
=== "Shading"
```python
import supervision as sv
=== "Color"
image = ...
detections = sv.Detections(...)
```python
import supervision as sv
triangle_annotator = sv.TriangleAnnotator()
annotated_frame = triangle_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
image = ...
detections = sv.Detections(...)
<div class="result" markdown>
color_annotator = sv.ColorAnnotator()
annotated_frame = color_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
![triangle-annotator-example](https://media.roboflow.com/supervision-annotator-examples/triangle-annotator-example.png){ align=center width="800" }
<div class="result" markdown>
</div>
![box-mask-annotator-example](https://media.roboflow.com/supervision-annotator-examples/box-mask-annotator-example-purple.png){ align=center width="800" }
=== "Ellipse"
</div>
```python
import supervision as sv
=== "Halo"
image = ...
detections = sv.Detections(...)
```python
import supervision as sv
ellipse_annotator = sv.EllipseAnnotator()
annotated_frame = ellipse_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
image = ...
detections = sv.Detections(...)
<div class="result" markdown>
halo_annotator = sv.HaloAnnotator()
annotated_frame = halo_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
![ellipse-annotator-example](https://media.roboflow.com/supervision-annotator-examples/ellipse-annotator-example-purple.png){ align=center width="800" }
<div class="result" markdown>
</div>
![halo-annotator-example](https://media.roboflow.com/supervision-annotator-examples/halo-annotator-example-purple.png){ align=center width="800" }
=== "Halo"
</div>
```python
import supervision as sv
=== "Mask"
image = ...
detections = sv.Detections(...)
```python
import supervision as sv
halo_annotator = sv.HaloAnnotator()
annotated_frame = halo_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
image = ...
detections = sv.Detections(...)
<div class="result" markdown>
mask_annotator = sv.MaskAnnotator()
annotated_frame = mask_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
![halo-annotator-example](https://media.roboflow.com/supervision-annotator-examples/halo-annotator-example-purple.png){ align=center width="800" }
!!! note
</div>
`MaskAnnotator` expects `detections.mask` to contain instance segmentation masks aligned to the image passed to `annotate`. For dense masks, provide a boolean array of shape `(N, H, W)` where `(H, W)` matches the image height and width (it also accepts `sv.CompactMask`). If your model returns framework-specific results, convert them to `sv.Detections` first, for example with `sv.Detections.from_ultralytics(...)` or `sv.Detections.from_inference(...)`.
=== "PercentageBar"
<div class="result" markdown>
```python
import supervision as sv
![mask-annotator-example](https://media.roboflow.com/supervision-annotator-examples/mask-annotator-example-purple.png){ align=center width="800" }
image = ...
detections = sv.Detections(...)
</div>
percentage_bar_annotator = sv.PercentageBarAnnotator()
annotated_frame = percentage_bar_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
=== "Markers"
<div class="result" markdown>
=== "Dot"
![percentage-bar-annotator-example](https://media.roboflow.com/supervision-annotator-examples/percentage-bar-annotator-example-purple.png){ align=center width="800" }
```python
import supervision as sv
</div>
image = ...
detections = sv.Detections(...)
=== "Mask"
dot_annotator = sv.DotAnnotator()
annotated_frame = dot_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
```python
import supervision as sv
<div class="result" markdown>
image = ...
detections = sv.Detections(...)
![dot-annotator-example](https://media.roboflow.com/supervision-annotator-examples/dot-annotator-example-purple.png){ align=center width="800" }
mask_annotator = sv.MaskAnnotator()
annotated_frame = mask_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
</div>
<div class="result" markdown>
=== "Triangle"
![mask-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
mask-annotator-example-purple.png){ align=center width="800" }
```python
import supervision as sv
</div>
image = ...
detections = sv.Detections(...)
=== "Polygon"
triangle_annotator = sv.TriangleAnnotator()
annotated_frame = triangle_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
```python
import supervision as sv
<div class="result" markdown>
image = ...
detections = sv.Detections(...)
![triangle-annotator-example](https://media.roboflow.com/supervision-annotator-examples/triangle-annotator-example.png){ align=center width="800" }
polygon_annotator = sv.PolygonAnnotator()
annotated_frame = polygon_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
</div>
<div class="result" markdown>
=== "Labels"
![polygon-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
polygon-annotator-example-purple.png){ align=center width="800" }
=== "Label"
</div>
```python
import supervision as sv
=== "Label"
image = ...
detections = sv.Detections(...)
```python
import supervision as sv
labels = [
f"{class_name} {confidence:.2f}"
for class_name, confidence in zip(
detections["class_name"],
detections.confidence,
)
]
image = ...
detections = sv.Detections(...)
label_annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER)
annotated_frame = label_annotator.annotate(
scene=image.copy(), detections=detections, labels=labels
)
```
labels = [
f"{class_name} {confidence:.2f}"
for class_name, confidence
in zip(detections['class_name'], detections.confidence)
]
<div class="result" markdown>
label_annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER)
annotated_frame = label_annotator.annotate(
scene=image.copy(),
detections=detections,
labels=labels
)
```
![label-annotator-example](https://media.roboflow.com/supervision-annotator-examples/label-annotator-example-purple.png){ align=center width="800" }
<div class="result" markdown>
</div>
![label-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
label-annotator-example-purple.png){ align=center width="800" }
=== "RichLabel"
</div>
```python
import supervision as sv
=== "RichLabel"
image = ...
detections = sv.Detections(...)
```python
import supervision as sv
labels = [
f"{class_name} {confidence:.2f}"
for class_name, confidence in zip(
detections["class_name"],
detections.confidence,
)
]
image = ...
detections = sv.Detections(...)
rich_label_annotator = sv.RichLabelAnnotator(
font_path="TTF_FONT_PATH",
text_position=sv.Position.CENTER,
)
annotated_frame = rich_label_annotator.annotate(
scene=image.copy(),
detections=detections,
labels=labels,
)
```
labels = [
f"{class_name} {confidence:.2f}"
for class_name, confidence
in zip(detections['class_name'], detections.confidence)
]
<div class="result" markdown>
rich_label_annotator = sv.RichLabelAnnotator(
font_path="<TTF_FONT_PATH>",
text_position=sv.Position.CENTER
)
annotated_frame = rich_label_annotator.annotate(
scene=image.copy(),
detections=detections,
labels=labels
)
```
![label-annotator-example](https://media.roboflow.com/supervision-annotator-examples/label-annotator-example-purple.png){ align=center width="800" }
<div class="result" markdown>
</div>
![label-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
label-annotator-example-purple.png){ align=center width="800" }
=== "Transformative"
</div>
=== "Blur"
=== "Icon"
```python
import supervision as sv
```python
import supervision as sv
image = ...
detections = sv.Detections(...)
image = ...
detections = sv.Detections(...)
blur_annotator = sv.BlurAnnotator()
annotated_frame = blur_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
icon_paths = [
"<ICON_PATH>"
for _ in detections
]
<div class="result" markdown>
icon_annotator = sv.IconAnnotator()
annotated_frame = icon_annotator.annotate(
scene=image.copy(),
detections=detections,
icon_path=icon_paths
)
```
![blur-annotator-example](https://media.roboflow.com/supervision-annotator-examples/blur-annotator-example-purple.png){ align=center width="800" }
<div class="result" markdown>
</div>
![icon-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
icon-annotator-example.png){ align=center width="800" }
=== "Pixelate"
</div>
```python
import supervision as sv
<!-- === "Crop"
image = ...
detections = sv.Detections(...)
pixelate_annotator = sv.PixelateAnnotator()
annotated_frame = pixelate_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
<div class="result" markdown>
![pixelate-annotator-example](https://media.roboflow.com/supervision-annotator-examples/pixelate-annotator-example-10.png){ align=center width="800" }
</div>
<!-- === "Crop"
```python
import supervision as sv
@@ -363,167 +366,172 @@ Annotators accept detections and apply box or mask visualizations to the detecti
crop_annotator = sv.CropAnnotator()
annotated_frame = crop_annotator.annotate(
scene=image.copy(),
detections=detections
detections=detections,
)
```
<div class="result" markdown>
![crop-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
crop-annotator-example.png){ align=center width="800" }
![crop-annotator-example](https://media.roboflow.com/supervision-annotator-examples/crop-annotator-example.png){ align=center width="800" }
</div>
-->
=== "Blur"
-->
```python
import supervision as sv
=== "Tracking & Aggregation"
image = ...
detections = sv.Detections(...)
=== "Trace"
blur_annotator = sv.BlurAnnotator()
annotated_frame = blur_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
```python
import supervision as sv
from ultralytics import YOLO
<div class="result" markdown>
model = YOLO("yolov8x.pt")
![blur-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
blur-annotator-example-purple.png){ align=center width="800" }
trace_annotator = sv.TraceAnnotator()
</div>
video_info = sv.VideoInfo.from_video_path(video_path="...")
frames_generator = sv.get_video_frames_generator(source_path="...")
tracker = sv.ByteTrack()
=== "Pixelate"
with sv.VideoSink(target_path="...", video_info=video_info) as sink:
for frame in frames_generator:
result = model(frame)[0]
detections = sv.Detections.from_ultralytics(result)
detections = tracker.update_with_detections(detections)
annotated_frame = trace_annotator.annotate(
scene=frame.copy(),
detections=detections,
)
sink.write_frame(frame=annotated_frame)
```
```python
import supervision as sv
<div class="result" markdown>
image = ...
detections = sv.Detections(...)
![trace-annotator-example](https://media.roboflow.com/supervision-annotator-examples/trace-annotator-example-purple.png){ align=center width="800" }
pixelate_annotator = sv.PixelateAnnotator()
annotated_frame = pixelate_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
</div>
<div class="result" markdown>
=== "HeatMap"
![pixelate-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
pixelate-annotator-example-10.png){ align=center width="800" }
```python
import supervision as sv
from ultralytics import YOLO
</div>
model = YOLO("yolov8x.pt")
=== "Trace"
heat_map_annotator = sv.HeatMapAnnotator()
```python
import supervision as sv
from ultralytics import YOLO
video_info = sv.VideoInfo.from_video_path(video_path="...")
frames_generator = sv.get_video_frames_generator(source_path="...")
model = YOLO('yolov8x.pt')
with sv.VideoSink(target_path="...", video_info=video_info) as sink:
for frame in frames_generator:
result = model(frame)[0]
detections = sv.Detections.from_ultralytics(result)
annotated_frame = heat_map_annotator.annotate(
scene=frame.copy(),
detections=detections,
)
sink.write_frame(frame=annotated_frame)
```
trace_annotator = sv.TraceAnnotator()
<div class="result" markdown>
video_info = sv.VideoInfo.from_video_path(video_path='...')
frames_generator = sv.get_video_frames_generator(source_path='...')
tracker = sv.ByteTrack()
![heat-map-annotator-example](https://media.roboflow.com/supervision-annotator-examples/heat-map-annotator-example-purple.png){ align=center width="800" }
with sv.VideoSink(target_path='...', video_info=video_info) as sink:
for frame in frames_generator:
result = model(frame)[0]
detections = sv.Detections.from_ultralytics(result)
detections = tracker.update_with_detections(detections)
annotated_frame = trace_annotator.annotate(
scene=frame.copy(),
detections=detections)
sink.write_frame(frame=annotated_frame)
```
</div>
<div class="result" markdown>
=== "Others"
![trace-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
trace-annotator-example-purple.png){ align=center width="800" }
=== "PercentageBar"
</div>
```python
import supervision as sv
=== "HeatMap"
image = ...
detections = sv.Detections(...)
```python
import supervision as sv
from ultralytics import YOLO
percentage_bar_annotator = sv.PercentageBarAnnotator()
annotated_frame = percentage_bar_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
model = YOLO('yolov8x.pt')
<div class="result" markdown>
heat_map_annotator = sv.HeatMapAnnotator()
![percentage-bar-annotator-example](https://media.roboflow.com/supervision-annotator-examples/percentage-bar-annotator-example-purple.png){ align=center width="800" }
video_info = sv.VideoInfo.from_video_path(video_path='...')
frames_generator = sv.get_video_frames_generator(source_path='...')
</div>
with sv.VideoSink(target_path='...', video_info=video_info) as sink:
for frame in frames_generator:
result = model(frame)[0]
detections = sv.Detections.from_ultralytics(result)
annotated_frame = heat_map_annotator.annotate(
scene=frame.copy(),
detections=detections)
sink.write_frame(frame=annotated_frame)
```
=== "Icon"
<div class="result" markdown>
```python
import supervision as sv
![heat-map-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
heat-map-annotator-example-purple.png){ align=center width="800" }
image = ...
detections = sv.Detections(...)
</div>
icon_paths = ["<ICON_PATH>" for _ in detections]
=== "Background Color"
icon_annotator = sv.IconAnnotator()
annotated_frame = icon_annotator.annotate(
scene=image.copy(),
detections=detections,
icon_path=icon_paths,
)
```
```python
import supervision as sv
<div class="result" markdown>
image = ...
detections = sv.Detections(...)
![icon-annotator-example](https://media.roboflow.com/supervision-annotator-examples/icon-annotator-example.png){ align=center width="800" }
background_overlay_annotator = sv.BackgroundOverlayAnnotator()
annotated_frame = background_overlay_annotator.annotate(
scene=image.copy(),
detections=detections
)
```
</div>
<div class="result" markdown>
=== "Background Color"
![background-overlay-annotator-example](https://media.roboflow.com/supervision-annotator-examples/background-color-annotator-example-purple.png){ align=center width="800" }
```python
import supervision as sv
</div>
image = ...
detections = sv.Detections(...)
=== "Comparison"
background_overlay_annotator = sv.BackgroundOverlayAnnotator()
annotated_frame = background_overlay_annotator.annotate(
scene=image.copy(),
detections=detections,
)
```
```python
import supervision as sv
<div class="result" markdown>
image = ...
detections_1 = sv.Detections(...)
detections_2 = sv.Detections(...)
![background-overlay-annotator-example](https://media.roboflow.com/supervision-annotator-examples/background-color-annotator-example-purple.png){ align=center width="800" }
comparison_annotator = sv.ComparisonAnnotator()
annotated_frame = comparison_annotator.annotate(
scene=image.copy(),
detections_1=detections_1,
detections_2=detections_2
)
```
</div>
<div class="result" markdown>
=== "Comparison"
![comparison-annotator-example](https://media.roboflow.com/supervision-annotator-examples/
comparison-annotator-example.png){ align=center width="800" }
```python
import supervision as sv
</div>
image = ...
detections_1 = sv.Detections(...)
detections_2 = sv.Detections(...)
comparison_annotator = sv.ComparisonAnnotator()
annotated_frame = comparison_annotator.annotate(
scene=image.copy(),
detections_1=detections_1,
detections_2=detections_2,
)
```
<div class="result" markdown>
![comparison-annotator-example](https://media.roboflow.com/supervision-annotator-examples/comparison-annotator-example.png){ align=center width="800" }
</div>
<div class="md-typeset">
<h2>Try Supervision Annotators on your own image</h2>
+7
View File
@@ -0,0 +1,7 @@
---
comments: true
---
# CompactMask
:::supervision.detection.compact_mask.CompactMask
+1 -1
View File
@@ -1,6 +1,6 @@
---
comments: true
status: new
description: API reference for supervision's Detections class — the core data structure for bounding boxes, masks, confidence scores, and tracker IDs.
---
# Detections
-29
View File
@@ -1,29 +0,0 @@
---
comments: true
---
# Double Detection Filter
<div class="md-typeset">
<h2><a href="#supervision.detection.overlap_filter.OverlapFilter">OverlapFilter</a></h2>
</div>
:::supervision.detection.overlap_filter.OverlapFilter
<div class="md-typeset">
<h2><a href="#supervision.detection.overlap_filter.box_non_max_suppression">box_non_max_suppression</a></h2>
</div>
:::supervision.detection.overlap_filter.box_non_max_suppression
<div class="md-typeset">
<h2><a href="#supervision.detection.overlap_filter.mask_non_max_suppression">mask_non_max_suppression</a></h2>
</div>
:::supervision.detection.overlap_filter.mask_non_max_suppression
<div class="md-typeset">
<h2><a href="#supervision.detection.overlap_filter.box_non_max_merge">box_non_max_merge</a></h2>
</div>
:::supervision.detection.overlap_filter.box_non_max_merge
+7 -2
View File
@@ -4,8 +4,13 @@ comments: true
# Legacy Metrics
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.
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>
+47
View File
@@ -4,4 +4,51 @@ comments: true
# InferenceSlicer
## GeoTIFF Datasets
Install the optional GeoTIFF dependencies before running this example:
```bash
pip install "supervision[geotiff]"
wget -O RGB.byte.tif https://raw.githubusercontent.com/rasterio/rasterio/main/tests/data/RGB.byte.tif
```
`InferenceSlicer` can read an open `rasterio` dataset window-by-window. This keeps large GeoTIFFs out of memory while passing each tile to the callback as an `(H, W, C)` NumPy array.
```python
import numpy as np
import rasterio
import supervision as sv
def callback(tile: np.ndarray) -> sv.Detections:
h, w = tile.shape[:2]
return sv.Detections(
xyxy=np.array([[w * 0.25, h * 0.25, w * 0.75, h * 0.75]], dtype=float),
confidence=np.array([0.9]),
class_id=np.array([0]),
)
slicer = sv.InferenceSlicer(
callback=callback,
slice_wh=(256, 256),
overlap_wh=(64, 64),
overlap_filter=sv.OverlapFilter.NONE,
)
with rasterio.open("RGB.byte.tif") as dataset:
detections = slicer(dataset)
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
-1
View File
@@ -1,6 +1,5 @@
---
comments: true
status: new
---
<div class="md-typeset">
-120
View File
@@ -1,120 +0,0 @@
---
comments: true
status: new
---
# Detection Utils
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.box_iou_batch">box_iou_batch</a></h2>
</div>
:::supervision.detection.utils.box_iou_batch
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.mask_iou_batch">mask_iou_batch</a></h2>
</div>
:::supervision.detection.utils.mask_iou_batch
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.oriented_box_iou_batch">oriented_box_iou_batch</a></h2>
</div>
:::supervision.detection.utils.oriented_box_iou_batch
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.polygon_to_mask">polygon_to_mask</a></h2>
</div>
:::supervision.detection.utils.polygon_to_mask
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.mask_to_xyxy">mask_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.mask_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.mask_to_polygons">mask_to_polygons</a></h2>
</div>
:::supervision.detection.utils.mask_to_polygons
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.polygon_to_xyxy">polygon_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.polygon_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.filter_polygons_by_area">filter_polygons_by_area</a></h2>
</div>
:::supervision.detection.utils.filter_polygons_by_area
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.move_boxes">move_boxes</a></h2>
</div>
:::supervision.detection.utils.move_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.move_masks">move_masks</a></h2>
</div>
:::supervision.detection.utils.move_masks
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.scale_boxes">scale_boxes</a></h2>
</div>
:::supervision.detection.utils.scale_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.clip_boxes">clip_boxes</a></h2>
</div>
:::supervision.detection.utils.clip_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.pad_boxes">pad_boxes</a></h2>
</div>
:::supervision.detection.utils.pad_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.xywh_to_xyxy">xywh_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.xywh_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.xyxy_to_xywh">xyxy_to_xywh</a></h2>
</div>
:::supervision.detection.utils.xyxy_to_xywh
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.xyxy_to_xcycarh">xyxy_to_xcycarh</a></h2>
</div>
:::supervision.detection.utils.xyxy_to_xcycarh
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.xcycwh_to_xyxy">xcycwh_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.xcycwh_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.contains_holes">contains_holes</a></h2>
</div>
:::supervision.detection.utils.contains_holes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.contains_multiple_segments">contains_multiple_segments</a></h2>
</div>
:::supervision.detection.utils.contains_multiple_segments
+41
View File
@@ -0,0 +1,41 @@
---
comments: true
---
# Boxes Utils
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.boxes.move_boxes">move_boxes</a></h2>
</div>
:::supervision.detection.utils.boxes.move_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.boxes.scale_boxes">scale_boxes</a></h2>
</div>
:::supervision.detection.utils.boxes.scale_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.boxes.clip_boxes">clip_boxes</a></h2>
</div>
:::supervision.detection.utils.boxes.clip_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.boxes.pad_boxes">pad_boxes</a></h2>
</div>
:::supervision.detection.utils.boxes.pad_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.boxes.denormalize_boxes">denormalize_boxes</a></h2>
</div>
:::supervision.detection.utils.boxes.denormalize_boxes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.boxes.xyxyxyxy_to_xyxy">xyxyxyxy_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.boxes.xyxyxyxy_to_xyxy
+84
View File
@@ -0,0 +1,84 @@
---
comments: true
status: new
---
# Converters Utils
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.xyxy_to_xywh">xyxy_to_xywh</a></h2>
</div>
:::supervision.detection.utils.converters.xyxy_to_xywh
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.xywh_to_xyxy">xywh_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.converters.xywh_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.xyxy_to_xcycarh">xyxy_to_xcycarh</a></h2>
</div>
:::supervision.detection.utils.converters.xyxy_to_xcycarh
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.xcycwh_to_xyxy">xcycwh_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.converters.xcycwh_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.xyxy_to_polygons">xyxy_to_polygons</a></h2>
</div>
:::supervision.detection.utils.converters.xyxy_to_polygons
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.mask_to_xyxy">mask_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.converters.mask_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.mask_to_polygons">mask_to_polygons</a></h2>
</div>
:::supervision.detection.utils.converters.mask_to_polygons
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.polygon_to_mask">polygon_to_mask</a></h2>
</div>
:::supervision.detection.utils.converters.polygon_to_mask
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.polygon_to_xyxy">polygon_to_xyxy</a></h2>
</div>
:::supervision.detection.utils.converters.polygon_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.xyxy_to_mask">xyxy_to_mask</a></h2>
</div>
:::supervision.detection.utils.converters.xyxy_to_mask
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.rle_to_mask">rle_to_mask</a></h2>
</div>
:::supervision.detection.utils.converters.rle_to_mask
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.mask_to_rle">mask_to_rle</a></h2>
</div>
:::supervision.detection.utils.converters.mask_to_rle
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.converters.is_compressed_rle">is_compressed_rle</a></h2>
</div>
:::supervision.detection.utils.converters.is_compressed_rle
+95
View File
@@ -0,0 +1,95 @@
---
comments: true
---
# IoU and NMS Utils
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.OverlapFilter">OverlapFilter</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.OverlapFilter
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.OverlapMetric">OverlapMetric</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.OverlapMetric
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.utils.box_iou">box_iou</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.box_iou
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.box_iou_batch">box_iou_batch</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.box_iou_batch
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.box_iou_batch_with_jaccard">box_iou_batch_with_jaccard</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.box_iou_batch_with_jaccard
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.mask_iou_batch">mask_iou_batch</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.mask_iou_batch
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.oriented_box_iou_batch">oriented_box_iou_batch</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.oriented_box_iou_batch
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.box_non_max_suppression">box_non_max_suppression</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.box_non_max_suppression
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.box_soft_non_max_suppression">box_soft_non_max_suppression</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.box_soft_non_max_suppression
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.mask_non_max_suppression">mask_non_max_suppression</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.mask_non_max_suppression
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.mask_soft_non_max_suppression">mask_soft_non_max_suppression</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.mask_soft_non_max_suppression
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.box_non_max_merge">box_non_max_merge</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.box_non_max_merge
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.mask_non_max_merge">mask_non_max_merge</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.mask_non_max_merge
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.oriented_box_non_max_suppression">oriented_box_non_max_suppression</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.oriented_box_non_max_suppression
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.iou_and_nms.oriented_box_non_max_merge">oriented_box_non_max_merge</a></h2>
</div>
:::supervision.detection.utils.iou_and_nms.oriented_box_non_max_merge
+42
View File
@@ -0,0 +1,42 @@
---
comments: true
status: new
---
# Masks Utils
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.masks.mask_to_roi">mask_to_roi</a></h2>
</div>
:::supervision.detection.utils.masks.mask_to_roi
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.masks.move_masks">move_masks</a></h2>
</div>
:::supervision.detection.utils.masks.move_masks
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.masks.contains_holes">contains_holes</a></h2>
</div>
:::supervision.detection.utils.masks.contains_holes
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.masks.contains_multiple_segments">contains_multiple_segments</a></h2>
</div>
:::supervision.detection.utils.masks.contains_multiple_segments
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.masks.filter_segments_by_distance">filter_segments_by_distance</a></h2>
</div>
:::supervision.detection.utils.masks.filter_segments_by_distance
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.masks.calculate_masks_centroids">calculate_masks_centroids</a></h2>
</div>
:::supervision.detection.utils.masks.calculate_masks_centroids
+17
View File
@@ -0,0 +1,17 @@
---
comments: true
---
# Polygons Utils
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.polygons.filter_polygons_by_area">filter_polygons_by_area</a></h2>
</div>
:::supervision.detection.utils.polygons.filter_polygons_by_area
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.polygons.approximate_polygon">approximate_polygon</a></h2>
</div>
:::supervision.detection.utils.polygons.approximate_polygon
+36
View File
@@ -0,0 +1,36 @@
---
comments: true
status: new
---
# 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>
</div>
:::supervision.detection.utils.vlms.edit_distance
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.vlms.fuzzy_match_index">fuzzy_match_index</a></h2>
</div>
:::supervision.detection.utils.vlms.fuzzy_match_index
+81
View File
@@ -0,0 +1,81 @@
---
comments: true
description: Frequently asked questions about installing Supervision, supported computer vision models, datasets, tracking, metrics, and licensing.
---
# Frequently Asked Questions
## What is Supervision?
Supervision is an open-source Python library by Roboflow for computer vision workflows. It provides a unified `Detections` class with converters for supported object detection, segmentation, and VLM outputs.
## How do I install Supervision?
Install the base package with:
```bash
pip install supervision
```
Use the `metrics` extra when you need optional metric dependencies:
```bash
pip install "supervision[metrics]"
```
Sample asset utilities are part of the base package under `supervision.assets`.
Supervision does not install OpenCV. Its image, drawing, and file-video APIs use the included fallback when `cv2` is unavailable, and automatically use a compatible `cv2` already present in your environment. See the [OpenCV migration guide](how_to/opencv_migration.md) when upgrading an existing environment or choosing an OpenCV wheel yourself.
## Which object detection models work with Supervision?
Supervision is model agnostic. `sv.Detections` includes converters for Ultralytics YOLO, Roboflow Inference, Hugging Face Transformers outputs, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers including Florence-2, PaliGemma, Qwen VL, Gemini, DeepSeek VL 2, and Moondream. Keypoint outputs have separate `sv.KeyPoints` converters, including MediaPipe.
## What can I do with Supervision?
You can annotate images and video, filter detections, track objects, count objects in zones or across lines, load and convert datasets, evaluate models with detection metrics, and export predictions for downstream analysis.
## 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()`, 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?
For detection datasets, Supervision supports YOLO, COCO JSON, Pascal VOC, CreateML, and LabelMe. Use `DetectionDataset.from_yolo()`, `DetectionDataset.from_coco()`, `DetectionDataset.from_pascal_voc()`, `DetectionDataset.from_createml()`, or `DetectionDataset.from_labelme()` to load datasets, and the matching `as_*` methods to export them.
## How do I count objects in a zone?
Use `sv.PolygonZone` for arbitrary polygon regions and `sv.LineZone` for line-crossing counts. Line crossing requires `detections.tracker_id`, so run a tracker before calling the line zone trigger.
## How do I benchmark a model?
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?
Yes. Supervision is free and open source under the MIT license.
## How do I process frames from a webcam with supervision?
Supervision does not support live camera capture. Manage the capture device yourself with `cv2.VideoCapture`, which works regardless of which OpenCV wheel (`opencv-python` or `opencv-python-headless`) is installed, and pass individual frames to supervision annotators:
```python
import cv2 # requires: pip install opencv-python (or opencv-python-headless)
import supervision as sv
cap = cv2.VideoCapture(0)
annotator = sv.BoxAnnotator()
while True:
ret, frame = cap.read()
if not ret:
break
# run your detector, then annotate:
# annotated = annotator.annotate(frame, detections)
cap.release()
```
## Where is the source code?
The source code is available at [github.com/roboflow/supervision](https://github.com/roboflow/supervision).
+74 -37
View File
@@ -1,6 +1,11 @@
---
comments: true
status: new
description: Benchmark object detection models with supervision — compute mAP, confusion matrix, and per-class metrics to compare model performance.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
date_modified: 2026-04-22
---
![Corgi Example](https://media.roboflow.com/supervision/image-examples/how-to/benchmark-models/corgi-sorted-2.png)
@@ -37,14 +42,9 @@ We'll use the following libraries:
- `supervision` to evaluate the model results
```bash
pip install roboflow supervision
pip install git+https://github.com/roboflow/inference.git@linas/allow-latest-rc-supervision
pip install roboflow inference "supervision[metrics]"
```
!!! info
We're updating `inference` at the moment. Please install it as shown above.
Here's how you can download a dataset:
```python
@@ -52,7 +52,7 @@ from roboflow import Roboflow
rf = Roboflow(api_key="<YOUR_API_KEY>")
project = rf.workspace("<WORKSPACE_NAME>").project("<PROJECT_NAME>")
dataset = project.version(<DATASET_VERSION_NUMBER>).download("<FORMAT>")
dataset = project.version("<DATASET_VERSION_NUMBER>").download("<FORMAT>")
```
If your dataset is from Universe, go to `Dataset` > `Download Dataset` > select the format (e.g. `YOLOv11`) > `Show download code`.
@@ -75,6 +75,8 @@ This will create a folder called `Corgi-v2-4` with the dataset in the current wo
Let's load a model.
Select and instantiate the detection or segmentation model you want to benchmark. Supervision works with Roboflow Inference for both local and cloud-deployed models, as well as Ultralytics YOLO checkpoints. Choose the tab below that matches your preferred framework, then pass images to the loaded model during the evaluation loop.
=== "Inference, Local"
Roboflow supports a range of state-of-the-art [pre-trained models](https://inference.roboflow.com/quickstart/aliases/) for object detection, instance segmentation, and pose tracking. You don't even need an API key!
@@ -123,8 +125,7 @@ Evaluating your model requires careful selection of the dataset. Which images sh
- **Validation Set**: This is the set of images used to validate the model during training. Every Nth training epoch, the model is evaluated on the validation set. Often the training is stopped once the validation loss stops improving. Therefore, even while the images aren't used to train the model, it still indirectly influences the training outcome.
- **Test Set**: This is the set of images kept aside for model testing. It is exactly the set you should use for benchmarking. If the dataset was split correctly, none of these images would be shown to the model during training.
Therefore, an unrelated dataset or the `test` set is the best choice for benchmarking.
Several other problems may arise:
Therefore, an unrelated dataset or the `test` set is the best choice for benchmarking. Several other problems may arise:
- **Extra Classes**: An unrelated dataset may contain additional classes which you may need to [filter out](https://supervision.roboflow.com/how_to/filter_detections/#by-set-of-classes) before computing metrics.
- **Class Mismatch**: In an unrelated dataset, the class names or IDs may be different to what your model produces, you'll need to remap them, which is [shown in this guide](#running-a-model).
@@ -138,8 +139,7 @@ At this stage, you should have:
- A dataset of labeled images to evaluate the model.
- A model prepared for benchmarking.
With these ready, we can now run the model and obtain predictions.
We'll use `supervision` to create a dataset iterator, and then run the model on each image.
With these ready, we can now run the model and obtain predictions. We'll use `supervision` to create a dataset iterator, and then run the model on each image.
=== "Inference"
@@ -149,7 +149,7 @@ We'll use `supervision` to create a dataset iterator, and then run the model on
test_set = sv.DetectionDataset.from_yolo(
images_directory_path=f"{dataset.location}/test/images",
annotations_directory_path=f"{dataset.location}/test/labels",
data_yaml_path=f"{dataset.location}/data.yaml"
data_yaml_path=f"{dataset.location}/data.yaml",
)
image_paths = []
@@ -173,7 +173,7 @@ We'll use `supervision` to create a dataset iterator, and then run the model on
test_set = sv.DetectionDataset.from_yolo(
images_directory_path=f"{dataset.location}/test/images",
annotations_directory_path=f"{dataset.location}/test/labels",
data_yaml_path=f"{dataset.location}/data.yaml"
data_yaml_path=f"{dataset.location}/data.yaml",
)
image_paths = []
@@ -191,8 +191,7 @@ We'll use `supervision` to create a dataset iterator, and then run the model on
## Remapping classes
Did you notice an issue in the above logic?
Since we're using an unrelated dataset, the class names and IDs may be different from what the model was trained on.
Did you notice an issue in the above logic? Since we're using an unrelated dataset, the class names and IDs may be different from what the model was trained on.
We need to remap them to match the dataset classes. Here's how to do it:
@@ -200,14 +199,16 @@ We need to remap them to match the dataset classes. Here's how to do it:
def remap_classes(
detections: sv.Detections,
class_ids_from_to: dict[int, int],
class_names_from_to: dict[str, str]
class_names_from_to: dict[str, str],
) -> None:
new_class_ids = [
class_ids_from_to.get(class_id, class_id) for class_id in detections.class_id]
class_ids_from_to.get(class_id, class_id) for class_id in detections.class_id
]
detections.class_id = np.array(new_class_ids)
new_class_names = [
class_names_from_to.get(name, name) for name in detections["class_name"]]
class_names_from_to.get(name, name) for name in detections["class_name"]
]
predictions["class_name"] = np.array(new_class_names)
```
@@ -223,7 +224,7 @@ Let's also remove the predictions that are not in the dataset classes.
test_set = sv.DetectionDataset.from_yolo(
images_directory_path=f"{dataset.location}/test/images",
annotations_directory_path=f"{dataset.location}/test/labels",
data_yaml_path=f"{dataset.location}/data.yaml"
data_yaml_path=f"{dataset.location}/data.yaml",
)
image_paths = []
@@ -237,11 +238,9 @@ Let's also remove the predictions that are not in the dataset classes.
remap_classes(
detections=predictions,
class_ids_from_to={16: 0},
class_names_from_to={"dog": "Corgi"}
class_names_from_to={"dog": "Corgi"},
)
predictions = predictions[
np.isin(predictions["class_name"], test_set.classes)
]
predictions = predictions[np.isin(predictions["class_name"], test_set.classes),]
image_paths.append(image_path)
predictions_list.append(predictions)
@@ -252,8 +251,7 @@ Let's also remove the predictions that are not in the dataset classes.
Dataset class names and IDs can be found in the `data.yaml` file, or by printing `dataset.classes`.
Each model will have a different class mapping, so make sure to check the model's documentation. In this case, the model was trained on the COCO dataset, with a class
configuration found [here](https://github.com/ultralytics/ultralytics/blob/main/ultralytics/cfg/datasets/coco8.yaml).
Each model will have a different class mapping, so make sure to check the model's documentation. In this case, the model was trained on the COCO dataset, with a class configuration found [here](https://github.com/ultralytics/ultralytics/blob/main/ultralytics/cfg/datasets/coco8.yaml).
```python
import supervision as sv
@@ -261,7 +259,7 @@ Let's also remove the predictions that are not in the dataset classes.
test_set = sv.DetectionDataset.from_yolo(
images_directory_path=f"{dataset.location}/test/images",
annotations_directory_path=f"{dataset.location}/test/labels",
data_yaml_path=f"{dataset.location}/data.yaml"
data_yaml_path=f"{dataset.location}/data.yaml",
)
image_paths = []
@@ -275,11 +273,9 @@ Let's also remove the predictions that are not in the dataset classes.
remap_classes(
detections=predictions,
class_ids_from_to={16: 0},
class_names_from_to={"dog": "Corgi"}
class_names_from_to={"dog": "Corgi"},
)
predictions = predictions[
np.isin(predictions["class_name"], test_set.classes)
]
predictions = predictions[np.isin(predictions["class_name"], test_set.classes),]
image_paths.append(image_path)
predictions_list.append(predictions)
@@ -288,8 +284,7 @@ Let's also remove the predictions that are not in the dataset classes.
## Visualizing Predictions
The first step in evaluating your model’s performance is to visualize its predictions.
This gives an intuitive sense of how well your model is detecting objects and where it might be failing.
The first step in evaluating your model’s performance is to visualize its predictions. This gives an intuitive sense of how well your model is detecting objects and where it might be failing.
```python
import supervision as sv
@@ -298,16 +293,22 @@ N = 9
GRID_SIZE = (3, 3)
target_annotator = sv.PolygonAnnotator(color=sv.Color.from_hex("#8315f9"), thickness=8)
prediction_annotator = sv.PolygonAnnotator(color=sv.Color.from_hex("#00cfc6"), thickness=6)
prediction_annotator = sv.PolygonAnnotator(
color=sv.Color.from_hex("#00cfc6"), thickness=6
)
annotated_images = []
for image_path, predictions, targets in zip(
image_paths[:N], predictions_list[:N], targets_list[:N]
image_paths[:N], predictions_list[:N], targets_list[:N]
):
annotated_image = cv2.imread(image_path)
annotated_image = target_annotator.annotate(scene=annotated_image, detections=targets)
annotated_image = prediction_annotator.annotate(scene=annotated_image, detections=prediction)
annotated_image = target_annotator.annotate(
scene=annotated_image, detections=targets
)
annotated_image = prediction_annotator.annotate(
scene=annotated_image, detections=prediction
)
annotated_images.append(annotated_image)
sv.plot_images_grid(images=annotated_images, grid_size=GRID_SIZE)
@@ -323,6 +324,20 @@ Here, predictions in purple are targets (ground truth), and predictions in teal
See [annotator documentation](https://supervision.roboflow.com/latest/detection/annotators/) for even more options.
## Visual Benchmarking
To inspect where a model succeeds and fails, pass `save_directory_path` to `sv.ConfusionMatrix.benchmark(...)`. For every dataset image it writes a 2x2 result grid — `Ground Truth`, `True Positives`, `False Positives`, and `False Negatives` panels — directly into that directory, reusing the original image filenames. This makes it easy to skim through per-image outcomes alongside the aggregate confusion matrix.
```python
import supervision as sv
confusion_matrix = sv.ConfusionMatrix.benchmark(
dataset=test_set,
callback=callback,
save_directory_path="./results",
)
```
## Benchmarking Metrics
With multiple models, fine details matter. Visual inspection may not be enough. `supervision` provides a collection of metrics that help obtain precise numerical results of model performance.
@@ -439,3 +454,25 @@ A condensed version of this guide is also available as a [Colab Notebook](https:
For more details, be sure to check out our [documentation](https://supervision.roboflow.com/latest/) and join our community discussions. If you find any issues, please let us know on [GitHub](https://github.com/roboflow/supervision/issues).
Best of luck with your benchmarking!
## Frequently Asked Questions
### How do I benchmark a model with supervision?
Use `supervision.metrics.mean_average_precision.MeanAveragePrecision` — accumulate prediction and ground-truth `Detections` with `update(...)` and then call `compute()`. For confusion matrices, use `sv.ConfusionMatrix.from_detections(predictions=predictions, targets=targets, classes=classes)`.
### What IoU thresholds does MeanAveragePrecision use?
It computes mAP over IoU thresholds from 0.50 to 0.95 in steps of 0.05 (mAP@50:95), plus mAP@50 and mAP@75 individually.
### Can I benchmark segmentation models?
Yes, if you want to evaluate their bounding boxes. Convert model outputs to `Detections` and pass them to `MeanAveragePrecision.update(...)`; the current mAP path prepares COCO-style bounding boxes from `detections.xyxy`.
### What is a ConfusionMatrix and how do I use it?
`sv.ConfusionMatrix` visualizes true positives, false positives, and false negatives per class. Create one with `sv.ConfusionMatrix.from_detections(predictions=predictions, targets=targets, classes=classes, conf_threshold=0.5, iou_threshold=0.5)`, then call `confusion_matrix.plot()` to render a heatmap. If you want per-image validation visualizations saved to disk, pass `save_directory_path="./results"` to `sv.ConfusionMatrix.benchmark(...)`; it will write 2x2 result grids directly into that directory using the original image filenames, with `Ground Truth`, `True Positives`, `False Positives`, and `False Negatives` panels.
## Author
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
+150
View File
@@ -0,0 +1,150 @@
---
comments: true
description: Count objects entering a polygon zone in images and video using supervision's PolygonZone — measure throughput and density in any region.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
date_modified: 2026-04-22
---
With supervision, you can count the number of objects in a zone in an image or video. In this guide, we will show how to count the number of cars in a traffic video.
[View the notebook that accompanies this tutorial](https://github.com/roboflow/notebooks/blob/main/notebooks/how-to-use-polygonzone-annotate-and-supervision.ipynb).
To make it easier for you to follow our tutorial download the video we will use as an example. You can do this using the `supervision.assets` module:
```python
from supervision.assets import download_assets, VideoAssets
download_assets(VideoAssets.VEHICLES_2)
```
## Initialize a Model and Load Video
First, we need to initialize a model. Let's use a YOLOv8 model with the default COCO checkpoint. We also need to load a video on which to run inference.
Create a YOLO model instance and download the source video. The model will process each frame during inference. A shared color palette ensures consistent zone coloring throughout the output video.
```python
import numpy as np
import supervision as sv
import cv2
from ultralytics import YOLO
from supervision.assets import VideoAssets, download_assets
model = YOLO("yolov8s.pt")
VIDEO = download_assets(VideoAssets.VEHICLES_2)
colors = sv.ColorPalette.DEFAULT
```
## Calculate Coordinates
To count objects in a zone, you need to know the coordinates where you want to draw the zone.
You can calculate coordinates using the [PolygonZone web utility](https://roboflow.github.io/polygonzone/).
To use the PolygonZone website, you will need to upload an image or frame from a video. You can retrieve a frame using this code:
```python
generator = sv.get_video_frames_generator(VIDEO)
iterator = iter(generator)
frame = next(iterator)
cv2.imwrite("first_frame.png", frame)
```
PolygonZone will give you NumPy arrays that you can use with supervision to count objects in zones.
<video width="100%" loop muted autoplay>
<source src="https://media.roboflow.com/polygonzone.mp4" type="video/mp4">
</video>
Save the coordinates in an array:
```python
polygons = [
np.array([[718, 595], [927, 592], [851, 1062], [42, 1059]]),
np.array([[987, 595], [1199, 595], [1893, 1056], [1015, 1062]]),
]
```
## Define Zones
With the coordinates of the zones to draw ready, we can set up our zones:
Instantiate a `PolygonZone` for each polygon array, pairing it with a `PolygonZoneAnnotator` for visual overlay and a `BoxAnnotator` for drawing detection boxes. Each zone will later trigger on incoming detections to determine which objects fall inside its boundaries, enabling per-zone counting in the inference callback.
```python
zones = [sv.PolygonZone(polygon=polygon) for polygon in polygons]
zone_annotators = [
sv.PolygonZoneAnnotator(
zone=zone,
color=colors.by_idx(index),
thickness=4,
text_thickness=8,
text_scale=4,
)
for index, zone in enumerate(zones)
]
box_annotators = [
sv.BoxAnnotator(
color=colors.by_idx(index),
thickness=4,
)
for index in range(len(polygons))
]
```
## Run Inference
We can run inference on a video using the [sv.process_video](https://supervision.roboflow.com/utils/video/#process_video) function. This function accepts a callback that runs inference on each frame and compiles the results into a video.
Below, we can call our YOLOv8 model, annotate predictions and zones, then save the results to a file called `result.mp4`.
```python
def process_frame(frame: np.ndarray, i) -> np.ndarray:
results = model(frame, imgsz=1280, verbose=False)[0]
detections = sv.Detections.from_ultralytics(results)
for zone, zone_annotator, box_annotator in zip(
zones, zone_annotators, box_annotators
):
mask = zone.trigger(detections=detections)
detections_filtered = detections[mask]
frame = box_annotator.annotate(scene=frame, detections=detections_filtered)
frame = zone_annotator.annotate(scene=frame)
return frame
sv.process_video(source_path=VIDEO, target_path="result.mp4", callback=process_frame)
```
Here is an example of inference run on the video:
<video width="100%" loop muted autoplay>
<source src="https://blog.roboflow.com/content/media/2023/03/trim-counting.mp4" type="video/mp4">
</video>
## Frequently Asked Questions
### How do I count objects in a zone with supervision?
Create `sv.PolygonZone` with a polygon defining your region. Call `zone.trigger(detections)` on each frame — it returns a mask of detections inside the zone.
### Can I count objects crossing a line instead of entering a zone?
Yes. Use `sv.LineZone` — define a start and end point. `zone.trigger(detections)` returns a tuple of two boolean arrays, `(crossed_in, crossed_out)`, indicating which detections crossed the line in each direction. `LineZone` requires `detections.tracker_id`; run a tracker first so the same object can be matched across frames.
### Can I combine zone counting with tracking?
Yes. You can pass tracker IDs from `sv.ByteTrack` alongside your detections, but `sv.PolygonZone` still evaluates the zone on each frame and reports which objects are currently inside it. If you want to count each object only once when it first enters the zone, maintain a set of seen `tracker_id` values after filtering detections with `zone.trigger(detections)`, or use a dedicated entry/crossing counting tool such as `sv.LineZone` when it better matches your use case.
## Author
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
+119 -54
View File
@@ -1,45 +1,64 @@
---
comments: true
description: Learn to load model predictions, create Detections objects, and annotate images with bounding boxes, labels, and masks using supervision.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
- name: Borda
role: Open Source Engineer, Roboflow
github: https://github.com/borda
date_modified: 2026-04-22
---
# Detect and Annotate
Supervision provides a seamless process for annotating predictions generated by various
object detection and segmentation models. This guide shows how to perform inference
with the [Inference](https://github.com/roboflow/inference),
[Ultralytics](https://github.com/ultralytics/ultralytics) or
[Transformers](https://github.com/huggingface/transformers) packages. Following this,
you'll learn how to import these predictions into Supervision and use them to annotate
source image.
!!! tip "Sample Image"
Don't have an image? Download the one used in this tutorial:
```bash
wget https://media.roboflow.com/notebooks/examples/dog.jpeg
```
```
Then replace `<SOURCE_IMAGE_PATH>` with `"dog.jpeg"`.
```
Supervision provides a seamless process for annotating predictions generated by various object detection and segmentation models. This guide shows how to perform inference with the [Inference](https://github.com/roboflow/inference), [Ultralytics](https://github.com/ultralytics/ultralytics) or [Transformers](https://github.com/huggingface/transformers) packages. Following this, you'll learn how to import these predictions into Supervision and use them to annotate source image.
![basic-annotation](https://media.roboflow.com/supervision_detect_and_annotate_example_1.png)
## Run Detection
First, you'll need to obtain predictions from your object detection or segmentation
model.
First, you'll need to obtain predictions from your object detection or segmentation model.
To run inference, initialize your chosen model and pass the source image to its predict or infer method. Supervision supports Roboflow Inference, Ultralytics YOLO, and Hugging Face Transformers -- select the tab matching your framework. The result is a framework-specific object you will convert to a `Detections` instance in the next step.
=== "Inference"
```python
import cv2
from inference import get_model
model = get_model(model_id="yolov8n-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model.infer(image)[0]
```
=== "Ultralytics"
```python
import cv2
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model(image)[0]
```
=== "Transformers"
```python
import torch
from PIL import Image
@@ -48,7 +67,7 @@ model.
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
image = Image.open(<SOURCE_IMAGE_PATH>)
image = Image.open("dog.jpeg")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
@@ -57,15 +76,19 @@ model.
width, height = image.size
target_size = torch.tensor([[height, width]])
results = processor.post_process_object_detection(
outputs=outputs, target_sizes=target_size)[0]
outputs=outputs, target_sizes=target_size
)[0]
```
## Load Predictions into Supervision
Now that we have predictions from a model, we can load them into Supervision.
Each supported framework has a dedicated class method on `sv.Detections` that converts raw model output into a unified Supervision object. Call `from_inference`, `from_ultralytics`, or `from_transformers` depending on the package you used for inference. This normalization step ensures all downstream annotators and filters work identically regardless of the source model.
=== "Inference"
We can do so using the [`sv.Detections.from_inference`](/latest/detection/core/#supervision.detection.core.Detections.from_inference) method, which accepts model results from both detection and segmentation models.
We can do so using the [`sv.Detections.from_inference`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_inference) method, which accepts model results from both detection and segmentation models.
```{ .py hl_lines="2 8" }
import cv2
@@ -73,13 +96,14 @@ Now that we have predictions from a model, we can load them into Supervision.
from inference import get_model
model = get_model(model_id="yolov8n-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model.infer(image)[0]
detections = sv.Detections.from_inference(results)
```
=== "Ultralytics"
We can do so using the [`sv.Detections.from_ultralytics`](/latest/detection/core/#supervision.detection.core.Detections.from_ultralytics) method, which accepts model results from both detection and segmentation models.
We can do so using the [`sv.Detections.from_ultralytics`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_ultralytics) method, which accepts model results from both detection and segmentation models.
```{ .py hl_lines="2 8" }
import cv2
@@ -87,13 +111,14 @@ Now that we have predictions from a model, we can load them into Supervision.
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model(image)[0]
detections = sv.Detections.from_ultralytics(results)
```
=== "Transformers"
We can do so using the [`sv.Detections.from_transformers`](/latest/detection/core/#supervision.detection.core.Detections.from_transformers) method, which accepts model results from both detection and segmentation models.
We can do so using the [`sv.Detections.from_transformers`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_transformers) method, which accepts model results from both detection and segmentation models.
```{ .py hl_lines="2 19-21" }
import torch
@@ -104,7 +129,7 @@ Now that we have predictions from a model, we can load them into Supervision.
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
image = Image.open(<SOURCE_IMAGE_PATH>)
image = Image.open("dog.jpeg")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
@@ -121,24 +146,27 @@ Now that we have predictions from a model, we can load them into Supervision.
You can load predictions from other computer vision frameworks and libraries using:
- [`from_deepsparse`](/latest/detection/core/#supervision.detection.core.Detections.from_deepsparse) ([Deepsparse](https://github.com/neuralmagic/deepsparse))
- [`from_detectron2`](/latest/detection/core/#supervision.detection.core.Detections.from_detectron2) ([Detectron2](https://github.com/facebookresearch/detectron2))
- [`from_mmdetection`](/latest/detection/core/#supervision.detection.core.Detections.from_mmdetection) ([MMDetection](https://github.com/open-mmlab/mmdetection))
- [`from_sam`](/latest/detection/core/#supervision.detection.core.Detections.from_sam) ([Segment Anything Model](https://github.com/facebookresearch/segment-anything))
- [`from_yolo_nas`](/latest/detection/core/#supervision.detection.core.Detections.from_yolo_nas) ([YOLO-NAS](https://github.com/Deci-AI/super-gradients/blob/master/YOLONAS.md))
- [`from_deepsparse`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_deepsparse) ([Deepsparse](https://github.com/neuralmagic/deepsparse))
- [`from_detectron2`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_detectron2) ([Detectron2](https://github.com/facebookresearch/detectron2))
- [`from_mmdetection`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_mmdetection) ([MMDetection](https://github.com/open-mmlab/mmdetection))
- [`from_sam`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_sam) ([Segment Anything Model](https://github.com/facebookresearch/segment-anything))
- [`from_yolo_nas`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections.from_yolo_nas) ([YOLO-NAS](https://github.com/Deci-AI/super-gradients/blob/master/YOLONAS.md))
## Annotate Image with Detections
Finally, we can annotate the image with the predictions. Since we are working with an object detection model, we will use the [`sv.BoxAnnotator`](/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator) and [`sv.LabelAnnotator`](/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator) classes.
Finally, we can annotate the image with the predictions. Since we are working with an object detection model, we will use the [`sv.BoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator) and [`sv.LabelAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator) classes.
To draw bounding boxes and class labels on your image, create a `BoxAnnotator` and a `LabelAnnotator`, then call their `annotate` methods in sequence. Each annotator returns the modified image, so you can chain multiple annotators together. The result is a single NumPy array with all visual overlays rendered and ready for display or saving.
=== "Inference"
```{ .py hl_lines="10-16" }
import cv2
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8n-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model.infer(image)[0]
detections = sv.Detections.from_inference(results)
@@ -152,13 +180,14 @@ Finally, we can annotate the image with the predictions. Since we are working wi
```
=== "Ultralytics"
```{ .py hl_lines="10-16" }
import cv2
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model(image)[0]
detections = sv.Detections.from_ultralytics(results)
@@ -172,6 +201,7 @@ Finally, we can annotate the image with the predictions. Since we are working wi
```
=== "Transformers"
```{ .py hl_lines="23-30" }
import torch
import supervision as sv
@@ -181,7 +211,7 @@ Finally, we can annotate the image with the predictions. Since we are working wi
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
image = Image.open(<SOURCE_IMAGE_PATH>)
image = Image.open("dog.jpeg")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
@@ -208,18 +238,17 @@ Finally, we can annotate the image with the predictions. Since we are working wi
## Display Custom Labels
By default, [`sv.LabelAnnotator`](/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator)
will label each detection with its `class_name` (if possible) or `class_id`. You can
override this behavior by passing a list of custom `labels` to the `annotate` method.
By default, [`sv.LabelAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator) will label each detection with its `class_name` (if possible) or `class_id`. You can override this behavior by passing a list of custom `labels` to the `annotate` method.
=== "Inference"
```{ .py hl_lines="13-17 22" }
import cv2
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8n-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model.infer(image)[0]
detections = sv.Detections.from_inference(results)
@@ -239,13 +268,14 @@ override this behavior by passing a list of custom `labels` to the `annotate` me
```
=== "Ultralytics"
```{ .py hl_lines="13-17 22" }
import cv2
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model(image)[0]
detections = sv.Detections.from_ultralytics(results)
@@ -265,6 +295,7 @@ override this behavior by passing a list of custom `labels` to the `annotate` me
```
=== "Transformers"
```{ .py hl_lines="26-30 35" }
import torch
import supervision as sv
@@ -274,7 +305,7 @@ override this behavior by passing a list of custom `labels` to the `annotate` me
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
image = Image.open(<SOURCE_IMAGE_PATH>)
image = Image.open("dog.jpeg")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
@@ -307,20 +338,17 @@ override this behavior by passing a list of custom `labels` to the `annotate` me
## Annotate Image with Segmentations
If you are running the segmentation model
[`sv.MaskAnnotator`](/latest/detection/annotators/#supervision.annotators.core.MaskAnnotator)
is a drop-in replacement for
[`sv.BoxAnnotator`](/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator)
that will allow you to draw masks instead of boxes.
If you are running the segmentation model [`sv.MaskAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.MaskAnnotator) is a drop-in replacement for [`sv.BoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator) that will allow you to draw masks instead of boxes.
=== "Inference"
```python
import cv2
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8n-seg-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model.infer(image)[0]
detections = sv.Detections.from_inference(results)
@@ -328,19 +356,25 @@ that will allow you to draw masks instead of boxes.
label_annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER_OF_MASS)
annotated_image = mask_annotator.annotate(
scene=image, detections=detections)
scene=image,
detections=detections,
)
annotated_image = label_annotator.annotate(
scene=annotated_image, detections=detections)
scene=annotated_image,
detections=detections,
)
sv.plot_image(annotated_image)
```
=== "Ultralytics"
```python
import cv2
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n-seg.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("dog.jpeg")
results = model(image)[0]
detections = sv.Detections.from_ultralytics(results)
@@ -348,12 +382,17 @@ that will allow you to draw masks instead of boxes.
label_annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER_OF_MASS)
annotated_image = mask_annotator.annotate(
scene=image, detections=detections)
scene=image,
detections=detections,
)
annotated_image = label_annotator.annotate(
scene=annotated_image, detections=detections)
scene=annotated_image,
detections=detections,
)
```
=== "Transformers"
```python
import torch
import supervision as sv
@@ -363,7 +402,7 @@ that will allow you to draw masks instead of boxes.
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50-panoptic")
model = DetrForSegmentation.from_pretrained("facebook/detr-resnet-50-panoptic")
image = Image.open(<SOURCE_IMAGE_PATH>)
image = Image.open("dog.jpeg")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
@@ -372,24 +411,50 @@ that will allow you to draw masks instead of boxes.
width, height = image.size
target_size = torch.tensor([[height, width]])
results = processor.post_process_segmentation(
outputs=outputs, target_sizes=target_size)[0]
outputs=outputs, target_sizes=target_size
)[0]
detections = sv.Detections.from_transformers(
transformers_results=results,
id2label=model.config.id2label)
transformers_results=results, id2label=model.config.id2label
)
mask_annotator = sv.MaskAnnotator()
label_annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER_OF_MASS)
labels = [
f"{class_name} {confidence:.2f}"
for class_name, confidence
in zip(detections['class_name'], detections.confidence)
for class_name, confidence in zip(
detections["class_name"],
detections.confidence,
)
]
annotated_image = mask_annotator.annotate(
scene=image, detections=detections)
annotated_image = mask_annotator.annotate(scene=image, detections=detections)
annotated_image = label_annotator.annotate(
scene=annotated_image, detections=detections, labels=labels)
scene=annotated_image, detections=detections, labels=labels
)
```
![segmentation-annotation](https://media.roboflow.com/supervision_detect_and_annotate_example_3.png)
## Frequently Asked Questions
### How do I detect and annotate objects with supervision?
Pass any model's output to `sv.Detections.from_<model>()` to create a unified `Detections` object. Then pass it to `sv.BoxAnnotator` or `sv.MaskAnnotator` to draw predictions on an image.
### Can I annotate both bounding boxes and masks at the same time?
Yes. Chain annotators: first draw boxes with `BoxAnnotator`, then overlay masks with `MaskAnnotator` on the same scene.
### How do I label detections with class names?
Use `sv.LabelAnnotator` and pass custom text with the `labels` parameter. If a connector provides class names, they are stored in `detections["class_name"]` / `detections.data["class_name"]`; when `labels` is omitted, `LabelAnnotator` uses class names first, then class IDs, then detection indices.
### Can I use supervision with Hugging Face models?
Yes. `sv.Detections.from_transformers()` accepts supported Hugging Face object detection and segmentation outputs. Vision-language model outputs are handled through `sv.Detections.from_vlm(...)`, for example with `sv.VLM.FLORENCE_2` or `sv.VLM.PALIGEMMA`.
## Authors
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
- [Borda](https://github.com/borda) — Open Source Engineer, Roboflow
+69 -37
View File
@@ -1,14 +1,16 @@
---
comments: true
description: Detect small objects in images by applying SAHI inference slicing with supervision's InferenceSlicer — improve recall for tiny targets.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
date_modified: 2026-04-22
---
# Detect Small Objects
This guide shows how to detect small objects
with the [Inference](https://github.com/roboflow/inference),
[Ultralytics](https://github.com/ultralytics/ultralytics) or
[Transformers](https://github.com/huggingface/transformers) packages using
[`InferenceSlicer`](/latest/detection/tools/inference_slicer/#supervision.detection.tools.inference_slicer.InferenceSlicer).
This guide shows how to detect small objects with the [Inference](https://github.com/roboflow/inference), [Ultralytics](https://github.com/ultralytics/ultralytics) or [Transformers](https://github.com/huggingface/transformers) packages using [`InferenceSlicer`](https://supervision.roboflow.com/latest/detection/tools/inference_slicer/#supervision.detection.tools.inference_slicer.InferenceSlicer).
<video controls>
<source src="https://media.roboflow.com/supervision_detect_small_objects_example.mp4" type="video/mp4">
@@ -16,17 +18,19 @@ with the [Inference](https://github.com/roboflow/inference),
## Baseline Detection
Small object detection in high-resolution images presents challenges due to the objects'
size relative to the image resolution.
Small object detection in high-resolution images presents challenges due to the objects' size relative to the image resolution.
Running a standard detection model on the full image establishes a baseline for comparison. Load your chosen model, pass the image through it, and convert the results into a `Detections` object. This baseline reveals how many small objects the model misses at native resolution, motivating the sliced inference approach shown later.
=== "Inference"
```python
import cv2
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8x-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
results = model.infer(image)[0]
detections = sv.Detections.from_inference(results)
@@ -34,19 +38,24 @@ size relative to the image resolution.
label_annotator = sv.LabelAnnotator()
annotated_image = box_annotator.annotate(
scene=image, detections=detections)
scene=image,
detections=detections,
)
annotated_image = label_annotator.annotate(
scene=annotated_image, detections=detections)
scene=annotated_image,
detections=detections,
)
```
=== "Ultralytics"
```python
import cv2
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8x.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
results = model(image)[0]
detections = sv.Detections.from_ultralytics(results)
@@ -54,12 +63,17 @@ size relative to the image resolution.
label_annotator = sv.LabelAnnotator()
annotated_image = box_annotator.annotate(
scene=image, detections=detections)
scene=image,
detections=detections,
)
annotated_image = label_annotator.annotate(
scene=annotated_image, detections=detections)
scene=annotated_image,
detections=detections,
)
```
=== "Transformers"
```python
import torch
import supervision as sv
@@ -69,7 +83,7 @@ size relative to the image resolution.
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForSegmentation.from_pretrained("facebook/detr-resnet-50")
image = Image.open(<SOURCE_IMAGE_PATH>)
image = Image.open("<SOURCE_IMAGE_PATH>")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
@@ -78,40 +92,36 @@ size relative to the image resolution.
width, height = image_slice.size
target_size = torch.tensor([[width, height]])
results = processor.post_process_object_detection(
outputs=outputs, target_sizes=target_size)[0]
outputs=outputs, target_sizes=target_size
)[0]
detections = sv.Detections.from_transformers(results)
box_annotator = sv.BoxAnnotator()
label_annotator = sv.LabelAnnotator()
labels = [
model.config.id2label[class_id]
for class_id
in detections.class_id
]
labels = [model.config.id2label[class_id] for class_id in detections.class_id]
annotated_image = box_annotator.annotate(
scene=image, detections=detections)
annotated_image = box_annotator.annotate(scene=image, detections=detections)
annotated_image = label_annotator.annotate(
scene=annotated_image, detections=detections, labels=labels)
scene=annotated_image, detections=detections, labels=labels
)
```
![basic-detection](https://media.roboflow.com/supervision_detect_small_objects_example_1.png)
## Input Resolution
Modifying the input resolution of images before detection can enhance small object
identification at the cost of processing speed and increased memory usage. This method
is less effective for ultra-high-resolution images (4K and above).
Modifying the input resolution of images before detection can enhance small object identification at the cost of processing speed and increased memory usage. This method is less effective for ultra-high-resolution images (4K and above).
=== "Inference"
```{ .py hl_lines="5" }
import cv2
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8x-1280")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
results = model.infer(image)[0]
detections = sv.Detections.from_inference(results)
@@ -125,13 +135,14 @@ is less effective for ultra-high-resolution images (4K and above).
```
=== "Ultralytics"
```{ .py hl_lines="7" }
import cv2
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8x.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
results = model(image, imgsz=1280)[0]
detections = sv.Detections.from_ultralytics(results)
@@ -148,15 +159,14 @@ is less effective for ultra-high-resolution images (4K and above).
## Inference Slicer
[`InferenceSlicer`](/latest/detection/tools/inference_slicer/#supervision.detection.tools.inference_slicer.InferenceSlicer)
processes high-resolution images by dividing them into smaller segments, detecting
objects within each, and aggregating the results.
[`InferenceSlicer`](https://supervision.roboflow.com/latest/detection/tools/inference_slicer/#supervision.detection.tools.inference_slicer.InferenceSlicer) processes high-resolution images by dividing them into smaller segments, detecting objects within each, and aggregating the results.
<video controls>
<source src="https://media.roboflow.com/supervision_detect_small_objects_example_2.mp4" type="video/mp4">
</video>
=== "Inference"
```{ .py hl_lines="9-14" }
import cv2
import numpy as np
@@ -164,7 +174,7 @@ objects within each, and aggregating the results.
from inference import get_model
model = get_model(model_id="yolov8x-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
def callback(image_slice: np.ndarray) -> sv.Detections:
results = model.infer(image_slice)[0]
@@ -183,6 +193,7 @@ objects within each, and aggregating the results.
```
=== "Ultralytics"
```{ .py hl_lines="9-14" }
import cv2
import numpy as np
@@ -190,7 +201,7 @@ objects within each, and aggregating the results.
from ultralytics import YOLO
model = YOLO("yolov8x.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
def callback(image_slice: np.ndarray) -> sv.Detections:
result = model(image_slice)[0]
@@ -209,6 +220,7 @@ objects within each, and aggregating the results.
```
=== "Transformers"
```{ .py hl_lines="13-28" }
import cv2
import torch
@@ -220,7 +232,7 @@ objects within each, and aggregating the results.
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
def callback(image_slice: np.ndarray) -> sv.Detections:
image_slice = cv2.cvtColor(image_slice, cv2.COLOR_BGR2RGB)
@@ -258,9 +270,10 @@ objects within each, and aggregating the results.
## Small Object Segmentation
[`InferenceSlicer`](/latest/detection/tools/inference_slicer/#supervision.detection.tools.inference_slicer.InferenceSlicer) can perform segmentation tasks too.
[`InferenceSlicer`](https://supervision.roboflow.com/latest/detection/tools/inference_slicer/#supervision.detection.tools.inference_slicer.InferenceSlicer) can perform segmentation tasks too.
=== "Inference"
```{ .py hl_lines="6 16 19-20" }
import cv2
import numpy as np
@@ -268,7 +281,7 @@ objects within each, and aggregating the results.
from inference import get_model
model = get_model(model_id="yolov8x-seg-640")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
def callback(image_slice: np.ndarray) -> sv.Detections:
results = model.infer(image_slice)[0]
@@ -287,6 +300,7 @@ objects within each, and aggregating the results.
```
=== "Ultralytics"
```{ .py hl_lines="6 16 19-20" }
import cv2
import numpy as np
@@ -294,7 +308,7 @@ objects within each, and aggregating the results.
from ultralytics import YOLO
model = YOLO("yolov8x-seg.pt")
image = cv2.imread(<SOURCE_IMAGE_PATH>)
image = cv2.imread("<SOURCE_IMAGE_PATH>")
def callback(image_slice: np.ndarray) -> sv.Detections:
result = model(image_slice)[0]
@@ -313,3 +327,21 @@ objects within each, and aggregating the results.
```
![detection-with-inference-slicer](https://media.roboflow.com/supervision-docs/inference-slicer-segmentation-example.png)
## Frequently Asked Questions
### How do I detect small objects with supervision?
Use `sv.InferenceSlicer` to split a high-resolution image into overlapping tiles, run detection on each tile, and merge results with non-maximum suppression. This dramatically improves recall for tiny targets.
### What overlap should I use between tiles?
`InferenceSlicer` takes overlap in pixels via `overlap_wh`, not as a percentage. The default is `100` pixels in both directions. Increase `overlap_wh` when objects are close to the tile size or often appear on tile boundaries, and decrease it when speed is more important.
### Can I use InferenceSlicer with any detection model?
Yes. Wrap any model or converter path that can produce `sv.Detections` in a callback, pass that callback to `sv.InferenceSlicer(callback=...)`, and then call the slicer with your image.
## Author
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
+53 -16
View File
@@ -1,20 +1,23 @@
---
comments: true
description: Filter and query detection results by class, confidence, or spatial overlap using supervision's Detections API — clean predictions in one line.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
date_modified: 2026-04-22
---
# Filter Detections
The advanced filtering capabilities of the `Detections` class offer users a versatile and efficient way to narrow down
and refine object detections. This section outlines various filtering methods, including filtering by specific class
or a set of classes, confidence, object area, bounding box area, relative area, box dimensions, and designated zones.
Each method is demonstrated with concise code examples to provide users with a clear understanding of how to implement
the filters in their applications.
The advanced filtering capabilities of the `Detections` class offer users a versatile and efficient way to narrow down and refine object detections. This section outlines various filtering methods, including filtering by specific class or a set of classes, confidence, object area, bounding box area, relative area, box dimensions, and designated zones. Each method is demonstrated with concise code examples to provide users with a clear understanding of how to implement the filters in their applications.
### by specific class
Allows you to select detections that belong only to one selected class.
=== "After"
```python
import supervision as sv
@@ -29,6 +32,7 @@ Allows you to select detections that belong only to one selected class.
</div>
=== "Before"
```python
import supervision as sv
@@ -47,6 +51,7 @@ Allows you to select detections that belong only to one selected class.
Allows you to select detections that belong only to selected set of classes.
=== "After"
```python
import numpy as np
import supervision as sv
@@ -63,6 +68,7 @@ Allows you to select detections that belong only to selected set of classes.
</div>
=== "Before"
```python
import numpy as np
import supervision as sv
@@ -83,6 +89,7 @@ Allows you to select detections that belong only to selected set of classes.
Allows you to select detections with specific confidence value, for example higher than selected threshold.
=== "After"
```python
import supervision as sv
@@ -97,6 +104,7 @@ Allows you to select detections with specific confidence value, for example high
</div>
=== "Before"
```python
import supervision as sv
@@ -112,10 +120,10 @@ Allows you to select detections with specific confidence value, for example high
### by area
Allows you to select detections based on their size. We define the area as the number of pixels occupied by the
detection in the image. In the example below, we have sifted out the detections that are too small.
Allows you to select detections based on their size. We define the area as the number of pixels occupied by the detection in the image. In the example below, we have sifted out the detections that are too small.
=== "After"
```python
import supervision as sv
@@ -130,6 +138,7 @@ detection in the image. In the example below, we have sifted out the detections
</div>
=== "Before"
```python
import supervision as sv
@@ -145,12 +154,10 @@ detection in the image. In the example below, we have sifted out the detections
### by relative area
Allows you to select detections based on their size in relation to the size of whole image. Sometimes the concept of
detection size changes depending on the image. Detection occupying 10000 square px can be large on a 1280x720 image
but small on a 3840x2160 image. In such cases, we can filter out detections based on the percentage of the image area
occupied by them. In the example below, we remove too large detections.
Allows you to select detections based on their size in relation to the size of whole image. Sometimes the concept of detection size changes depending on the image. Detection occupying 10000 square px can be large on a 1280x720 image but small on a 3840x2160 image. In such cases, we can filter out detections based on the percentage of the image area occupied by them. In the example below, we remove too large detections.
=== "After"
```python
import supervision as sv
@@ -169,6 +176,7 @@ occupied by them. In the example below, we remove too large detections.
</div>
=== "Before"
```python
import supervision as sv
@@ -188,11 +196,10 @@ occupied by them. In the example below, we remove too large detections.
### by box dimensions
Allows you to select detections based on their dimensions. The size of the bounding box, as well as its coordinates,
can be criteria for rejecting detection. Implementing such filtering requires a bit of custom code but is relatively
simple and fast.
Allows you to select detections based on their dimensions. The size of the bounding box, as well as its coordinates, can be criteria for rejecting detection. Implementing such filtering requires a bit of custom code but is relatively simple and fast.
=== "After"
```python
import supervision as sv
@@ -209,6 +216,7 @@ simple and fast.
</div>
=== "Before"
```python
import supervision as sv
@@ -226,10 +234,10 @@ simple and fast.
### by `PolygonZone`
Allows you to use `Detections` in combination with `PolygonZone` to weed out bounding boxes that are in and out of the
zone. In the example below you can see how to filter out all detections located in the lower part of the image.
Allows you to use `Detections` in combination with `PolygonZone` to weed out bounding boxes that are in and out of the zone. In the example below you can see how to filter out all detections located in the lower part of the image.
=== "After"
```python
import supervision as sv
@@ -246,6 +254,7 @@ zone. In the example below you can see how to filter out all detections located
</div>
=== "Before"
```python
import supervision as sv
@@ -266,6 +275,7 @@ zone. In the example below you can see how to filter out all detections located
`Detections`' greatest strength, however, is that you can build arbitrarily complex logical conditions by simply combining separate conditions using `&` or `|`.
=== "After"
```python
import supervision as sv
@@ -282,6 +292,7 @@ zone. In the example below you can see how to filter out all detections located
</div>
=== "Before"
```python
import supervision as sv
@@ -296,3 +307,29 @@ zone. In the example below you can see how to filter out all detections located
![original](https://media.roboflow.com/open-source/supervision/supervision-detection-original.png){ align=center width="800" }
</div>
## Frequently Asked Questions
### How do I filter detections by class in supervision?
Use NumPy-style boolean indexing: `detections[detections.class_id == 0]` for class 0. Combine with `&` or `|` for multiple conditions.
### How do I filter by confidence threshold?
`detections[detections.confidence > 0.5]` returns only detections above the threshold. Chain with class filters for precise results.
### How do I filter by bounding box area?
`detections[detections.area > 1000]` filters by pixel area. If masks are present, `detections.area` uses mask area; otherwise, if oriented-box coordinates are present, it uses oriented polygon area; all remaining detections use bounding box area from `xyxy`. Use `detections.box_area` when you specifically need axis-aligned bounding box area.
### Can I filter by box aspect ratio or dimensions?
Yes. Use `detections.box_aspect_ratio` for aspect ratio filtering. If you need explicit box dimensions, compute them from `detections.xyxy` as `width = detections.xyxy[:, 2] - detections.xyxy[:, 0]` and `height = detections.xyxy[:, 3] - detections.xyxy[:, 1]`.
### How do I remove duplicate detections (NMS) from my results?
Use `detections.with_nms(threshold=0.5)` — it applies non-maximum suppression on the `xyxy` boxes.
## Author
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
+63
View File
@@ -0,0 +1,63 @@
---
comments: true
description: Migrate Supervision installations after OpenCV becomes an ambient optional backend: use the included fallback by default or select one compatible OpenCV wheel for your application.
date_modified: 2026-07-17
---
# Migrate to Supervision Without an OpenCV Dependency
Supervision no longer installs OpenCV or offers an OpenCV extra. A standard installation includes the NumPy, Pillow, SciPy, and PyAV fallback needed by Supervision's image, drawing, and file-video APIs. When a compatible `cv2` is already installed, Supervision selects it once when the process imports the package.
## Keep the default fallback
Install Supervision normally when your application does not otherwise require OpenCV:
```bash
pip install supervision
```
The fallback keeps Supervision's documented APIs operational. Some text and anti-aliased drawing pixels can differ from OpenCV, so use the same backend while validating image-level baselines.
## Prefer OpenCV behavior
Install exactly one OpenCV wheel family when your application relies on OpenCV outside Supervision or needs its native behavior:
```bash
# Servers and containers without OpenCV GUI modules
pip install opencv-python-headless supervision
# Desktop applications that need OpenCV GUI modules
pip install opencv-python supervision
```
Do not install both `opencv-python` and `opencv-python-headless`. If another dependency, such as a model runtime, already provides a compatible `cv2`, keep that installation instead of adding a second wheel family.
## Verify the selected backend
Backend selection happens at import time and lasts for the process lifetime. Run this command in a fresh Python process after changing dependencies:
```bash
python -c "from supervision import _cv2; print(_cv2.BACKEND_NAME)"
```
It prints `fallback` without OpenCV and the OpenCV backend name when `cv2` is available. `_cv2` is private; use this command only as an installation diagnostic, not as application API.
## Capture webcams yourself
Supervision's video helpers support file paths through either backend. Live camera capture remains application-owned, so install your chosen OpenCV wheel if you use `cv2.VideoCapture(0)`:
```python
import cv2
import supervision as sv
capture = cv2.VideoCapture(0)
annotator = sv.BoxAnnotator()
```
## Roll back an upgrade
If a downstream image baseline requires the pre-migration package behavior, pin Supervision below the first release that removes the OpenCV dependency, then plan a backend-specific migration separately:
```bash
pip install "supervision<0.30.0"
```
+246 -95
View File
@@ -1,28 +1,24 @@
---
comments: true
description: Load, split, merge, and convert computer vision datasets between YOLO, COCO, Pascal VOC, CreateML, and LabelMe formats using supervision's DetectionDataset.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
date_modified: 2026-06-25
---
With Supervision, you can load and manipulate classification, object detection, and
segmentation datasets. This tutorial will walk you through how to load, split, merge,
visualize, and augment datasets in Supervision.
With Supervision, you can load and manipulate classification, object detection, and segmentation datasets. This tutorial will walk you through how to load, split, merge, visualize, and augment datasets in Supervision.
## Download Dataset
In this tutorial, we will use a dataset from
[Roboflow Universe](https://universe.roboflow.com/), a public repository of
thousands of computer vision datasets. If you already have your dataset in
[COCO](https://roboflow.com/formats/coco-json),
[YOLO](https://roboflow.com/formats/yolov8-pytorch-txt),
or [Pascal VOC](https://roboflow.com/formats/pascal-voc-xml) format, you can skip this
section.
In this tutorial, we will use a dataset from [Roboflow Universe](https://universe.roboflow.com/), a public repository of thousands of computer vision datasets. If you already have your dataset in [COCO](https://roboflow.com/formats/coco-json), [YOLO](https://roboflow.com/formats/yolov8-pytorch-txt), [Pascal VOC](https://roboflow.com/formats/pascal-voc-xml), [CreateML](https://roboflow.com/formats/createml-json), or [LabelMe](https://roboflow.com/formats/labelme-json) format, you can skip this section.
```bash
pip install roboflow
```
Next, log into your Roboflow account and download the dataset of your choice in the
COCO, YOLO, or Pascal VOC format. You can customize the following code snippet with
your workspace ID, project ID, and version number.
Next, log into your Roboflow account and download the dataset of your choice. The following snippets show common COCO, YOLO, Pascal VOC, and CreateML exports; LabelMe datasets can also be loaded directly from per-image JSON files in the next section. You can customize the code with your workspace ID, project ID, and version number.
=== "COCO"
@@ -32,8 +28,8 @@ your workspace ID, project ID, and version number.
roboflow.login()
rf = roboflow.Roboflow()
project = rf.workspace('<WORKSPACE_ID>').project('<PROJECT_ID>')
dataset = project.version('<PROJECT_VERSION>').download("coco")
project = rf.workspace("<WORKSPACE_ID>").project("<PROJECT_ID>")
dataset = project.version("<PROJECT_VERSION>").download("coco")
```
=== "YOLO"
@@ -44,8 +40,8 @@ your workspace ID, project ID, and version number.
roboflow.login()
rf = roboflow.Roboflow()
project = rf.workspace('<WORKSPACE_ID>').project('<PROJECT_ID>')
dataset = project.version('<PROJECT_VERSION>').download("yolov8")
project = rf.workspace("<WORKSPACE_ID>").project("<PROJECT_ID>")
dataset = project.version("<PROJECT_VERSION>").download("yolov8")
```
=== "Pascal VOC"
@@ -56,16 +52,25 @@ your workspace ID, project ID, and version number.
roboflow.login()
rf = roboflow.Roboflow()
project = rf.workspace('<WORKSPACE_ID>').project('<PROJECT_ID>')
dataset = project.version('<PROJECT_VERSION>').download("voc")
project = rf.workspace("<WORKSPACE_ID>").project("<PROJECT_ID>")
dataset = project.version("<PROJECT_VERSION>").download("voc")
```
=== "CreateML"
```python
import roboflow
roboflow.login()
rf = roboflow.Roboflow()
project = rf.workspace("<WORKSPACE_ID>").project("<PROJECT_ID>")
dataset = project.version("<PROJECT_VERSION>").download("createml")
```
## Load Dataset
The Supervision library provides convenient functions to load datasets in various
formats. If your dataset is already split into train, test, and valid subsets, you can
load each of those as separate [`sv.DetectionDataset`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset)
instances.
The Supervision library provides convenient functions to load datasets in various formats. If your dataset is already split into train, test, and valid subsets, you can load each of those as separate [`sv.DetectionDataset`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset) instances.
=== "COCO"
@@ -75,16 +80,16 @@ instances.
import supervision as sv
ds_train = sv.DetectionDataset.from_coco(
images_directory_path=f'{dataset.location}/train',
annotations_path=f'{dataset.location}/train/_annotations.coco.json',
images_directory_path=f"{dataset.location}/train",
annotations_path=f"{dataset.location}/train/_annotations.coco.json",
)
ds_valid = sv.DetectionDataset.from_coco(
images_directory_path=f'{dataset.location}/valid',
annotations_path=f'{dataset.location}/valid/_annotations.coco.json',
images_directory_path=f"{dataset.location}/valid",
annotations_path=f"{dataset.location}/valid/_annotations.coco.json",
)
ds_test = sv.DetectionDataset.from_coco(
images_directory_path=f'{dataset.location}/test',
annotations_path=f'{dataset.location}/test/_annotations.coco.json',
images_directory_path=f"{dataset.location}/test",
annotations_path=f"{dataset.location}/test/_annotations.coco.json",
)
ds_train.classes
@@ -102,19 +107,19 @@ instances.
import supervision as sv
ds_train = sv.DetectionDataset.from_yolo(
images_directory_path=f'{dataset.location}/train/images',
annotations_directory_path=f'{dataset.location}/train/labels',
data_yaml_path=f'{dataset.location}/data.yaml'
images_directory_path=f"{dataset.location}/train/images",
annotations_directory_path=f"{dataset.location}/train/labels",
data_yaml_path=f"{dataset.location}/data.yaml",
)
ds_valid = sv.DetectionDataset.from_yolo(
images_directory_path=f'{dataset.location}/valid/images',
annotations_directory_path=f'{dataset.location}/valid/labels',
data_yaml_path=f'{dataset.location}/data.yaml'
images_directory_path=f"{dataset.location}/valid/images",
annotations_directory_path=f"{dataset.location}/valid/labels",
data_yaml_path=f"{dataset.location}/data.yaml",
)
ds_test = sv.DetectionDataset.from_yolo(
images_directory_path=f'{dataset.location}/test/images',
annotations_directory_path=f'{dataset.location}/test/labels',
data_yaml_path=f'{dataset.location}/data.yaml'
images_directory_path=f"{dataset.location}/test/images",
annotations_directory_path=f"{dataset.location}/test/labels",
data_yaml_path=f"{dataset.location}/data.yaml",
)
ds_train.classes
@@ -132,16 +137,70 @@ instances.
import supervision as sv
ds_train = sv.DetectionDataset.from_pascal_voc(
images_directory_path=f'{dataset.location}/train/images',
annotations_directory_path=f'{dataset.location}/train/labels'
images_directory_path=f"{dataset.location}/train/images",
annotations_directory_path=f"{dataset.location}/train/labels",
)
ds_valid = sv.DetectionDataset.from_pascal_voc(
images_directory_path=f'{dataset.location}/valid/images',
annotations_directory_path=f'{dataset.location}/valid/labels'
images_directory_path=f"{dataset.location}/valid/images",
annotations_directory_path=f"{dataset.location}/valid/labels",
)
ds_test = sv.DetectionDataset.from_pascal_voc(
images_directory_path=f'{dataset.location}/test/images',
annotations_directory_path=f'{dataset.location}/test/labels'
images_directory_path=f"{dataset.location}/test/images",
annotations_directory_path=f"{dataset.location}/test/labels",
)
ds_train.classes
# ['person', 'bicycle', 'car', ...]
len(ds_train), len(ds_valid), len(ds_test)
# 800, 100, 100
```
=== "CreateML"
We can do so using the [`sv.DetectionDataset.from_createml`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.from_createml) to load annotations in [CreateML](https://roboflow.com/formats/createml-json) format.
```python
import supervision as sv
ds_train = sv.DetectionDataset.from_createml(
images_directory_path=f"{dataset.location}/train",
annotations_path=f"{dataset.location}/train/_annotations.createml.json",
)
ds_valid = sv.DetectionDataset.from_createml(
images_directory_path=f"{dataset.location}/valid",
annotations_path=f"{dataset.location}/valid/_annotations.createml.json",
)
ds_test = sv.DetectionDataset.from_createml(
images_directory_path=f"{dataset.location}/test",
annotations_path=f"{dataset.location}/test/_annotations.createml.json",
)
ds_train.classes
# ['person', 'bicycle', 'car', ...]
len(ds_train), len(ds_valid), len(ds_test)
# 800, 100, 100
```
=== "LabelMe"
We can do so using the [`sv.DetectionDataset.from_labelme`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.from_labelme) to load annotations in [LabelMe](https://roboflow.com/formats/labelme-json) format. LabelMe `rectangle` shapes are loaded as bounding boxes and `polygon` shapes are loaded as masks with bounding boxes.
```python
import supervision as sv
ds_train = sv.DetectionDataset.from_labelme(
images_directory_path="<TRAIN_IMAGES_DIRECTORY_PATH>",
annotations_directory_path="<TRAIN_ANNOTATIONS_DIRECTORY_PATH>",
)
ds_valid = sv.DetectionDataset.from_labelme(
images_directory_path="<VALID_IMAGES_DIRECTORY_PATH>",
annotations_directory_path="<VALID_ANNOTATIONS_DIRECTORY_PATH>",
)
ds_test = sv.DetectionDataset.from_labelme(
images_directory_path="<TEST_IMAGES_DIRECTORY_PATH>",
annotations_directory_path="<TEST_ANNOTATIONS_DIRECTORY_PATH>",
)
ds_train.classes
@@ -153,9 +212,7 @@ instances.
## Split Dataset
If your dataset is not already split into train, test, and valid subsets, you can
easily do so using the [`sv.DetectionDataset.split`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.split)
method. We can split it as follows, ensuring a random shuffle of the data.
If your dataset is not already split into train, test, and valid subsets, you can easily do so using the [`sv.DetectionDataset.split`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.split) method. We can split it as follows, ensuring a random shuffle of the data.
```python
import supervision as sv
@@ -174,9 +231,7 @@ len(ds_train), len(ds_valid), len(ds_test)
## Merge Dataset
If you have multiple datasets that you would like to merge, you can do so using the
[`sv.DetectionDataset.merge`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.merge)
method.
If you have multiple datasets that you would like to merge, you can do so using the [`sv.DetectionDataset.merge`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.merge) method.
=== "COCO"
@@ -280,12 +335,75 @@ method.
# 1000
```
=== "CreateML"
```{ .py hl_lines="22-28" }
import supervision as sv
ds_train = sv.DetectionDataset.from_createml(
images_directory_path=f'{dataset.location}/train',
annotations_path=f'{dataset.location}/train/_annotations.createml.json',
)
ds_valid = sv.DetectionDataset.from_createml(
images_directory_path=f'{dataset.location}/valid',
annotations_path=f'{dataset.location}/valid/_annotations.createml.json',
)
ds_test = sv.DetectionDataset.from_createml(
images_directory_path=f'{dataset.location}/test',
annotations_path=f'{dataset.location}/test/_annotations.createml.json',
)
ds_train.classes
# ['person', 'bicycle', 'car', ...]
len(ds_train), len(ds_valid), len(ds_test)
# 800, 100, 100
ds = sv.DetectionDataset.merge([ds_train, ds_valid, ds_test])
ds.classes
# ['person', 'bicycle', 'car', ...]
len(ds)
# 1000
```
=== "LabelMe"
```{ .py hl_lines="22-28" }
import supervision as sv
ds_train = sv.DetectionDataset.from_labelme(
images_directory_path="<TRAIN_IMAGES_DIRECTORY_PATH>",
annotations_directory_path="<TRAIN_ANNOTATIONS_DIRECTORY_PATH>",
)
ds_valid = sv.DetectionDataset.from_labelme(
images_directory_path="<VALID_IMAGES_DIRECTORY_PATH>",
annotations_directory_path="<VALID_ANNOTATIONS_DIRECTORY_PATH>",
)
ds_test = sv.DetectionDataset.from_labelme(
images_directory_path="<TEST_IMAGES_DIRECTORY_PATH>",
annotations_directory_path="<TEST_ANNOTATIONS_DIRECTORY_PATH>",
)
ds_train.classes
# ['person', 'bicycle', 'car', ...]
len(ds_train), len(ds_valid), len(ds_test)
# 800, 100, 100
ds = sv.DetectionDataset.merge([ds_train, ds_valid, ds_test])
ds.classes
# ['person', 'bicycle', 'car', ...]
len(ds)
# 1000
```
## Iterate over Dataset
There are two ways to loop over a `sv.DetectionDataset`: using a direct
[for loop](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.__iter__)
called on the `sv.DetectionDataset` instance or loading `sv.DetectionDataset` entries
[by index](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.__getitem__).
There are two ways to loop over a `sv.DetectionDataset`: using a direct [for loop](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.__iter__) called on the `sv.DetectionDataset` instance or loading `sv.DetectionDataset` entries [by index](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.__getitem__).
```python
import supervision as sv
@@ -294,23 +412,17 @@ ds = sv.DetectionDataset(...)
# Option 1
for image_path, image, annotations in ds:
... # Process each image and its annotations
... # Process each image and its annotations
# Option 2
for idx in range(len(ds)):
image_path, image, annotations = ds[idx]
... # Process the image and annotations at index `idx`
... # Process the image and annotations at index `idx`
```
## Visualize Dataset
The Supervision library provides tools for easily visualizing your detection dataset.
You can create a grid of annotated images to quickly inspect your data and labels.
First, initialize the [`sv.BoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator)
and [`sv.LabelAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator).
Then, iterate through a subset of the dataset (e.g., the first 25 images), drawing
bounding boxes and class labels on each image. Finally, combine the annotated images
into a grid for display.
The Supervision library provides tools for easily visualizing your detection dataset. You can create a grid of annotated images to quickly inspect your data and labels. First, initialize the [`sv.BoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator) and [`sv.LabelAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator). Then, iterate through a subset of the dataset (e.g., the first 25 images), drawing bounding boxes and class labels on each image. Finally, combine the annotated images into a grid for display.
```python
import supervision as sv
@@ -331,12 +443,9 @@ for i in range(16):
annotated_image = label_annotator.annotate(annotated_image, annotations, labels)
annotated_images.append(annotated_image)
grid = sv.create_tiles(
sv.plot_images_grid(
annotated_images,
grid_size=(4, 4),
single_tile_size=(400, 400),
tile_padding_color=sv.Color.WHITE,
tile_margin_color=sv.Color.WHITE
)
```
@@ -354,8 +463,8 @@ grid = sv.create_tiles(
ds = sv.DetectionDataset(...)
ds.as_coco(
images_directory_path='<IMAGE_DIRECTORY_PATH>',
annotations_path='<ANNOTATIONS_PATH>'
images_directory_path="<IMAGE_DIRECTORY_PATH>",
annotations_path="<ANNOTATIONS_PATH>",
)
```
@@ -369,9 +478,9 @@ grid = sv.create_tiles(
ds = sv.DetectionDataset(...)
ds.as_yolo(
images_directory_path='<IMAGE_DIRECTORY_PATH>',
annotations_directory_path='<ANNOTATIONS_DIRECTORY_PATH>',
data_yaml_path='<DATA_YAML_PATH>'
images_directory_path="<IMAGE_DIRECTORY_PATH>",
annotations_directory_path="<ANNOTATIONS_DIRECTORY_PATH>",
data_yaml_path="<DATA_YAML_PATH>",
)
```
@@ -385,29 +494,50 @@ grid = sv.create_tiles(
ds = sv.DetectionDataset(...)
ds.as_pascal_voc(
images_directory_path='<IMAGE_DIRECTORY_PATH>',
annotations_directory_path='<ANNOTATIONS_DIRECTORY_PATH>'
images_directory_path="<IMAGE_DIRECTORY_PATH>",
annotations_directory_path="<ANNOTATIONS_DIRECTORY_PATH>",
)
```
=== "CreateML"
We can do so using the [`sv.DetectionDataset.as_createml`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.as_createml) method to save annotations in [CreateML](https://roboflow.com/formats/createml-json) format.
```python
import supervision as sv
ds = sv.DetectionDataset(...)
ds.as_createml(
images_directory_path="<IMAGE_DIRECTORY_PATH>",
annotations_path="<ANNOTATIONS_PATH>",
)
```
=== "LabelMe"
We can do so using the [`sv.DetectionDataset.as_labelme`](https://supervision.roboflow.com/latest/datasets/core/#supervision.dataset.core.DetectionDataset.as_labelme) method to save annotations in [LabelMe](https://roboflow.com/formats/labelme-json) format. Detections with masks are exported as `polygon` shapes; box-only detections are exported as `rectangle` shapes.
```python
import supervision as sv
ds = sv.DetectionDataset(...)
ds.as_labelme(
images_directory_path="<IMAGE_DIRECTORY_PATH>",
annotations_directory_path="<ANNOTATIONS_DIRECTORY_PATH>",
)
```
## Augment Dataset
In this section, we'll explore using Supervision in combination with Albumentations to
augment our dataset. Data augmentation is a common technique in computer vision to
increase the size and diversity of training datasets, leading to improved model
performance and generalization.
In this section, we'll explore using Supervision in combination with Albumentations to augment our dataset. Data augmentation is a common technique in computer vision to increase the size and diversity of training datasets, leading to improved model performance and generalization.
```bash
pip install augmentation
pip install albumentations
```
Albumentations provides a flexible and powerful API for image augmentation. The core of
the library is the [`Compose`](https://albumentations.ai/docs/api_reference/full_reference/?h=compose#albumentations.core.composition.Compose)
class, which allows you to chain multiple image transformations together. Each
transformation is defined using a dedicated class, such as
[`HorizontalFlip`](https://albumentations.ai/docs/api_reference/full_reference/?h=horizontalflip#albumentations.augmentations.geometric.transforms.HorizontalFlip),
[`RandomBrightnessContrast`](https://albumentations.ai/docs/api_reference/full_reference/?h=horizontalflip#albumentations.augmentations.transforms.RandomBrightnessContrast),
or [`Perspective`](https://albumentations.ai/docs/api_reference/full_reference/?h=horizontalflip#albumentations.augmentations.geometric.transforms.Perspective).
Albumentations provides a flexible and powerful API for image augmentation. The core of the library is the [`Compose`](https://albumentations.ai/docs/api-reference/albumentations/core/composition/#Compose) class, which allows you to chain multiple image transformations together. Each transformation is defined using a dedicated class, such as [`HorizontalFlip`](https://albumentations.ai/docs/api-reference/albumentations/augmentations/geometric/flip/#HorizontalFlip), [`RandomBrightnessContrast`](https://albumentations.ai/docs/api-reference/albumentations/augmentations/pixel/transforms/#RandomBrightnessContrast), or [`Perspective`](https://albumentations.ai/docs/api-reference/albumentations/augmentations/geometric/transforms/#Perspective).
```python
import albumentations as A
@@ -416,17 +546,16 @@ augmentation = A.Compose(
transforms=[
A.Perspective(p=0.1),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.5)
A.RandomBrightnessContrast(p=0.5),
],
bbox_params=A.BboxParams(
format='pascal_voc',
label_fields=['category']
format="pascal_voc",
label_fields=["category"],
),
)
```
The key is to set `format='pascal_voc'`, which corresponds to the
`[x_min, y_min, x_max, y_max]` bounding box format used in Supervision.
The key is to set `format='pascal_voc'`, which corresponds to the `[x_min, y_min, x_max, y_max]` bounding box format used in Supervision.
```python
import numpy as np
@@ -440,15 +569,37 @@ _, original_image, original_annotations = ds[0]
output = augmentation(
image=original_image,
bboxes=original_annotations.xyxy,
category=original_annotations.class_id
category=original_annotations.class_id,
)
augmented_image = output['image']
augmented_image = output["image"]
augmented_annotations = replace(
original_annotations,
xyxy=np.array(output['bboxes']),
class_id=np.array(output['category'])
xyxy=np.array(output["bboxes"]),
class_id=np.array(output["category"]),
)
```
![augment-dataset](https://media.roboflow.com/supervision-docs/augment-dataset.png)
## Frequently Asked Questions
### What dataset formats does supervision support?
For detection datasets, supervision supports YOLO, COCO JSON, Pascal VOC, CreateML, and LabelMe. Use `DetectionDataset.from_yolo()`, `from_coco()`, `from_pascal_voc()`, `from_createml()`, or `from_labelme()` to load, and `as_yolo()`, `as_coco()`, `as_pascal_voc()`, `as_createml()`, or `as_labelme()` to save. Classification datasets use `ClassificationDataset.from_folder_structure()` and `as_folder_structure()`.
### Can I split a dataset into train/val/test sets?
`DetectionDataset.split(split_ratio=0.8)` returns exactly two datasets: train (80%) and test (20%). If you need a validation set, split one of those subsets in a separate step.
### Can I merge two datasets together?
Yes. `DetectionDataset.merge([dataset_a, dataset_b])` combines multiple datasets into one. Useful for combining datasets from different sources.
### What augmentations are available?
Common augmentations such as flip, rotate, translate, scale, crop, color jitter, and Gaussian blur can be applied using an external library like Albumentations, as shown in the augmentation example above. Supervision does not provide an `sv.Augmenter` pipeline.
## Author
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
+70 -51
View File
@@ -1,52 +1,53 @@
---
comments: true
description: Save object detection results to CSV or JSON with supervision's CSVSink and JSONSink — export predictions for analysis and downstream pipelines.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
date_modified: 2026-04-22
---
# Save Detections
Supervision enables an easy way to save detections in .CSV and .JSON files for offline
processing. This guide demonstrates how to perform video inference using the
[Inference](https://github.com/roboflow/inference),
[Ultralytics](https://github.com/ultralytics/ultralytics) or
[Transformers](https://github.com/huggingface/transformers) packages and save their results with
[`sv.CSVSink`](/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink) and
[`sv.JSONSink`](/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.JSONSink).
Supervision enables an easy way to save detections in .CSV and .JSON files for offline processing. This guide demonstrates how to perform video inference using the [Inference](https://github.com/roboflow/inference), [Ultralytics](https://github.com/ultralytics/ultralytics) or [Transformers](https://github.com/huggingface/transformers) packages and save their results with [`sv.CSVSink`](https://supervision.roboflow.com/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink) and [`sv.JSONSink`](https://supervision.roboflow.com/latest/detection/tools/save_detections/#supervision.detection.tools.json_sink.JSONSink).
## Run Detection
First, you'll need to obtain predictions from your object detection or segmentation
model. You can learn more on this topic in our
[How to Detect and Annotate](/latest/how_to/detect_and_annotate.md) guide.
First, you'll need to obtain predictions from your object detection or segmentation model. You can learn more on this topic in our [How to Detect and Annotate](https://supervision.roboflow.com/latest/how_to/detect_and_annotate/) guide.
To generate predictions for saving, initialize your model and iterate over video frames using `sv.get_video_frames_generator`. Each frame is passed to the model, and the raw output is converted into a `sv.Detections` object. This detection loop forms the foundation for both CSV and JSON export workflows shown below.
=== "Inference"
```python
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8n-640")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
for frame in frames_generator:
results = model.infer(image)[0]
detections = sv.Detections.from_inference(results)
```
=== "Ultralytics"
```python
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
for frame in frames_generator:
results = model(frame)[0]
detections = sv.Detections.from_ultralytics(results)
```
=== "Transformers"
```python
import torch
import supervision as sv
@@ -54,10 +55,9 @@ model. You can learn more on this topic in our
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
for frame in frames_generator:
frame = sv.cv2_to_pillow(frame)
inputs = processor(images=frame, return_tensors="pt")
@@ -67,27 +67,25 @@ model. You can learn more on this topic in our
width, height = frame.size
target_size = torch.tensor([[height, width]])
results = processor.post_process_object_detection(
outputs=outputs, target_sizes=target_size)[0]
outputs=outputs, target_sizes=target_size
)[0]
detections = sv.Detections.from_transformers(results)
```
## Save Detections as CSV
To save detections to a `.CSV` file, open our
[`sv.CSVSink`](/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink)
and then pass the
[`sv.Detections`](/latest/detection/core/#supervision.detection.core.Detections)
object resulting from the inference to it. Its fields are parsed and saved on disk.
To save detections to a `.CSV` file, open our [`sv.CSVSink`](https://supervision.roboflow.com/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink) and then pass the [`sv.Detections`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections) object resulting from the inference to it. Its fields are parsed and saved on disk.
=== "Inference"
```{ .py hl_lines="7 12" }
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8n-640")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.CSVSink(<TARGET_CSV_PATH>) as sink:
with sv.CSVSink("<TARGET_CSV_PATH>") as sink:
for frame in frames_generator:
results = model.infer(image)[0]
@@ -96,14 +94,15 @@ object resulting from the inference to it. Its fields are parsed and saved on di
```
=== "Ultralytics"
```{ .py hl_lines="7 12" }
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.CSVSink(<TARGET_CSV_PATH>) as sink:
with sv.CSVSink("<TARGET_CSV_PATH>") as sink:
for frame in frames_generator:
results = model(frame)[0]
@@ -112,6 +111,7 @@ object resulting from the inference to it. Its fields are parsed and saved on di
```
=== "Transformers"
```{ .py hl_lines="9 23" }
import torch
import supervision as sv
@@ -119,9 +119,9 @@ object resulting from the inference to it. Its fields are parsed and saved on di
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.CSVSink(<TARGET_CSV_PATH>) as sink:
with sv.CSVSink("<TARGET_CSV_PATH>") as sink:
for frame in frames_generator:
frame = sv.cv2_to_pillow(frame)
@@ -146,22 +146,18 @@ object resulting from the inference to it. Its fields are parsed and saved on di
## Custom Fields
Besides regular fields in
[`sv.Detections`](/latest/detection/core/#supervision.detection.core.Detections),
[`sv.CSVSink`](/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink)
also allows you to add custom information to each row, which can be passed via the
`custom_data` dictionary. Let's utilize this feature to save information about the
frame index from which the detections originate.
Besides regular fields in [`sv.Detections`](https://supervision.roboflow.com/latest/detection/core/#supervision.detection.core.Detections), [`sv.CSVSink`](https://supervision.roboflow.com/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink) also allows you to add custom information to each row, which can be passed via the `custom_data` dictionary. Let's utilize this feature to save information about the frame index from which the detections originate.
=== "Inference"
```{ .py hl_lines="8 12" }
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8n-640")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.CSVSink(<TARGET_CSV_PATH>) as sink:
with sv.CSVSink("<TARGET_CSV_PATH>") as sink:
for frame_index, frame in enumerate(frames_generator):
results = model.infer(image)[0]
@@ -170,14 +166,15 @@ frame index from which the detections originate.
```
=== "Ultralytics"
```{ .py hl_lines="8 12" }
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.CSVSink(<TARGET_CSV_PATH>) as sink:
with sv.CSVSink("<TARGET_CSV_PATH>") as sink:
for frame_index, frame in enumerate(frames_generator):
results = model(frame)[0]
@@ -186,6 +183,7 @@ frame index from which the detections originate.
```
=== "Transformers"
```{ .py hl_lines="10 23" }
import torch
import supervision as sv
@@ -193,9 +191,9 @@ frame index from which the detections originate.
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.CSVSink(<TARGET_CSV_PATH>) as sink:
with sv.CSVSink("<TARGET_CSV_PATH>") as sink:
for frame_index, frame in enumerate(frames_generator):
frame = sv.cv2_to_pillow(frame)
@@ -220,21 +218,18 @@ frame index from which the detections originate.
## Save Detections as JSON
If you prefer to save the result in a `.JSON` file instead of a `.CSV` file, all you
need to do is replace
[`sv.CSVSink`](/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink)
with
[`sv.JSONSink`](/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.JSONSink).
If you prefer to save the result in a `.JSON` file instead of a `.CSV` file, all you need to do is replace [`sv.CSVSink`](https://supervision.roboflow.com/latest/detection/tools/save_detections/#supervision.detection.tools.csv_sink.CSVSink) with [`sv.JSONSink`](https://supervision.roboflow.com/latest/detection/tools/save_detections/#supervision.detection.tools.json_sink.JSONSink).
=== "Inference"
```{ .py hl_lines="7" }
import supervision as sv
from inference import get_model
model = get_model(model_id="yolov8n-640")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.JSONSink(<TARGET_CSV_PATH>) as sink:
with sv.JSONSink("<TARGET_JSON_PATH>") as sink:
for frame_index, frame in enumerate(frames_generator):
results = model.infer(image)[0]
@@ -243,14 +238,15 @@ with
```
=== "Ultralytics"
```{ .py hl_lines="7" }
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.JSONSink(<TARGET_CSV_PATH>) as sink:
with sv.JSONSink("<TARGET_JSON_PATH>") as sink:
for frame_index, frame in enumerate(frames_generator):
results = model(frame)[0]
@@ -259,6 +255,7 @@ with
```
=== "Transformers"
```{ .py hl_lines="9" }
import torch
import supervision as sv
@@ -266,9 +263,9 @@ with
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50")
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator("<SOURCE_VIDEO_PATH>")
with sv.JSONSink(<TARGET_CSV_PATH>) as sink:
with sv.JSONSink("<TARGET_JSON_PATH>") as sink:
for frame_index, frame in enumerate(frames_generator):
frame = sv.cv2_to_pillow(frame)
@@ -284,3 +281,25 @@ with
detections = sv.Detections.from_transformers(results)
sink.append(detections, {"frame_index": frame_index})
```
## Frequently Asked Questions
### How do I save detections to CSV with supervision?
Open `sv.CSVSink("output.csv")` as a context manager and call `sink.append(detections)` for each frame. The CSV includes box coordinates, confidence, class ID, tracker ID, and any fields stored in `detections.data`.
### Can I save detections to JSON instead?
Yes. Open `sv.JSONSink("output.json")` as a context manager and call `sink.append(detections)` for each frame. The file is written as a JSON array when the context exits.
### Can I add custom fields to the saved output?
Yes. Pass a dict as the second argument: `sink.append(detections, {"frame_index": 5})` — the keys become extra columns in the CSV or extra fields in the JSON.
### Can I save only specific classes or confidence levels?
Filter the `Detections` object before saving: `sink.append(detections[detections.confidence > 0.7])`.
## Author
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
+72 -65
View File
@@ -1,24 +1,25 @@
---
comments: true
status: new
description: Track objects across video frames with ByteTrack in supervision — assign persistent IDs and analyze motion from any object detection model.
authors:
- name: Piotr Skalski
role: Computer Vision Engineer, Roboflow
github: https://github.com/SkalskiP
- name: Soumik Mandal
role: ML Engineer, Roboflow
github: https://github.com/soumik12345
date_modified: 2026-04-22
---
# Track Objects
Leverage Supervision's advanced capabilities for enhancing your video analysis by
seamlessly [tracking](/latest/trackers/) objects recognized by
a multitude of object detection, segmentation and keypoint models. This comprehensive guide will
take you through the steps to perform inference using the YOLOv8 model via either the
[Inference](https://github.com/roboflow/inference) or
[Ultralytics](https://github.com/ultralytics/ultralytics) packages. Following this,
you'll discover how to track these objects efficiently and annotate your video content
for a deeper analysis.
Leverage Supervision's advanced capabilities for enhancing your video analysis by seamlessly [tracking](https://supervision.roboflow.com/latest/trackers/) objects recognized by a multitude of object detection, segmentation and keypoint models. This comprehensive guide will take you through the steps to perform inference using the YOLOv8 model via either the [Inference](https://github.com/roboflow/inference) or [Ultralytics](https://github.com/ultralytics/ultralytics) packages. Following this, you'll discover how to track these objects efficiently and annotate your video content for a deeper analysis.
## Object Detection & Segmentation
To make it easier for you to follow our tutorial download the video we will use as an
example. You can do this using
[`supervision[assets]`](/latest/assets/) extension.
To make it easier for you to follow our tutorial download the video we will use as an example. You can do this using the [`supervision.assets`](https://supervision.roboflow.com/latest/assets/) module included in the base package.
This section demonstrates how to detect and segment objects in video frames using YOLOv8 with either the Inference or Ultralytics package. You will download a sample video, define a per-frame callback function that runs model prediction, and process the entire video to produce an annotated output file.
```python
from supervision.assets import download_assets, VideoAssets
@@ -32,16 +33,9 @@ download_assets(VideoAssets.PEOPLE_WALKING)
### Run Inference
First, you'll need to obtain predictions from your object detection or segmentation
model. In this tutorial, we are using the YOLOv8 model as an example. However,
Supervision is versatile and compatible with various models. Check this
[link](/latest/how_to/detect_and_annotate/#load-predictions-into-supervision)
for guidance on how to plug in other models.
First, you'll need to obtain predictions from your object detection or segmentation model. In this tutorial, we are using the YOLOv8 model as an example. However, Supervision is versatile and compatible with various models. Check this [link](https://supervision.roboflow.com/latest/how_to/detect_and_annotate/#load-predictions-into-supervision) for guidance on how to plug in other models.
We will define a `callback` function, which will process each frame of the video
by obtaining model predictions and then annotating the frame based on these predictions.
This `callback` function will be essential in the subsequent steps of the tutorial, as
it will be modified to include tracking, labeling, and trace annotations.
We will define a `callback` function, which will process each frame of the video by obtaining model predictions and then annotating the frame based on these predictions. This `callback` function will be essential in the subsequent steps of the tutorial, as it will be modified to include tracking, labeling, and trace annotations.
!!! tip
@@ -76,7 +70,7 @@ it will be modified to include tracking, labeling, and trace annotations.
import supervision as sv
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(model_id="yolov8n-640", api_key=<ROBOFLOW API KEY>)
model = get_roboflow_model(model_id="yolov8n-640", api_key="<ROBOFLOW_API_KEY>")
box_annotator = sv.BoxAnnotator()
def callback(frame: np.ndarray, _: int) -> np.ndarray:
@@ -97,11 +91,11 @@ it will be modified to include tracking, labeling, and trace annotations.
### Tracking
After running inference and obtaining predictions, the next step is to track the
detected objects throughout the video. Utilizing Supervision’s
[`sv.ByteTrack`](/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.
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"
@@ -134,7 +128,7 @@ enabling the continuous following of the object's motion path across different f
import supervision as sv
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(model_id="yolov8n-640", api_key=<ROBOFLOW API KEY>)
model = get_roboflow_model(model_id="yolov8n-640", api_key="<ROBOFLOW_API_KEY>")
tracker = sv.ByteTrack()
box_annotator = sv.BoxAnnotator()
@@ -153,11 +147,7 @@ enabling the continuous following of the object's motion path across different f
### Annotate Video with Tracking IDs
Annotating the video with tracking IDs helps in distinguishing and following each object
distinctly. With the
[`sv.LabelAnnotator`](/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator)
in Supervision, we can overlay the tracker IDs and class labels on the detected objects,
offering a clear visual representation of each object's class and unique identifier.
Annotating the video with tracking IDs helps in distinguishing and following each object distinctly. With the [`sv.LabelAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator) in Supervision, we can overlay the tracker IDs and class labels on the detected objects, offering a clear visual representation of each object's class and unique identifier.
=== "Ultralytics"
@@ -177,9 +167,9 @@ offering a clear visual representation of each object's class and unique identif
detections = tracker.update_with_detections(detections)
labels = [
f"#{tracker_id} {results.names[class_id]}"
for class_id, tracker_id
in zip(detections.class_id, detections.tracker_id)
f"#{tracker_id} {class_name}"
for class_name, tracker_id
in zip(detections.data["class_name"], detections.tracker_id)
]
annotated_frame = box_annotator.annotate(
@@ -201,7 +191,7 @@ offering a clear visual representation of each object's class and unique identif
import supervision as sv
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(model_id="yolov8n-640", api_key=<ROBOFLOW API KEY>)
model = get_roboflow_model(model_id="yolov8n-640", api_key="<ROBOFLOW_API_KEY>")
tracker = sv.ByteTrack()
box_annotator = sv.BoxAnnotator()
label_annotator = sv.LabelAnnotator()
@@ -212,9 +202,9 @@ offering a clear visual representation of each object's class and unique identif
detections = tracker.update_with_detections(detections)
labels = [
f"#{tracker_id} {results.names[class_id]}"
for class_id, tracker_id
in zip(detections.class_id, detections.tracker_id)
f"#{tracker_id} {class_name}"
for class_name, tracker_id
in zip(detections.data["class_name"], detections.tracker_id)
]
annotated_frame = box_annotator.annotate(
@@ -235,11 +225,7 @@ offering a clear visual representation of each object's class and unique identif
### Annotate Video with Traces
Adding traces to the video involves overlaying the historical paths of the detected
objects. This feature, powered by the
[`sv.TraceAnnotator`](/latest/detection/annotators/#supervision.annotators.core.TraceAnnotator),
allows for visualizing the trajectories of objects, helping in understanding the
movement patterns and interactions between objects in the video.
Adding traces to the video involves overlaying the historical paths of the detected objects. This feature, powered by the [`sv.TraceAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.TraceAnnotator), allows for visualizing the trajectories of objects, helping in understanding the movement patterns and interactions between objects in the video.
=== "Ultralytics"
@@ -260,9 +246,9 @@ movement patterns and interactions between objects in the video.
detections = tracker.update_with_detections(detections)
labels = [
f"#{tracker_id} {results.names[class_id]}"
for class_id, tracker_id
in zip(detections.class_id, detections.tracker_id)
f"#{tracker_id} {class_name}"
for class_name, tracker_id
in zip(detections.data["class_name"], detections.tracker_id)
]
annotated_frame = box_annotator.annotate(
@@ -286,7 +272,7 @@ movement patterns and interactions between objects in the video.
import supervision as sv
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(model_id="yolov8n-640", api_key=<ROBOFLOW API KEY>)
model = get_roboflow_model(model_id="yolov8n-640", api_key="<ROBOFLOW_API_KEY>")
tracker = sv.ByteTrack()
box_annotator = sv.BoxAnnotator()
label_annotator = sv.LabelAnnotator()
@@ -298,9 +284,9 @@ movement patterns and interactions between objects in the video.
detections = tracker.update_with_detections(detections)
labels = [
f"#{tracker_id} {results.names[class_id]}"
for class_id, tracker_id
in zip(detections.class_id, detections.tracker_id)
f"#{tracker_id} {class_name}"
for class_name, tracker_id
in zip(detections.data["class_name"], detections.tracker_id)
]
annotated_frame = box_annotator.annotate(
@@ -325,8 +311,7 @@ movement patterns and interactions between objects in the video.
Models aren't limited to object detection and segmentation. Keypoint detection allows for detailed analysis of body joints and connections, especially valuable for applications like human pose estimation. This section introduces keypoint tracking. We'll walk through the steps of annotating keypoints, converting them into bounding box detections compatible with `ByteTrack`, and applying detection smoothing for enhanced stability.
To make it easier for you to follow our tutorial, let's download the video we will use as an
example. You can do this using [`supervision[assets]`](/latest/assets/) extension.
To make it easier for you to follow our tutorial, let's download the video we will use as an example. You can do this using the [`supervision.assets`](https://supervision.roboflow.com/latest/assets/) module included in the base package.
```python
from supervision.assets import download_assets, VideoAssets
@@ -340,12 +325,11 @@ download_assets(VideoAssets.SKIING)
### Keypoint Detection
First, you'll need to obtain predictions from your keypoint detection model. In this tutorial, we are using the YOLOv8 model as an example. However,
Supervision is versatile and compatible with various models. Check this [link](/latest/keypoint/core/) for guidance on how to plug in other models.
First, you'll need to obtain predictions from your keypoint detection model. In this tutorial, we are using the YOLOv8 model as an example. However, Supervision is versatile and compatible with various models. Check this [link](https://supervision.roboflow.com/latest/keypoint/core/) for guidance on how to plug in other models.
We will define a `callback` function, which will process each frame of the video by obtaining model predictions and then annotating the frame based on these predictions.
Let's immediately visualize the results with our [`EdgeAnnotator`](/latest/keypoint/annotators/#supervision.keypoint.annotators.EdgeAnnotator) and [`VertexAnnotator`](https://supervision.roboflow.com/latest/keypoint/annotators/#supervision.keypoint.annotators.VertexAnnotator).
Let's immediately visualize the results with our [`EdgeAnnotator`](https://supervision.roboflow.com/latest/keypoint/annotators/#supervision.key_points.annotators.EdgeAnnotator) and [`VertexAnnotator`](https://supervision.roboflow.com/latest/keypoint/annotators/#supervision.key_points.annotators.VertexAnnotator).
=== "Ultralytics"
@@ -382,7 +366,7 @@ Let's immediately visualize the results with our [`EdgeAnnotator`](/latest/keypo
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(
model_id="yolov8m-pose-640", api_key=<ROBOFLOW API KEY>)
model_id="yolov8m-pose-640", api_key="<ROBOFLOW_API_KEY>")
edge_annotator = sv.EdgeAnnotator()
vertex_annotator = sv.VertexAnnotator()
@@ -408,9 +392,9 @@ Let's immediately visualize the results with our [`EdgeAnnotator`](/latest/keypo
### Convert to Detections
Keypoint tracking is currently supported via the conversion of `KeyPoints` to `Detections`. This is achieved with the [`KeyPoints.as_detections()`](/latest/keypoint/core/#supervision.keypoint.core.KeyPoints.as_detections) function.
Keypoint tracking is currently supported via the conversion of `KeyPoints` to `Detections`. This is achieved with the [`KeyPoints.as_detections()`](https://supervision.roboflow.com/latest/keypoint/core/#supervision.key_points.core.KeyPoints.as_detections) function.
Let's convert to detections and visualize the results with our [`BoxAnnotator`](/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator).
Let's convert to detections and visualize the results with our [`BoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator).
!!! tip
@@ -455,7 +439,7 @@ Let's convert to detections and visualize the results with our [`BoxAnnotator`](
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(
model_id="yolov8m-pose-640", api_key=<ROBOFLOW API KEY>)
model_id="yolov8m-pose-640", api_key="<ROBOFLOW_API_KEY>")
edge_annotator = sv.EdgeAnnotator()
vertex_annotator = sv.VertexAnnotator()
box_annotator = sv.BoxAnnotator()
@@ -485,7 +469,7 @@ Let's convert to detections and visualize the results with our [`BoxAnnotator`](
### Keypoint Tracking
Now that we have a `Detections` object, we can track it throughout the video. Utilizing Supervision’s [`sv.ByteTrack`](/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. We shall visualize the result with `TraceAnnotator`.
Now that we have a `Detections` object, we can track it 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. We shall visualize the result with `TraceAnnotator`.
=== "Ultralytics"
@@ -532,7 +516,7 @@ Now that we have a `Detections` object, we can track it throughout the video. Ut
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(
model_id="yolov8m-pose-640", api_key=<ROBOFLOW API KEY>)
model_id="yolov8m-pose-640", api_key="<ROBOFLOW_API_KEY>")
edge_annotator = sv.EdgeAnnotator()
vertex_annotator = sv.VertexAnnotator()
box_annotator = sv.BoxAnnotator()
@@ -568,7 +552,7 @@ Now that we have a `Detections` object, we can track it throughout the video. Ut
### Bonus: Smoothing
We could stop here as we have successfully tracked the object detected by the keypoint model. However, we can further enhance the stability of the boxes by applying [`DetectionsSmoother`](/latest/detection/tools/smoother/). This tool helps in stabilizing the boxes by smoothing the bounding box coordinates across frames. It is very simple to use:
We could stop here as we have successfully tracked the object detected by the keypoint model. However, we can further enhance the stability of the boxes by applying [`DetectionsSmoother`](https://supervision.roboflow.com/latest/detection/tools/smoother/). This tool helps in stabilizing the boxes by smoothing the bounding box coordinates across frames. It is very simple to use:
=== "Ultralytics"
@@ -617,7 +601,7 @@ We could stop here as we have successfully tracked the object detected by the ke
from inference.models.utils import get_roboflow_model
model = get_roboflow_model(
model_id="yolov8m-pose-640", api_key=<ROBOFLOW API KEY>)
model_id="yolov8m-pose-640", api_key="<ROBOFLOW_API_KEY>")
edge_annotator = sv.EdgeAnnotator()
vertex_annotator = sv.VertexAnnotator()
box_annotator = sv.BoxAnnotator()
@@ -654,3 +638,26 @@ We could stop here as we have successfully tracked the object detected by the ke
</video>
This structured walkthrough should give a detailed pathway to annotate videos effectively using Supervision’s various functionalities, including object tracking and trace annotations.
## Frequently Asked Questions
### How do I track objects across video frames with supervision?
Pass `Detections` to `sv.ByteTrack.update_with_detections()` on each frame. The tracker assigns persistent IDs. Combine with `sv.TraceAnnotator` to visualize trajectories. `sv.ByteTrack` is deprecated in favor of `ByteTrackTracker` from the `trackers` package, where the update method is named `update()`.
### What should I know about ByteTrack?
ByteTrack uses low-confidence detections during association, which can improve continuity during missed or weak detections. Supervision's built-in `ByteTrack` wrapper is deprecated in favor of the external `trackers` package.
### Can I track instances instead of bounding boxes?
Yes. ByteTrack tracks bounding boxes. For instance masks, use `sv.MaskAnnotator` with the tracker IDs to color-code each tracked object consistently.
### Does ByteTrack work with any detection model?
Yes. ByteTrack is model-agnostic - it accepts any `Detections` object with bounding boxes, regardless of the supported converter or model output that produced it.
## Authors
- [Piotr Skalski](https://github.com/SkalskiP) — Computer Vision Engineer, Roboflow
- [Soumik Mandal](https://github.com/soumik12345) — ML Engineer, Roboflow
+193
View File
@@ -0,0 +1,193 @@
---
comments: true
description: Use CompactMask for memory-efficient instance segmentation in supervision — ingest COCO RLE payloads, skip mask materialisation, and merge mixed dense and compact detections without allocating a full pixel stack.
authors:
- name: Borda
role: Open Source Engineer, Roboflow
github: https://github.com/borda
date_modified: 2026-07-01
---
# Use Compact Masks for Memory-Efficient Segmentation
[CompactMask][supervision.detection.compact_mask.CompactMask] stores each instance mask as a run-length encoding of its bounding-box **crop** rather than a full `(H, W)` boolean frame. For high-resolution images with many sparse masks this can reduce memory from tens of gigabytes to tens of megabytes, and eliminates full-frame decode work in annotators that only need the cropped region.
!!! Note
`sv.mask_to_xyxy` keeps supervision's inclusive max-coordinate convention for compatibility with `CompactMask` and current box-based adapters. Use `sv.mask_to_roi` when you need exclusive slice bounds for NumPy indexing or crop extraction.
This guide covers the four main integration points:
1. [Ingesting COCO RLE payloads directly as CompactMask](#ingest-coco-rle-payloads)
2. [Parsing Roboflow Inference results without a dense stack](#parse-inference-results)
3. [Skipping mask materialisation for box/label annotators](#skip-unnecessary-materialisation)
4. [Merging mixed dense and compact detections](#merge-mixed-detections)
---
## Ingest COCO RLE Payloads
If your model or API returns masks in the COCO RLE format (`{"size": [H, W], "counts": "..."}`) you can convert them directly to `CompactMask` without allocating an `(N, H, W)` boolean array:
```python
import numpy as np
import supervision as sv
from supervision.detection.compact_mask import CompactMask
# Example: two COCO RLE masks for a 720×1280 frame.
# Replace the counts strings with actual compressed RLE payloads from your
# model or API — e.g., from pycocotools mask.encode() or an Inference response.
rles = [
{"size": [720, 1280], "counts": "YOUR_RLE_COUNTS_STRING_HERE"},
{"size": [720, 1280], "counts": "YOUR_RLE_COUNTS_STRING_HERE"},
]
xyxy = np.array(
[
[100.0, 50.0, 400.0, 300.0],
[500.0, 200.0, 900.0, 600.0],
]
)
compact = CompactMask.from_coco_rle(rles, xyxy, image_shape=(720, 1280))
detections = sv.Detections(
xyxy=xyxy,
mask=compact,
class_id=np.array([0, 1]),
)
```
`from_coco_rle` uses run-length arithmetic scoped to each bounding box so no dense pixel array is ever created. Uncompressed integer count lists are also accepted in place of compressed strings.
---
## Parse Inference Results
`Detections.from_inference` accepts a `compact_masks=True` flag that routes the Roboflow RLE payload through `CompactMask.from_coco_rle` instead of decoding to a dense stack:
```python
import supervision as sv
# result: a Roboflow Inference v2 response dict with instance masks.
detections = sv.Detections.from_inference(result, compact_masks=True)
from supervision.detection.compact_mask import CompactMask
assert isinstance(detections.mask, CompactMask)
```
!!! Warning
`compact_masks=True` crops each mask to its detector bounding box. Pixels outside the box are silently dropped. For masks that extend meaningfully beyond the reported bounding box, use the default `compact_masks=False` (dense decode) to preserve all pixels.
To convert an existing dense-mask `Detections` to compact at any point:
```python
detections_compact = detections.to_compact_masks()
```
---
## Skip Unnecessary Materialisation
Annotators that do not draw masks (box, label, circle, ellipse, trace, keypoint) expose `requires_mask = False`. Integrations can branch on this flag to avoid decoding compact or RLE masks before annotation:
```python
import supervision as sv
annotators = [
sv.BoxAnnotator(),
sv.LabelAnnotator(),
sv.MaskAnnotator(), # requires_mask = True
]
for ann in annotators:
if ann.requires_mask:
# Annotator reads mask pixels — CompactMask decodes lazily per crop.
scene = ann.annotate(scene, detections)
else:
# Annotator ignores masks — strip mask field to eliminate any decode cost.
det_no_mask = sv.Detections(
xyxy=detections.xyxy,
confidence=detections.confidence,
class_id=detections.class_id,
)
scene = ann.annotate(scene, det_no_mask)
```
Annotators that set `requires_mask = True`: [MaskAnnotator][supervision.annotators.core.MaskAnnotator], [PolygonAnnotator][supervision.annotators.core.PolygonAnnotator], [HaloAnnotator][supervision.annotators.core.HaloAnnotator].
All others default to `requires_mask = False`.
!!! Note
`PolygonAnnotator` and `MaskAnnotator` both operate directly on `CompactMask` without materialising the full `(N, H, W)` frame — passing compact detections to them is already efficient.
---
## Merge Mixed Detections
When merging `Detections` objects that mix dense `ndarray` masks and `CompactMask` instances, `Detections.merge` converts dense inputs to `CompactMask` automatically. No full `(N, H, W)` stack is allocated:
```python
import numpy as np
import supervision as sv
from supervision.detection.compact_mask import CompactMask
H, W = 720, 1280
# Compact detections from an RLE-based source.
# Replace the counts string with a real compressed RLE payload from your model or API.
rles = [{"size": [H, W], "counts": "YOUR_RLE_COUNTS_STRING_HERE"}]
xyxy_a = np.array([[100.0, 50.0, 400.0, 300.0]])
cm = CompactMask.from_coco_rle(rles, xyxy_a, image_shape=(H, W))
det_a = sv.Detections(xyxy=xyxy_a, mask=cm, class_id=np.array([0]))
# Dense detections from a different source.
masks_b = np.zeros((1, H, W), dtype=bool)
masks_b[0, 200:400, 500:800] = True
xyxy_b = np.array([[500.0, 200.0, 799.0, 399.0]])
det_b = sv.Detections(xyxy=xyxy_b, mask=masks_b, class_id=np.array([1]))
# Output is CompactMask regardless of input order.
merged = sv.Detections.merge([det_a, det_b])
assert isinstance(merged.mask, CompactMask)
assert len(merged) == 2
```
Merge rules:
| Inputs | Output mask type |
| ------------------------------------- | ------------------------------- |
| All `CompactMask` | `CompactMask` |
| Mixed `CompactMask` + dense `ndarray` | `CompactMask` |
| All dense `ndarray` | `ndarray` (backward compatible) |
All `CompactMask` inputs must share the same `image_shape`; mismatches raise `ValueError`.
---
## Performance Notes
These estimates apply to the **parsing and annotation stage**, not end-to-end pipeline FPS. Model inference typically dominates total runtime.
| Optimisation | Realistic gain | Applies when |
| ---------------------------- | -------------------------- | ------------------------------------------------------------- |
| `from_coco_rle` ingestion | 25–60% faster parse | Full-frame COCO RLE payload; current dense decode path |
| `MaskAnnotator` ROI blending | 10–35% faster annotation | Many small, sparse masks on high-res frames |
| `PolygonAnnotator` crop path | 15–45% faster polygon draw | Many compact masks; full-frame materialise was the bottleneck |
| Mixed-mask merge | 5–20% faster merge | Mix of compact and dense sources (e.g. multi-camera stitch) |
Upper-end gains assume: ≥1080p frames, tens to hundreds of instances, masks covering less than ~20% of total pixels.
---
## API Reference
- [CompactMask][supervision.detection.compact_mask.CompactMask]
- [CompactMask.from_coco_rle][supervision.detection.compact_mask.CompactMask.from_coco_rle]
- [CompactMask.from_dense][supervision.detection.compact_mask.CompactMask.from_dense]
- [Detections.from_inference][supervision.detection.core.Detections.from_inference]
- [Detections.to_compact_masks][supervision.detection.core.Detections.to_compact_masks]
- [Detections.merge][supervision.detection.core.Detections.merge]
- [BaseAnnotator.requires_mask][supervision.annotators.base.BaseAnnotator]
+31 -20
View File
@@ -4,19 +4,34 @@ comments: true
hide:
- navigation
- toc
description: Open-source Python library providing computer vision tools for annotating detections, tracking objects, counting in zones, and processing datasets.
---
<div class="md-typeset">
<h1></h1>
</div>
<div align="center" id="logo">
<div align="center" id="logo" style="padding-top: 1rem;">
<a align="center" href="" target="_blank">
<img width="850"
src="https://media.roboflow.com/open-source/supervision/rf-supervision-banner.png?updatedAt=1678995927529">
</a>
</div>
<style>
#hello {
margin: 0;
}
</style>
## What is Supervision?
Supervision is an open-source Python library by Roboflow for building computer vision applications. It provides a unified `Detections` object with converters for supported outputs from Ultralytics, Roboflow Inference, Transformers, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers.
With Supervision you can annotate images and video with bounding boxes, masks, and labels; track objects across frames with persistent IDs; count and filter detections inside polygon zones; load and convert datasets between YOLO, COCO, and Pascal VOC formats; and benchmark model performance with mAP and confusion matrices.
Supervision is MIT licensed, has 38,000+ GitHub stars, and over 1 million monthly PyPI downloads. It is developed in public on GitHub for production computer vision workflows.
## 👋 Hello
We write your reusable computer vision tools. Whether you need to load your dataset from your hard drive, draw detections on an image or video, or count how many detections are in a zone. You can count on us!
@@ -30,36 +45,29 @@ We write your reusable computer vision tools. Whether you need to load your data
## 💻 Install
You can install `supervision` in a
[**Python>=3.8**](https://www.python.org/) environment.
You can install `supervision` in a [**Python>=3.10**](https://www.python.org/) environment.
!!! example "Installation"
=== "pip (recommended)"
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision)
[![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision)
[![license](https://img.shields.io/pypi/l/supervision)](https://github.com/roboflow/supervision/blob/main/LICENSE.md)
[![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision) [![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision) [![license](https://img.shields.io/pypi/l/supervision)](../LICENSE.md) [![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
```bash
pip install supervision
```
=== "poetry"
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision)
[![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision)
[![license](https://img.shields.io/pypi/l/supervision)](https://github.com/roboflow/supervision/blob/main/LICENSE.md)
[![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision) [![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision) [![license](https://img.shields.io/pypi/l/supervision)](../LICENSE.md) [![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
```bash
poetry add supervision
```
=== "uv"
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision)
[![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision)
[![license](https://img.shields.io/pypi/l/supervision)](https://github.com/roboflow/supervision/blob/main/LICENSE.md)
[![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision) [![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision) [![license](https://img.shields.io/pypi/l/supervision)](../LICENSE.md) [![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
```bash
uv pip install supervision
@@ -72,18 +80,17 @@ You can install `supervision` in a
```
=== "rye"
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision)
[![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision)
[![license](https://img.shields.io/pypi/l/supervision)](https://github.com/roboflow/supervision/blob/main/LICENSE.md)
[![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
[![version](https://badge.fury.io/py/supervision.svg)](https://badge.fury.io/py/supervision) [![downloads](https://img.shields.io/pypi/dm/supervision)](https://pypistats.org/packages/supervision) [![license](https://img.shields.io/pypi/l/supervision)](../LICENSE.md) [![python-version](https://img.shields.io/pypi/pyversions/supervision)](https://badge.fury.io/py/supervision)
```bash
rye add supervision
```
!!! example "conda/mamba install"
=== "conda"
[![conda-recipe](https://img.shields.io/badge/recipe-supervision-green.svg)](https://anaconda.org/conda-forge/supervision) [![conda-downloads](https://img.shields.io/conda/dn/conda-forge/supervision.svg)](https://anaconda.org/conda-forge/supervision) [![conda-version](https://img.shields.io/conda/vn/conda-forge/supervision.svg)](https://anaconda.org/conda-forge/supervision) [![conda-platforms](https://img.shields.io/conda/pn/conda-forge/supervision.svg)](https://anaconda.org/conda-forge/supervision)
```bash
@@ -91,6 +98,7 @@ You can install `supervision` in a
```
=== "mamba"
[![mamba-recipe](https://img.shields.io/badge/recipe-supervision-green.svg)](https://anaconda.org/conda-forge/supervision) [![mamba-downloads](https://img.shields.io/conda/dn/conda-forge/supervision.svg)](https://anaconda.org/conda-forge/supervision) [![mamba-version](https://img.shields.io/conda/vn/conda-forge/supervision.svg)](https://anaconda.org/conda-forge/supervision) [![mamba-platforms](https://img.shields.io/conda/pn/conda-forge/supervision.svg)](https://anaconda.org/conda-forge/supervision)
```bash
@@ -98,7 +106,9 @@ You can install `supervision` in a
```
!!! example "git clone (for development)"
=== "virtualenv"
```bash
# clone repository and navigate to root directory
git clone --depth 1 -b develop https://github.com/roboflow/supervision.git
@@ -114,6 +124,7 @@ You can install `supervision` in a
```
=== "uv"
```bash
# clone repository and navigate to root directory
git clone --depth 1 -b develop https://github.com/roboflow/supervision.git
+9 -5
View File
@@ -59,7 +59,7 @@ document.addEventListener("DOMContentLoaded", function () {
<div
class="author-container"
data-login="${authorData.login}-${elementIndex}"
style="margin-left: ${marginLeft}; z-index: ${zIndex};"
style="margin-left: ${marginLeft};"
>
<a
href="https://github.com/${authorData.login}"
@@ -90,14 +90,17 @@ document.addEventListener("DOMContentLoaded", function () {
).join(',&nbsp;');
let authorsHTML = `
<div class="authors">
<div class="authors" style="margin: 0;">
${authorAvatarsHTML}
<div class="author-names">${authorNamesHTML}</div>
</div>
`;
element.innerText = `
<div style="flex-direction: column; height: 100%; display: flex;
<div style="
display: grid !important;
grid-template-rows: auto;
height: 100%;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji; background: ${theme.background}; font-size: 14px; line-height: 1.5; color: ${theme.color}">
<div style="display: flex; align-items: center;">
<span style="font-weight: 700; font-size: 1rem; color: ${theme.linkColor};">
@@ -105,13 +108,14 @@ document.addEventListener("DOMContentLoaded", function () {
</span>
</div>
${authorsHTML}
<div style="font-size: 12px; color: ${theme.color}; display: flex; flex: 0; justify-content: space-between">
<div style="font-size: 12px; color: ${theme.color}; display: grid; grid-template-columns: auto 3fr; justify-content: space-between; gap: 1rem;">
<div style="display: flex; align-items: center;">
<img src="/assets/supervision-lenny.png" aria-label="stars" width="20" height="20" role="img" />
&nbsp;
<span style="margin-left: 4px">${version}</span>
</div>
<div style="display: flex; align-items: center; flex-wrap: wrap">
<div style="display: flex; align-items: center; flex-wrap: wrap; align-content: right;
gap: 0.1rem;">
${labelHTML}
</div>
</div>
+19
View File
@@ -0,0 +1,19 @@
window.MathJax = {
tex: {
inlineMath: [["\\(", "\\)"]],
displayMath: [["\\[", "\\]"]],
processEscapes: true,
processEnvironments: true
},
options: {
ignoreHtmlClass: ".*|",
processHtmlClass: "arithmatex"
}
};
document$.subscribe(() => {
MathJax.startup.output.clearCache()
MathJax.typesetClear()
MathJax.texReset()
MathJax.typesetPromise()
})
+197
View File
@@ -0,0 +1,197 @@
/**
* Custom copy handler for Python console (pycon) code blocks.
* Strips >>> and ... prompts when copying code examples.
*/
document.addEventListener("DOMContentLoaded", function () {
const COPY_BUTTON_SELECTOR = ".md-clipboard, .md-code__button";
function handleCopyButtonClick(event) {
const copyButton = event.target.closest(COPY_BUTTON_SELECTOR);
if (!copyButton) return;
const codeBlock = findCodeBlockForCopyButton(copyButton);
if (!codeBlock) return;
const rawText = codeBlock.textContent || "";
if (!shouldStripPrompts(codeBlock, rawText)) return;
const strippedText = stripPythonPrompts(rawText);
primeClipboardButton(copyButton, strippedText);
}
function handleCopyButtonPointerDown(event) {
const copyButton = event.target.closest(COPY_BUTTON_SELECTOR);
if (!copyButton) return;
const codeBlock = findCodeBlockForCopyButton(copyButton);
if (!codeBlock) return;
const rawText = codeBlock.textContent || "";
if (!shouldStripPrompts(codeBlock, rawText)) return;
const strippedText = stripPythonPrompts(rawText);
primeClipboardButton(copyButton, strippedText);
}
function handleSelectionCopy(event) {
const selection = window.getSelection();
if (!selection || selection.rangeCount === 0) return;
const range = selection.getRangeAt(0);
const anchorNode = range.commonAncestorContainer;
const codeBlock =
anchorNode.nodeType === Node.ELEMENT_NODE
? anchorNode.closest("code")
: anchorNode.parentElement?.closest("code");
if (!codeBlock) return;
const rawText = selection.toString();
if (!shouldStripPrompts(codeBlock, rawText)) return;
event.preventDefault();
event.stopPropagation();
const strippedText = stripPythonPrompts(rawText);
event.clipboardData?.setData("text/plain", strippedText);
}
function bindCopyButtons(root) {
root
.querySelectorAll(COPY_BUTTON_SELECTOR)
.forEach((button) => {
button.removeEventListener("click", handleCopyButtonClick, true);
button.addEventListener("click", handleCopyButtonClick, true);
button.removeEventListener(
"pointerdown",
handleCopyButtonPointerDown,
true
);
button.addEventListener(
"pointerdown",
handleCopyButtonPointerDown,
true
);
});
}
function observeDynamicCopyButtons() {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type !== "childList") continue;
mutation.addedNodes.forEach((node) => {
if (node.nodeType !== Node.ELEMENT_NODE) return;
if (node.matches?.(COPY_BUTTON_SELECTOR)) {
bindCopyButtons(node.parentElement || document);
return;
}
if (node.querySelectorAll) {
const hasButtons = node.querySelectorAll(COPY_BUTTON_SELECTOR);
if (hasButtons.length > 0) {
bindCopyButtons(node);
}
}
});
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
document.addEventListener("click", handleCopyButtonClick, true);
document.addEventListener("pointerdown", handleCopyButtonPointerDown, true);
document.addEventListener("copy", handleSelectionCopy, true);
bindCopyButtons(document);
observeDynamicCopyButtons();
});
function primeClipboardButton(copyButton, strippedText) {
copyButton.setAttribute("data-clipboard-text", strippedText);
copyButton.removeAttribute("data-clipboard-target");
copyButton.setAttribute("data-md-clipboard", "true");
}
function shouldStripPrompts(codeBlock, rawText) {
const hasReplPrompts = /(^|\n)[ \t]*(>>>|\.\.\.)/.test(rawText);
return (
hasReplPrompts ||
codeBlock.classList.contains("language-pycon") ||
codeBlock.closest("pre")?.classList.contains("pycon") ||
codeBlock.closest(".pycon") !== null ||
codeBlock.closest(".highlight")?.classList.contains("pycon")
);
}
function findCodeBlockForCopyButton(copyButton) {
const targetSelector = copyButton.getAttribute("data-clipboard-target");
if (targetSelector) {
const target = document.querySelector(targetSelector);
const targetCode = target?.querySelector?.("code") || target;
if (targetCode?.tagName?.toLowerCase() === "code") {
return targetCode;
}
}
return (
copyButton.closest("pre")?.querySelector("code") ||
copyButton.parentElement?.querySelector("pre code") ||
copyButton
.closest(".highlight, .codehilite, .md-typeset__scrollwrap, .md-typeset")
?.querySelector("pre code") ||
copyButton
.closest(".highlight, .codehilite, .md-typeset__scrollwrap, .md-typeset")
?.querySelector("code")
);
}
/**
* Strips Python REPL prompts (>>> and ...) from code text.
* Also removes output lines (lines that don't start with >>> or ...).
*
* NOTE: This is a best-effort parser. It preserves unprompted lines inside
* triple-quoted strings, but it does not fully model Python's tokenizer.
*/
function stripPythonPrompts(text) {
const lines = text.split("\n");
const codeLines = [];
let inTripleQuotedString = false;
function toggleTripleQuoteState(sourceLine) {
const tripleQuotePattern = /("""|''')/g;
const matches = sourceLine.match(tripleQuotePattern);
if (!matches) return;
if (matches.length % 2 === 1) {
inTripleQuotedString = !inTripleQuotedString;
}
}
for (const line of lines) {
const trimmedLine = line.trimEnd();
// Primary prompt: ">>> "
if (trimmedLine.startsWith(">>> ")) {
const stripped = trimmedLine.slice(4);
codeLines.push(stripped);
toggleTripleQuoteState(stripped);
}
// Continuation prompt: "... "
else if (trimmedLine.startsWith("... ")) {
const stripped = trimmedLine.slice(4);
codeLines.push(stripped);
toggleTripleQuoteState(stripped);
}
// Handle prompts without space after (edge case)
else if (trimmedLine === ">>>") {
codeLines.push("");
}
else if (trimmedLine === "...") {
codeLines.push("");
}
else if (inTripleQuotedString) {
codeLines.push(trimmedLine);
toggleTripleQuoteState(trimmedLine);
}
// Skip output lines (lines that don't start with prompts)
// This intentionally excludes output like "1.0" from the copied text
}
return codeLines.join("\n").trim();
}
+89 -15
View File
@@ -1,6 +1,5 @@
---
comments: true
status: new
---
# Annotators
@@ -15,11 +14,11 @@ status: new
vertex_annotator = sv.VertexAnnotator(
color=sv.Color.GREEN,
radius=10
radius=10,
)
annotated_frame = vertex_annotator.annotate(
scene=image.copy(),
key_points=key_points
key_points=key_points,
)
```
@@ -39,11 +38,11 @@ status: new
edge_annotator = sv.EdgeAnnotator(
color=sv.Color.GREEN,
thickness=5
thickness=5,
)
annotated_frame = edge_annotator.annotate(
scene=image.copy(),
key_points=key_points
key_points=key_points,
)
```
@@ -64,11 +63,11 @@ status: new
vertex_label_annotator = sv.VertexLabelAnnotator(
color=sv.Color.GREEN,
text_color=sv.Color.BLACK,
border_radius=5
border_radius=5,
)
annotated_frame = vertex_label_annotator.annotate(
scene=image.copy(),
key_points=key_points
key_points=key_points,
)
```
@@ -78,20 +77,95 @@ status: new
</div>
<div class="md-typeset">
<h2><a href="#supervision.keypoint.annotators.VertexAnnotator">VertexAnnotator</a></h2>
</div>
=== "VertexEllipseAreaAnnotator"
:::supervision.keypoint.annotators.VertexAnnotator
```python
import supervision as sv
image = ...
key_points = sv.KeyPoints(...)
area_annotator = sv.VertexEllipseAreaAnnotator(
color=sv.Color.GREEN,
sigma=2.0,
)
annotated_frame = area_annotator.annotate(
scene=image.copy(),
key_points=key_points,
)
```
`sv.VertexEllipseAnnotator` is a compatibility alias for `sv.VertexEllipseAreaAnnotator`.
=== "VertexEllipseOutlineAnnotator"
```python
import supervision as sv
image = ...
key_points = sv.KeyPoints(...)
outline_annotator = sv.VertexEllipseOutlineAnnotator(
color=sv.Color.GREEN,
sigma=2.0,
thickness=2,
)
annotated_frame = outline_annotator.annotate(
scene=image.copy(),
key_points=key_points,
)
```
=== "VertexEllipseHaloAnnotator"
```python
import supervision as sv
image = ...
key_points = sv.KeyPoints(...)
halo_annotator = sv.VertexEllipseHaloAnnotator(
color=sv.Color.GREEN,
sigma=2.0,
)
annotated_frame = halo_annotator.annotate(
scene=image.copy(),
key_points=key_points,
)
```
<div class="md-typeset">
<h2><a href="#supervision.keypoint.annotators.EdgeAnnotator">EdgeAnnotator</a></h2>
<h2><a href="#supervision.key_points.annotators.VertexAnnotator">VertexAnnotator</a></h2>
</div>
:::supervision.keypoint.annotators.EdgeAnnotator
:::supervision.key_points.annotators.VertexAnnotator
<div class="md-typeset">
<h2><a href="#supervision.keypoint.annotators.VertexLabelAnnotator">VertexLabelAnnotator</a></h2>
<h2><a href="#supervision.key_points.annotators.EdgeAnnotator">EdgeAnnotator</a></h2>
</div>
:::supervision.keypoint.annotators.VertexLabelAnnotator
:::supervision.key_points.annotators.EdgeAnnotator
<div class="md-typeset">
<h2><a href="#supervision.key_points.annotators.VertexLabelAnnotator">VertexLabelAnnotator</a></h2>
</div>
:::supervision.key_points.annotators.VertexLabelAnnotator
<div class="md-typeset">
<h2><a href="#supervision.key_points.annotators.VertexEllipseAreaAnnotator">VertexEllipseAreaAnnotator</a></h2>
</div>
:::supervision.key_points.annotators.VertexEllipseAreaAnnotator
<div class="md-typeset">
<h2><a href="#supervision.key_points.annotators.VertexEllipseOutlineAnnotator">VertexEllipseOutlineAnnotator</a></h2>
</div>
:::supervision.key_points.annotators.VertexEllipseOutlineAnnotator
<div class="md-typeset">
<h2><a href="#supervision.key_points.annotators.VertexEllipseHaloAnnotator">VertexEllipseHaloAnnotator</a></h2>
</div>
:::supervision.key_points.annotators.VertexEllipseHaloAnnotator
+1 -2
View File
@@ -1,8 +1,7 @@
---
comments: true
status: new
---
# Keypoint Detection
:::supervision.keypoint.core.KeyPoints
:::supervision.key_points.core.KeyPoints
+192
View File
@@ -0,0 +1,192 @@
# supervision
> Large-context AI crawler summary for Supervision documentation.
Supervision is an open-source Python library by Roboflow for computer vision workflows. It provides a model-agnostic `Detections` class and composable tools for object detection, instance segmentation, keypoint detection, annotation, tracking, zone counting, dataset conversion, and model evaluation.
Supervision is MIT licensed, published on PyPI, developed on GitHub, and used by researchers and practitioners in production computer vision systems. The library includes converters for supported outputs from Ultralytics, Roboflow Inference, Hugging Face Transformers, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers.
## Primary Links
- Latest stable docs: https://supervision.roboflow.com/latest/
- Development docs: https://supervision.roboflow.com/develop/
- Source code: https://github.com/roboflow/supervision
- PyPI package: https://pypi.org/project/supervision/
- Changelog: https://supervision.roboflow.com/latest/changelog/
- Sitemap: https://supervision.roboflow.com/sitemap.xml
- Standard LLM summary: https://supervision.roboflow.com/llms.txt
- Full LLM summary: https://supervision.roboflow.com/llms.full.txt
## AI Access
The documentation is static HTML and is open for AI crawler consumption. `robots.txt` explicitly allows general crawlers plus GPTBot, ClaudeBot, PerplexityBot, Bytespider, CCBot, GoogleOther, and Applebot.
## Install
```bash
pip install supervision
```
Optional extras:
```bash
pip install "supervision[metrics]"
```
Sample asset utilities are included in the base package under `supervision.assets`.
## Core Concepts
### `sv.Detections`
`sv.Detections` is the central data structure in Supervision. It stores bounding boxes, segmentation masks, confidence scores, class IDs, tracker IDs, and arbitrary per-detection metadata in a `data` dictionary. It supports NumPy-style indexing for filtering by confidence, class, area, and spatial constraints.
Most connectors, annotators, trackers, dataset tools, and metrics either accept or return `Detections`, which makes it possible to change the upstream model while keeping downstream processing code stable.
### Model Connectors
Supervision normalizes outputs from multiple computer vision frameworks into the same `Detections` API. Common constructors include:
- `sv.Detections.from_ultralytics(...)`
- `sv.Detections.from_inference(...)`
- `sv.Detections.from_transformers(...)`
- `sv.Detections.from_vlm(...)`
- `sv.Detections.from_sam(...)`
- `sv.Detections.from_detectron2(...)`
- `sv.Detections.from_mmdetection(...)`
### Annotation
Supervision includes annotators for drawing boxes, masks, labels, traces, zones, vertices, edges, and other overlays on images and video frames. Common annotators include:
- `sv.BoxAnnotator`
- `sv.MaskAnnotator`
- `sv.LabelAnnotator`
- `sv.TraceAnnotator`
- `sv.PolygonZoneAnnotator`
- `sv.LineZoneAnnotator`
### Tracking
The built-in `sv.ByteTrack` wrapper assigns persistent IDs across video frames through `update_with_detections()`. The docs also note the migration path toward `ByteTrackTracker` from the external `trackers` package. Tracked detections can be passed to label, trace, zone, and line-counting annotators.
### Zones and Counting
`sv.PolygonZone` checks whether detections are inside an arbitrary polygon. `sv.LineZone` counts line crossings and requires `detections.tracker_id` so objects can be matched across frames. These tools are typically used with video callbacks and annotators to build traffic, occupancy, queue, and throughput analytics.
### Datasets
`sv.DetectionDataset` loads, merges, splits, and converts object detection datasets. Supported formats include YOLO, COCO JSON, Pascal VOC, and LabelMe. `sv.ClassificationDataset` supports folder-structured classification datasets.
### Metrics
Supervision includes detection metrics including mean average precision, mean average recall, precision, recall, F1 score, and confusion matrices. The current mAP workflow uses `supervision.metrics.mean_average_precision.MeanAveragePrecision` with `update(...)` and `compute()`.
## How-To Guides
- Detect and annotate: https://supervision.roboflow.com/latest/how_to/detect_and_annotate/
- Track objects: https://supervision.roboflow.com/latest/how_to/track_objects/
- Detect small objects: https://supervision.roboflow.com/latest/how_to/detect_small_objects/
- Filter detections: https://supervision.roboflow.com/latest/how_to/filter_detections/
- Save detections: https://supervision.roboflow.com/latest/how_to/save_detections/
- Count in zone: https://supervision.roboflow.com/latest/how_to/count_in_zone/
- Benchmark a model: https://supervision.roboflow.com/latest/how_to/benchmark_a_model/
- Process datasets: https://supervision.roboflow.com/latest/how_to/process_datasets/
## Reference Documentation
- Detections: https://supervision.roboflow.com/latest/detection/core/
- Detection annotators: https://supervision.roboflow.com/latest/detection/annotators/
- Compact masks: https://supervision.roboflow.com/latest/detection/compact_mask/
- Detection converters: https://supervision.roboflow.com/latest/detection/utils/converters/
- IoU and NMS: https://supervision.roboflow.com/latest/detection/utils/iou_and_nms/
- Boxes: https://supervision.roboflow.com/latest/detection/utils/boxes/
- Masks: https://supervision.roboflow.com/latest/detection/utils/masks/
- Polygons: https://supervision.roboflow.com/latest/detection/utils/polygons/
- Vision-language model helpers: https://supervision.roboflow.com/latest/detection/utils/vlms/
- Keypoint core: https://supervision.roboflow.com/latest/keypoint/core/
- Keypoint annotators: https://supervision.roboflow.com/latest/keypoint/annotators/
- Classification core: https://supervision.roboflow.com/latest/classification/core/
- Trackers: https://supervision.roboflow.com/latest/trackers/
- Dataset core: https://supervision.roboflow.com/latest/datasets/core/
- Mean average precision: https://supervision.roboflow.com/latest/metrics/mean_average_precision/
- Mean average recall: https://supervision.roboflow.com/latest/metrics/mean_average_recall/
- Precision: https://supervision.roboflow.com/latest/metrics/precision/
- Recall: https://supervision.roboflow.com/latest/metrics/recall/
- F1 score: https://supervision.roboflow.com/latest/metrics/f1_score/
- Common metric values: https://supervision.roboflow.com/latest/metrics/common_values/
- Line zone: https://supervision.roboflow.com/latest/detection/tools/line_zone/
- Polygon zone: https://supervision.roboflow.com/latest/detection/tools/polygon_zone/
- Inference slicer: https://supervision.roboflow.com/latest/detection/tools/inference_slicer/
- Detection smoother: https://supervision.roboflow.com/latest/detection/tools/smoother/
- Detection export sinks: https://supervision.roboflow.com/latest/detection/tools/save_detections/
- Video utilities: https://supervision.roboflow.com/latest/utils/video/
- Image utilities: https://supervision.roboflow.com/latest/utils/image/
- Iterable utilities: https://supervision.roboflow.com/latest/utils/iterables/
- Notebook utilities: https://supervision.roboflow.com/latest/utils/notebook/
- File utilities: https://supervision.roboflow.com/latest/utils/file/
- Draw utilities: https://supervision.roboflow.com/latest/utils/draw/
- Geometry utilities: https://supervision.roboflow.com/latest/utils/geometry/
- Assets: https://supervision.roboflow.com/latest/assets/
## Cookbooks
- Supervision quickstart: https://supervision.roboflow.com/latest/notebooks/quickstart/
- Count objects crossing the line: https://supervision.roboflow.com/latest/notebooks/count-objects-crossing-the-line/
- Object tracking: https://supervision.roboflow.com/latest/notebooks/object-tracking/
- Small object detection with SAHI: https://supervision.roboflow.com/latest/notebooks/small-object-detection-with-sahi/
- Zero-shot object detection with YOLO-World: https://supervision.roboflow.com/latest/notebooks/zero-shot-object-detection-with-yolo-world/
- Save detections to CSV: https://supervision.roboflow.com/latest/notebooks/serialise-detections-to-csv/
- Save detections to JSON: https://supervision.roboflow.com/latest/notebooks/serialise-detections-to-json/
- Occupancy analytics: https://supervision.roboflow.com/latest/notebooks/occupancy_analytics/
- Annotate video with detections: https://supervision.roboflow.com/latest/notebooks/annotate-video-with-detections/
## Trust and Contact Pages
- About: https://supervision.roboflow.com/latest/about/
- Contact: https://supervision.roboflow.com/latest/contact/
- FAQ: https://supervision.roboflow.com/latest/faq/
- License: https://github.com/roboflow/supervision/blob/develop/LICENSE.md
- Issues: https://github.com/roboflow/supervision/issues
- Community: https://discord.gg/GbfgXGJ8Bk
## Frequently Asked Questions
### What is Supervision?
Supervision is an open-source Python library by Roboflow for computer vision workflows. It provides a unified `Detections` class with converters for supported detection, segmentation, and VLM outputs.
### Is Supervision tied to one model provider?
No. Supervision is model agnostic. It is designed to normalize model outputs into a common API so downstream annotation, filtering, tracking, metrics, and dataset code can be reused.
### What dataset formats are supported?
For object detection datasets, Supervision supports YOLO, COCO JSON, Pascal VOC, and LabelMe import and export. For classification datasets, it supports folder-structure import and export.
### How do I detect small objects?
Use `sv.InferenceSlicer` to split large images into overlapping tiles, run inference on each tile, and merge the resulting detections with non-maximum suppression or non-maximum merge.
### How do I count objects crossing a line?
Run a tracker first to assign `detections.tracker_id`, then use `sv.LineZone.trigger(detections)` to calculate crossing events. Use `sv.LineZoneAnnotator` for visualization.
### How do I benchmark a model?
Load predictions and ground truth as `Detections`, update a `MeanAveragePrecision` metric object, and call `compute()`. Use `sv.ConfusionMatrix` when class-level confusion analysis is needed.
## Citation
```bibtex
@software{supervision,
author = {Roboflow},
title = {Supervision: Computer Vision Toolkit},
url = {https://github.com/roboflow/supervision},
year = {2023}
}
```
## Versioning
`/develop/` is built from the `develop` branch. `/latest/` is built from the `release/latest` branch. Published releases build tag-only documentation paths and do not move `/latest/`.
+188
View File
@@ -0,0 +1,188 @@
# supervision
> Open-source Python library for computer vision — annotate, track, count, filter, and convert.
Supervision is a Python library by Roboflow that provides a model-agnostic `Detections` class and composable tools for object detection and segmentation workflows. It includes converters for supported outputs from Ultralytics, Roboflow Inference, Hugging Face Transformers, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers.
Supervision is MIT licensed, published on PyPI, and developed in public on GitHub.
## AI Access
The documentation is static HTML and open for AI consumption. `robots.txt` explicitly allows general crawlers plus selected AI crawlers.
- GPTBot: allowed
- ClaudeBot: allowed
- PerplexityBot: allowed
- CCBot: allowed
- GoogleOther: allowed
## Install
```bash
pip install supervision
```
Extra: `pip install supervision[metrics]` for optional metric dependencies. Sample asset utilities are included in the base package under `supervision.assets`.
## Links
- GitHub: https://github.com/roboflow/supervision
- PyPI: https://pypi.org/project/supervision
- Docs (latest stable): https://supervision.roboflow.com/latest/
- Docs (develop): https://supervision.roboflow.com/develop/
- Changelog: https://supervision.roboflow.com/latest/changelog/
- Sitemap: https://supervision.roboflow.com/sitemap.xml
## Key APIs
### sv.Detections
Core data structure for bounding boxes, masks, confidence scores, class IDs, tracker IDs, and arbitrary per-detection metadata stored in a `data` dict. The lingua franca of the entire library — every connector, annotator, and tracker accepts or returns `Detections`. Supports NumPy-style boolean indexing for filtering by class, confidence, area, and spatial regions.
### sv.BoxAnnotator, sv.MaskAnnotator, sv.LabelAnnotator
Draw bounding boxes, segmentation masks, and text labels on images. Annotators expose `annotate(scene=..., detections=...)`; pass an input image and a `Detections` object to get the annotated output. `LabelAnnotator` can use explicit `labels` or fall back to `detections["class_name"]`, class IDs, then detection indices. Colors can be assigned by class or manually specified.
### sv.ByteTrack
Object tracker wrapper that assigns persistent IDs across video frames. The built-in `sv.ByteTrack` accepts `Detections` via `update_with_detections()`, but it is deprecated in favor of `ByteTrackTracker` from the external `trackers` package, where the method is named `update()`. Use tracked `Detections` with `sv.TraceAnnotator` to visualize trajectories.
### sv.PolygonZone and sv.LineZone
Zone-based counting. `PolygonZone.trigger(detections)` returns a boolean mask for detections currently inside an arbitrary polygon. `LineZone.trigger(detections)` returns `(crossed_in, crossed_out)` arrays for line crossings and requires `detections.tracker_id` so objects can be matched across frames. Both are commonly paired with zone annotators for visualization.
### sv.DetectionDataset and sv.ClassificationDataset
For detection datasets, load, merge, split, and convert between YOLO, COCO JSON, Pascal VOC, and LabelMe formats. Classification datasets use folder-structure import and export via `ClassificationDataset.from_folder_structure()` and `as_folder_structure()`.
### sv.InferenceSlicer
SAHI-style inference slicing: split high-resolution images into overlapping tiles, run detection on each tile, merge results with non-maximum suppression or non-maximum merge. Configure tile overlap in pixels with `overlap_wh`.
### supervision.metrics.MeanAveragePrecision and sv.ConfusionMatrix
Benchmarking tools. For mAP@0.5:0.95, use `supervision.metrics.MeanAveragePrecision` with `update()` and `compute()` rather than the deprecated top-level `sv.MeanAveragePrecision.from_detections()`. `ConfusionMatrix.from_detections(predictions=predictions, targets=targets, classes=classes)` generates a confusion matrix for detection results.
### sv.CSVSink and sv.JSONSink
Export detection results to structured files. Use `CSVSink` and `JSONSink` as context managers, call `sink.append(detections, custom_data=...)`, and they write one row/object per detection with box coordinates, confidence, class ID, tracker ID, and data fields.
## How-To Guides
- Detect and annotate: https://supervision.roboflow.com/latest/how_to/detect_and_annotate/
- Track objects: https://supervision.roboflow.com/latest/how_to/track_objects/
- Detect small objects: https://supervision.roboflow.com/latest/how_to/detect_small_objects/
- Filter detections: https://supervision.roboflow.com/latest/how_to/filter_detections/
- Save detections: https://supervision.roboflow.com/latest/how_to/save_detections/
- Count in zone: https://supervision.roboflow.com/latest/how_to/count_in_zone/
- Benchmark a model: https://supervision.roboflow.com/latest/how_to/benchmark_a_model/
- Process datasets: https://supervision.roboflow.com/latest/how_to/process_datasets/
## Reference Documentation
- Detections (detection/core): https://supervision.roboflow.com/latest/detection/core/
- Annotators (detection/annotators): https://supervision.roboflow.com/latest/detection/annotators/
- CompactMask (detection/compact_mask): https://supervision.roboflow.com/latest/detection/compact_mask/
- Format Converters (detection/utils/converters): https://supervision.roboflow.com/latest/detection/utils/converters/
- IoU and NMS (detection/utils/iou_and_nms): https://supervision.roboflow.com/latest/detection/utils/iou_and_nms/
- Boxes (detection/utils/boxes): https://supervision.roboflow.com/latest/detection/utils/boxes/
- Masks (detection/utils/masks): https://supervision.roboflow.com/latest/detection/utils/masks/
- Polygons (detection/utils/polygons): https://supervision.roboflow.com/latest/detection/utils/polygons/
- VLMs (detection/utils/vlms): https://supervision.roboflow.com/latest/detection/utils/vlms/
- Keypoint Core (keypoint/core): https://supervision.roboflow.com/latest/keypoint/core/
- Keypoint Annotators (keypoint/annotators): https://supervision.roboflow.com/latest/keypoint/annotators/
- Classification Core (classification/core): https://supervision.roboflow.com/latest/classification/core/
- ByteTrack Tracker (trackers): https://supervision.roboflow.com/latest/trackers/
- Datasets Core (datasets/core): https://supervision.roboflow.com/latest/datasets/core/
- mAP (metrics/mean_average_precision): https://supervision.roboflow.com/latest/metrics/mean_average_precision/
- mAR (metrics/mean_average_recall): https://supervision.roboflow.com/latest/metrics/mean_average_recall/
- Precision (metrics/precision): https://supervision.roboflow.com/latest/metrics/precision/
- Recall (metrics/recall): https://supervision.roboflow.com/latest/metrics/recall/
- F1 Score (metrics/f1_score): https://supervision.roboflow.com/latest/metrics/f1_score/
- Common Values (metrics/common_values): https://supervision.roboflow.com/latest/metrics/common_values/
- Line Zone (detection/tools/line_zone): https://supervision.roboflow.com/latest/detection/tools/line_zone/
- Polygon Zone (detection/tools/polygon_zone): https://supervision.roboflow.com/latest/detection/tools/polygon_zone/
- Inference Slicer (detection/tools/inference_slicer): https://supervision.roboflow.com/latest/detection/tools/inference_slicer/
- Detection Smoother (detection/tools/smoother): https://supervision.roboflow.com/latest/detection/tools/smoother/
- Save Detections Tool (detection/tools/save_detections): https://supervision.roboflow.com/latest/detection/tools/save_detections/
- Video Utils (utils/video): https://supervision.roboflow.com/latest/utils/video/
- Image Utils (utils/image): https://supervision.roboflow.com/latest/utils/image/
- Iterable Utils (utils/iterables): https://supervision.roboflow.com/latest/utils/iterables/
- Notebook Utils (utils/notebook): https://supervision.roboflow.com/latest/utils/notebook/
- File Utils (utils/file): https://supervision.roboflow.com/latest/utils/file/
- Draw Utils (utils/draw): https://supervision.roboflow.com/latest/utils/draw/
- Geometry (utils/geometry): https://supervision.roboflow.com/latest/utils/geometry/
- Assets (assets): https://supervision.roboflow.com/latest/assets/
## Cookbooks
- Object tracking: https://supervision.roboflow.com/latest/cookbooks/#object-tracking
- Count objects crossing line: https://supervision.roboflow.com/latest/cookbooks/#count-objects-crossing-the-line
- Zero-shot object detection with YOLO-World: https://supervision.roboflow.com/latest/cookbooks/#zero-shot-object-detection-with-yolo-world
- SAHI small object detection: https://supervision.roboflow.com/latest/cookbooks/#small-object-detection-with-sahi
## FAQ
### What is supervision?
Supervision is an open-source Python library by Roboflow for computer vision workflows. It provides a unified `Detections` class with converters for supported detection, segmentation, and VLM outputs, plus tools for annotation, tracking, zone counting, dataset management, and model benchmarking.
### How do I install supervision?
Install with `pip install supervision`. For optional metric dependencies use `pip install supervision[metrics]`. Sample asset utilities are included in the base package under `supervision.assets`. The current package metadata requires Python 3.10+.
### What can I do with supervision?
Annotate images and video with bounding boxes, masks, and labels; track objects across frames with persistent IDs; count detections inside polygon zones or line crossings; filter and query detection results; load, split, and convert detection datasets between YOLO, COCO, Pascal VOC, and LabelMe formats; manage classification datasets with folder structures; and benchmark model performance with mAP and confusion matrices.
### Is supervision free to use?
Yes. Supervision is free and open-source under the MIT license. Source code is at https://github.com/roboflow/supervision.
### Which object detection models work with supervision?
Supervision is model-agnostic and works with supported outputs from Ultralytics YOLO, Roboflow Inference, Hugging Face Transformers, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers such as Florence-2, PaliGemma, Qwen VL, Gemini, DeepSeek VL 2, and Moondream. Keypoint outputs have separate converters, including MediaPipe.
### How do I benchmark a model with supervision?
Use `supervision.metrics.mean_average_precision.MeanAveragePrecision` for mAP — accumulate predictions and ground truth with `update(...)` then call `compute()`. For confusion matrices, use `sv.ConfusionMatrix.from_detections(predictions=predictions, targets=targets, classes=classes)`. See the Benchmark a Model how-to guide for a complete walkthrough.
### How do I track objects across video frames?
Use a tracker to assign persistent IDs. The built-in `sv.ByteTrack` wrapper accepts `Detections` with `update_with_detections()`, but it is deprecated in favor of `ByteTrackTracker` from the external `trackers` package. Combine tracked detections with `sv.TraceAnnotator` to visualize trajectories.
### What dataset formats does supervision support?
For detection datasets, supervision supports YOLO, COCO JSON, Pascal VOC, and LabelMe. Use `DetectionDataset.from_yolo()`, `from_coco()`, `from_pascal_voc()`, or `from_labelme()` to load, and `as_yolo()`, `as_coco()`, `as_pascal_voc()`, or `as_labelme()` to save. For classification datasets, use `ClassificationDataset.from_folder_structure()` and `as_folder_structure()`.
### How do I count objects in a zone?
Use `sv.PolygonZone` for arbitrary polygon zones. Use `sv.LineZone` for line-crossing counts after assigning tracker IDs, because `LineZone` needs `detections.tracker_id` to match objects across frames.
### How do I detect small objects with supervision?
Use `sv.InferenceSlicer` to split high-resolution images into overlapping tiles, run detection on each tile, and merge results with non-maximum suppression. Configure tile overlap in pixels with `overlap_wh`. See the Detect Small Objects how-to guide.
## Benchmarking
Supervision includes `supervision.metrics.MeanAveragePrecision` and `sv.ConfusionMatrix` for benchmarking object detection models. A curated [Model Leaderboard](https://leaderboard.roboflow.com/) compares YOLOv8, YOLOv11, and other models on standard datasets. The leaderboard repository is open source at https://github.com/roboflow/model-leaderboard.
## License
MIT — https://github.com/roboflow/supervision/blob/develop/LICENSE.md
## Citation
```bibtex
@software{supervision,
author = {Roboflow},
title = {Supervision: Computer Vision Toolkit},
url = {https://github.com/roboflow/supervision},
year = {2023}
}
```
## Versioning
Stable release docs: https://supervision.roboflow.com/latest/
Development branch: https://supervision.roboflow.com/develop/
+179
View File
@@ -0,0 +1,179 @@
# supervision
> Open-source Python library for computer vision — annotate, track, count, filter, and convert.
Supervision is a Python library by Roboflow that provides a model-agnostic `Detections` class and composable tools for object detection and segmentation workflows. It includes converters for supported outputs from Ultralytics, Roboflow Inference, Hugging Face Transformers, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers.
Supervision is MIT licensed, published on PyPI, and developed in public on GitHub.
## AI Access
The documentation is static HTML and open for AI consumption. `robots.txt` explicitly allows general crawlers plus selected AI crawlers.
- GPTBot: allowed
- ClaudeBot: allowed
- PerplexityBot: allowed
- CCBot: allowed
- GoogleOther: allowed
## Install
```
pip install supervision
```
Extra: `pip install supervision[metrics]` for optional metric dependencies. Sample asset utilities are included in the base package under `supervision.assets`.
## Links
- GitHub: https://github.com/roboflow/supervision
- PyPI: https://pypi.org/project/supervision
- Docs (latest stable): https://supervision.roboflow.com/latest/
- Changelog: https://supervision.roboflow.com/latest/changelog/
- Sitemap: https://supervision.roboflow.com/sitemap.xml
## Key APIs
### sv.Detections
Core data structure for bounding boxes, masks, confidence scores, class IDs, tracker IDs, and arbitrary per-detection metadata stored in a `data` dict. The lingua franca of the entire library — every connector, annotator, and tracker accepts or returns `Detections`. Supports NumPy-style boolean indexing for filtering by class, confidence, area, and spatial regions.
### sv.BoxAnnotator, sv.MaskAnnotator, sv.LabelAnnotator
Draw bounding boxes, segmentation masks, and text labels on images. Annotators expose `annotate(scene=..., detections=...)`; pass an input image and a `Detections` object to get the annotated output. `LabelAnnotator` can use explicit `labels` or fall back to `detections["class_name"]`, class IDs, then detection indices. Colors can be assigned by class or manually specified.
### sv.ByteTrack
Object tracker wrapper that assigns persistent IDs across video frames. The built-in `sv.ByteTrack` accepts `Detections` via `update_with_detections()`, but it is deprecated in favor of `ByteTrackTracker` from the external `trackers` package, where the method is named `update()`. Use tracked `Detections` with `sv.TraceAnnotator` to visualize trajectories.
### sv.PolygonZone and sv.LineZone
Zone-based counting. `PolygonZone.trigger(detections)` returns a boolean mask for detections currently inside an arbitrary polygon. `LineZone.trigger(detections)` returns `(crossed_in, crossed_out)` arrays for line crossings and requires `detections.tracker_id` so objects can be matched across frames. Both are commonly paired with zone annotators for visualization.
### sv.DetectionDataset and sv.ClassificationDataset
For detection datasets, load, merge, split, and convert between YOLO, COCO JSON, Pascal VOC, CreateML, and LabelMe formats. Classification datasets use folder-structure import and export via `ClassificationDataset.from_folder_structure()` and `as_folder_structure()`.
### sv.InferenceSlicer
SAHI-style inference slicing: split high-resolution images into overlapping tiles, run detection on each tile, merge results with non-maximum suppression or non-maximum merge. Configure tile overlap in pixels with `overlap_wh`.
### supervision.metrics.MeanAveragePrecision and sv.ConfusionMatrix
Benchmarking tools. For mAP@0.5:0.95, use `supervision.metrics.MeanAveragePrecision` with `update()` and `compute()` rather than the deprecated top-level `sv.MeanAveragePrecision.from_detections()`. `ConfusionMatrix.from_detections(predictions=predictions, targets=targets, classes=classes)` generates a confusion matrix for detection results.
### sv.CSVSink and sv.JSONSink
Export detection results to structured files. Use `CSVSink` and `JSONSink` as context managers, call `sink.append(detections, custom_data=...)`, and they write one row/object per detection with box coordinates, confidence, class ID, tracker ID, and data fields.
## How-To Guides
- Detect and annotate: https://supervision.roboflow.com/latest/how_to/detect_and_annotate/
- Track objects: https://supervision.roboflow.com/latest/how_to/track_objects/
- Detect small objects: https://supervision.roboflow.com/latest/how_to/detect_small_objects/
- Filter detections: https://supervision.roboflow.com/latest/how_to/filter_detections/
- Save detections: https://supervision.roboflow.com/latest/how_to/save_detections/
- Count in zone: https://supervision.roboflow.com/latest/how_to/count_in_zone/
- Benchmark a model: https://supervision.roboflow.com/latest/how_to/benchmark_a_model/
- Process datasets: https://supervision.roboflow.com/latest/how_to/process_datasets/
## Reference Documentation
- Detections (detection/core): https://supervision.roboflow.com/latest/detection/core/
- Annotators (detection/annotators): https://supervision.roboflow.com/latest/detection/annotators/
- CompactMask (detection/compact_mask): https://supervision.roboflow.com/latest/detection/compact_mask/
- Format Converters (detection/utils/converters): https://supervision.roboflow.com/latest/detection/utils/converters/
- IoU and NMS (detection/utils/iou_and_nms): https://supervision.roboflow.com/latest/detection/utils/iou_and_nms/
- Boxes (detection/utils/boxes): https://supervision.roboflow.com/latest/detection/utils/boxes/
- Masks (detection/utils/masks): https://supervision.roboflow.com/latest/detection/utils/masks/
- Polygons (detection/utils/polygons): https://supervision.roboflow.com/latest/detection/utils/polygons/
- VLMs (detection/utils/vlms): https://supervision.roboflow.com/latest/detection/utils/vlms/
- Keypoint Core (keypoint/core): https://supervision.roboflow.com/latest/keypoint/core/
- Keypoint Annotators (keypoint/annotators): https://supervision.roboflow.com/latest/keypoint/annotators/
- Classification Core (classification/core): https://supervision.roboflow.com/latest/classification/core/
- ByteTrack Tracker (trackers): https://supervision.roboflow.com/latest/trackers/
- Datasets Core (datasets/core): https://supervision.roboflow.com/latest/datasets/core/
- mAP (metrics/mean_average_precision): https://supervision.roboflow.com/latest/metrics/mean_average_precision/
- mAR (metrics/mean_average_recall): https://supervision.roboflow.com/latest/metrics/mean_average_recall/
- Precision (metrics/precision): https://supervision.roboflow.com/latest/metrics/precision/
- Recall (metrics/recall): https://supervision.roboflow.com/latest/metrics/recall/
- F1 Score (metrics/f1_score): https://supervision.roboflow.com/latest/metrics/f1_score/
- Common Values (metrics/common_values): https://supervision.roboflow.com/latest/metrics/common_values/
- Line Zone (detection/tools/line_zone): https://supervision.roboflow.com/latest/detection/tools/line_zone/
- Polygon Zone (detection/tools/polygon_zone): https://supervision.roboflow.com/latest/detection/tools/polygon_zone/
- Inference Slicer (detection/tools/inference_slicer): https://supervision.roboflow.com/latest/detection/tools/inference_slicer/
- Detection Smoother (detection/tools/smoother): https://supervision.roboflow.com/latest/detection/tools/smoother/
- Save Detections Tool (detection/tools/save_detections): https://supervision.roboflow.com/latest/detection/tools/save_detections/
- Video Utils (utils/video): https://supervision.roboflow.com/latest/utils/video/
- Image Utils (utils/image): https://supervision.roboflow.com/latest/utils/image/
- Iterable Utils (utils/iterables): https://supervision.roboflow.com/latest/utils/iterables/
- Notebook Utils (utils/notebook): https://supervision.roboflow.com/latest/utils/notebook/
- File Utils (utils/file): https://supervision.roboflow.com/latest/utils/file/
- Draw Utils (utils/draw): https://supervision.roboflow.com/latest/utils/draw/
- Geometry (utils/geometry): https://supervision.roboflow.com/latest/utils/geometry/
- Assets (assets): https://supervision.roboflow.com/latest/assets/
## Cookbooks
- Object tracking: https://supervision.roboflow.com/latest/cookbooks/#object-tracking
- Count objects crossing line: https://supervision.roboflow.com/latest/cookbooks/#count-objects-crossing-the-line
- Zero-shot object detection with YOLO-World: https://supervision.roboflow.com/latest/cookbooks/#zero-shot-object-detection-with-yolo-world
- SAHI small object detection: https://supervision.roboflow.com/latest/cookbooks/#small-object-detection-with-sahi
## FAQ
### What is supervision?
Supervision is an open-source Python library by Roboflow for computer vision workflows. It provides a unified `Detections` class with converters for supported detection, segmentation, and VLM outputs, plus tools for annotation, tracking, zone counting, dataset management, and model benchmarking.
### How do I install supervision?
Install with `pip install supervision`. For optional metric dependencies use `pip install supervision[metrics]`. Sample asset utilities are included in the base package under `supervision.assets`. The current package metadata requires Python 3.10+.
### What can I do with supervision?
Annotate images and video with bounding boxes, masks, and labels; track objects across frames with persistent IDs; count detections inside polygon zones or line crossings; filter and query detection results; load, split, and convert detection datasets between YOLO, COCO, Pascal VOC, and LabelMe formats; manage classification datasets with folder structures; and benchmark model performance with mAP and confusion matrices.
### Is supervision free to use?
Yes. Supervision is free and open-source under the MIT license. Source code is at https://github.com/roboflow/supervision.
### Which object detection models work with supervision?
Supervision is model-agnostic and works with supported outputs from Ultralytics YOLO, Roboflow Inference, Hugging Face Transformers, SAM, Detectron2, MMDetection, YOLO-NAS, PaddleDet, NCNN, Azure AI Vision, and VLM parsers such as Florence-2, PaliGemma, Qwen VL, Gemini, DeepSeek VL 2, and Moondream. Keypoint outputs have separate converters, including MediaPipe.
### How do I benchmark a model with supervision?
Use `supervision.metrics.mean_average_precision.MeanAveragePrecision` for mAP — accumulate predictions and ground truth with `update(...)` then call `compute()`. For confusion matrices, use `sv.ConfusionMatrix.from_detections(predictions=predictions, targets=targets, classes=classes)`. See the Benchmark a Model how-to guide for a complete walkthrough.
### How do I track objects across video frames?
Use a tracker to assign persistent IDs. The built-in `sv.ByteTrack` wrapper accepts `Detections` with `update_with_detections()`, but it is deprecated in favor of `ByteTrackTracker` from the external `trackers` package. Combine tracked detections with `sv.TraceAnnotator` to visualize trajectories.
### What dataset formats does supervision support?
For detection datasets, supervision supports YOLO, COCO JSON, Pascal VOC, CreateML, and LabelMe. Use `DetectionDataset.from_yolo()`, `from_coco()`, `from_pascal_voc()`, `from_createml()`, or `from_labelme()` to load, and `as_yolo()`, `as_coco()`, `as_pascal_voc()`, `as_createml()`, or `as_labelme()` to save. For classification datasets, use `ClassificationDataset.from_folder_structure()` and `as_folder_structure()`.
### How do I count objects in a zone?
Use `sv.PolygonZone` for arbitrary polygon zones. Use `sv.LineZone` for line-crossing counts after assigning tracker IDs, because `LineZone` needs `detections.tracker_id` to match objects across frames.
### How do I detect small objects with supervision?
Use `sv.InferenceSlicer` to split high-resolution images into overlapping tiles, run detection on each tile, and merge results with non-maximum suppression. Configure tile overlap in pixels with `overlap_wh`. See the Detect Small Objects how-to guide.
## Benchmarking
Supervision includes `supervision.metrics.MeanAveragePrecision` and `sv.ConfusionMatrix` for benchmarking object detection models. A curated [Model Leaderboard](https://leaderboard.roboflow.com/) compares YOLOv8, YOLOv11, and other models on standard datasets. The leaderboard repository is open source at https://github.com/roboflow/model-leaderboard.
## License
MIT — https://github.com/roboflow/supervision/blob/develop/LICENSE.md
## Citation
```bibtex
@software{supervision,
author = {Roboflow},
title = {Supervision: Computer Vision Toolkit},
url = {https://github.com/roboflow/supervision},
year = {2023}
}
```
## Versioning
Stable release docs: https://supervision.roboflow.com/latest/
Development branch: https://supervision.roboflow.com/develop/
+6 -1
View File
@@ -1,12 +1,17 @@
---
comments: true
status: new
---
# Common Values
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>
+6 -1
View File
@@ -1,10 +1,15 @@
---
comments: true
status: new
---
# 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>
+13 -1
View File
@@ -1,10 +1,16 @@
---
comments: true
status: new
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>
@@ -16,3 +22,9 @@ status: new
</div>
:::supervision.metrics.mean_average_precision.MeanAveragePrecisionResult
<div class="md-typeset">
<h2><a href="#supervision.dataset.formats.coco.get_coco_class_index_mapping">get_coco_class_index_mapping</a></h2>
</div>
:::supervision.dataset.formats.coco.get_coco_class_index_mapping
+6 -1
View File
@@ -1,10 +1,15 @@
---
comments: true
status: new
---
# 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>
+6 -1
View File
@@ -1,10 +1,15 @@
---
comments: true
status: new
---
# 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>
+6 -1
View File
@@ -1,10 +1,15 @@
---
comments: true
status: new
---
# 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>
+2 -3
View File
@@ -93,7 +93,7 @@
},
"outputs": [],
"source": [
"!pip install -q inference-gpu \"supervision[assets]\""
"!pip install -q inference-gpu \"supervision\""
]
},
{
@@ -156,7 +156,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -207,7 +207,6 @@
],
"source": [
"import supervision as sv\n",
"from supervision.assets import download_assets, VideoAssets\n",
"from inference.models.utils import get_roboflow_model\n",
"\n",
"\n",
+176
View File
@@ -0,0 +1,176 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "jxcxFKy2hRnA"
},
"source": [
"# Blurring Faces\n",
"\n",
"---\n",
"\n",
"[![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/roboflow/supervision/blob/develop/docs/notebooks/blurring_faces.ipynb)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "FAxD-vAgkadG"
},
"source": [
"Click the `Open in Colab` button to run the cookbook on Google Colab.\n",
"\n",
"## Introduction\n",
"\n",
"In this cookbook we'll use a frame from a video of someone in a supermarket. We'll download this video via the `supervision` assets module. We'll then run inference on this frame using the hosted Roboflow API to fetch detections of faces utilizing an open source face detection model on Roboflow Universe. Finally, we'll use supervision to blur the detected faces."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "o_F-fJGskuz9"
},
"source": [
"## Install packages\n",
"\n",
"Let's quickly install the `supervision` package with the assets module, as well as the roboflow `inference_sdk` with pip. We'll also install `tqdm` to show a progress bar, but this is optional in production code."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "c2X8k1opItiO"
},
"outputs": [],
"source": "!pip3 install -q supervision inference tqdm \"Pillow<12\""
},
{
"cell_type": "markdown",
"metadata": {
"id": "9xy1jXMrm5iU"
},
"source": [
"## Download Video and Extract Frame\n",
"\n",
"In order to blur a face in a frame, we'll need a frame with a face in it. Let's download a video, and grab a frame in the middle of the video. I played around a little, and found that the 800th frame is great frame for us to test, since the customer is facing the camera. In this code, we're also using tqdm to display a progress bar of our script."
]
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"source": [
"import supervision as sv\n",
"\n",
"video = sv.download_assets(sv.VideoAssets.GROCERY_STORE)\n",
"\n",
"# Seek directly to frame 800 using the start parameter (O(1) seek)\n",
"frame = next(sv.get_video_frames_generator(video, start=800))\n",
"\n",
"sv.plot_image(frame)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "tgejF7Zlosyd"
},
"source": [
"## Detecting Faces\n",
"\n",
"Now that we've got our image we'll need a good face detecting model. For this task, there are already an impressive amount of open source models available on [Roboflow Universe](https://universe.roboflow.com/). After a little digging, this [face detection model](https://universe.roboflow.com/mohamed-traore-2ekkp/face-detection-mik1i) has over 1300 images. Some models, including this one, require a Roboflow API key. You can [create a free account here](https://app.roboflow.com/login). From there, you can find the key under Settings > Workspaces > Roboflow API. Let's give it a try."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "3MDjVxEzKWGn",
"outputId": "8fee3446-cc81-4e3c-c4a0-b531d286f1a4"
},
"outputs": [],
"source": [
"import os\n",
"from inference_sdk import InferenceHTTPClient\n",
"\n",
"try:\n",
" from google.colab import userdata\n",
" ROBOFLOW_API_KEY = userdata.get(\"ROBOFLOW_API_KEY\") or \"\"\n",
"except ImportError:\n",
" ROBOFLOW_API_KEY = os.environ.get(\"ROBOFLOW_API_KEY\", \"\")\n",
"\n",
"assert ROBOFLOW_API_KEY, \"Set ROBOFLOW_API_KEY in Colab secrets or as env var\"\n",
"\n",
"client = InferenceHTTPClient(\n",
" api_url=\"https://detect.roboflow.com\",\n",
" api_key=ROBOFLOW_API_KEY\n",
")\n",
"\n",
"results = client.infer(frame, model_id=\"face-detection-mik1i/18\")\n",
"\n",
"print(f\"Detected {len(results['predictions'])} face(s)\")\n",
"print(results)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dkPMOHa_univ"
},
"source": [
"## Blurring the Face\n",
"\n",
"Now that we're detecting faces, bluring them is easy with supervision. Let's pass our results into a `Detections` object and annotate the frame with a `BlurAnnotator`."
]
},
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"source": [
"blur = sv.BlurAnnotator(kernel_size=100)\n",
"\n",
"detections = sv.Detections.from_inference(results)\n",
"\n",
"annotated_frame = blur.annotate(scene=frame.copy(), detections=detections)\n",
"\n",
"sv.plot_image(annotated_frame)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "YVNe8oe4vY4N"
},
"source": [
"## Conclusion\n",
"\n",
"With supervision, inference, and Roboflow Universe we were able to blur faces in minutes with an open source model. There are many other impressive use cases out there, so feel free to share in your own cookbooks. Happy building!"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"cell_execution_strategy": "setup",
"gpuType": "T4",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -17,7 +17,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "shellscript"
@@ -25,7 +25,7 @@
},
"outputs": [],
"source": [
"!pip install -q \"supervision[assets]\""
"pip install -q \"supervision\""
]
},
{
@@ -101,7 +101,7 @@
},
"outputs": [],
"source": [
"!pip install -q torch diffusers accelerate inference-gpu[yolo-world] dill git+https://github.com/openai/CLIP.git supervision==0.19.0rc5"
"!pip install -q torch diffusers accelerate inference-gpu[yolo-world] dill git+https://github.com/openai/CLIP.git supervision"
]
},
{
+1 -1
View File
@@ -92,7 +92,7 @@
},
"outputs": [],
"source": [
"!pip install -q inference-gpu \"supervision[assets]\""
"!pip install -q inference-gpu \"supervision\""
]
},
{
+1 -1
View File
@@ -72,7 +72,7 @@
},
"outputs": [],
"source": [
"!pip install roboflow supervision==0.19.0 -q"
"!pip install roboflow supervision -q"
]
},
{
File diff suppressed because one or more lines are too long
+5 -5
View File
@@ -300,7 +300,7 @@
},
"outputs": [],
"source": [
"!pip install -q \"ultralytics<=8.3.40\""
"!pip install -q ultralytics"
]
},
{
@@ -495,7 +495,7 @@
"source": [
"from ultralytics import YOLO\n",
"\n",
"model = YOLO(\"yolov8x.pt\")\n",
"model = YOLO(\"yolo11x.pt\")\n",
"result = model(image, verbose=False)[0]\n",
"detections = sv.Detections.from_ultralytics(result)"
]
@@ -594,7 +594,7 @@
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": null,
"metadata": {
"id": "yM6dmicTRGl6"
},
@@ -602,7 +602,7 @@
"source": [
"from ultralytics import YOLO\n",
"\n",
"model = YOLO(\"yolov8x-seg.pt\")\n",
"model = YOLO(\"yolo11x-seg.pt\")\n",
"result = model(image, verbose=False)[0]\n",
"detections = sv.Detections.from_ultralytics(result)"
]
@@ -926,7 +926,7 @@
},
"outputs": [],
"source": [
"!pip install -q supervision[assets]"
"!pip install -q supervision"
]
},
{
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -32,7 +32,7 @@
},
"outputs": [],
"source": [
"!pip install -q inference requests tqdm supervision==0.21.0"
"!pip install -q inference requests tqdm supervision"
]
},
{
@@ -695,12 +695,12 @@
"source": [
"###\u00a0Annotate Image with Detections\n",
"\n",
"Finally, we can annotate the image with the predictions. Since we are working with an object detection model, we will use the [`sv.BoundingBoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoundingBoxAnnotator) and [`sv.LabelAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator) classes."
"Finally, we can annotate the image with the predictions. Since we are working with an object detection model, we will use the [`sv.BoxAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.BoxAnnotator) and [`sv.LabelAnnotator`](https://supervision.roboflow.com/latest/detection/annotators/#supervision.annotators.core.LabelAnnotator) classes."
]
},
{
"cell_type": "code",
"execution_count": 49,
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
@@ -722,7 +722,7 @@
}
],
"source": [
"bounding_box_annotator = sv.BoundingBoxAnnotator()\n",
"bounding_box_annotator = sv.BoxAnnotator()\n",
"label_annotator = sv.LabelAnnotator()\n",
"\n",
"annotated_frame = frame.copy()\n",

Some files were not shown because too many files have changed in this diff Show More