Compare commits

...
75 Commits
Author SHA1 Message Date
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
soumik12345 00df1cbb04 fix: UnboundLocalError 2025-04-25 02:29:08 +05:30
Piotr Skalski 49d5505efa Merge pull request #1828 from roboflow/fix/make-trace-annotator-to-work-with-unassigned-trackers
make the `TraceAnnotator` to work with unassigned trackers
2025-04-24 00:30:13 +02:00
pre-commit-ci[bot] 1cf95972f3 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-23 22:26:28 +00:00
SkalskiP 047489b96e bump version from 0.26.0rc5 to 0.26.0rc6 2025-04-24 00:22:27 +02:00
SkalskiP da498b091b fix circular import 2025-04-24 00:13:32 +02:00
SkalskiP 2ea0f443f8 test new approach 2025-04-24 00:08:06 +02:00
SkalskiP 639318832b ready for tests 2025-04-23 23:55:34 +02:00
Piotr Skalski b9731ef9f3 Merge pull request #1826 from roboflow/feature/make-supervision-annotators-compatible-with-trackers-pending-tracker-id
make `supervision` annotators compatible with `trackers` pending tracker ID
2025-04-23 15:52:05 +02:00
pre-commit-ci[bot] b9475f14f3 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-23 13:45:43 +00:00
SkalskiP 587c61883b bump version from 0.26.0rc4 to 0.26.0rc5 2025-04-23 15:42:24 +02:00
SkalskiP f866fe046f ready for tests 2025-04-23 15:41:42 +02:00
Piotr Skalski 185322fcd1 Merge pull request #1824 from roboflow/docs/class/formatter
feat(mkdocs):  📝 add options for root heading and pygments language class in markdown extensions
2025-04-23 09:00:26 +02:00
Piotr Skalski 1dd6ff6ce5 Merge pull request #1825 from roboflow/feat/support-int-labels
feat(LabelAnnotator): add support for non-str labels
2025-04-23 08:58:57 +02:00
Piotr Skalski 9e79cb06d0 Merge pull request #1823 from roboflow/utils/xyxy_to_xyah
feat: ✨ add xyxy_to_xcycarh conversion function
2025-04-22 21:40:24 +02:00
Soumik Rakshit 94131ff56b add: support for non-str labels 2025-04-22 18:13:34 +00:00
pre-commit-ci[bot] ec0add34ee fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-22 18:08:21 +00:00
SkalskiP 6387513805 update test cases 2025-04-22 20:07:54 +02:00
Onuralp SEZER 9ed9cd2592 feat(mkdocs): 📝 add options for root heading and pygments language class in markdown extensions 2025-04-22 17:53:54 +03:00
Onuralp SEZER 5d6ad66618 feat: ✨ add xyxy_to_xcycarh conversion function 2025-04-22 17:00:52 +03:00
Onuralp SEZER 6f7ca11ea9 Merge pull request #1822 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-04-22 16:31:35 +03:00
pre-commit-ci[bot] 51a108b5ab chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.5 → v0.11.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.5...v0.11.6)
2025-04-21 17:20:07 +00:00
Onuralp SEZER cfe18afcc9 Merge pull request #1821 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-5.4.2
⬆️ Bump astral-sh/setup-uv from 5.4.1 to 5.4.2
2025-04-21 05:13:12 +03:00
dependabot[bot] 39acd616a6 ⬆️ Bump astral-sh/setup-uv from 5.4.1 to 5.4.2
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5.4.1 to 5.4.2.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/0c5e2b8115b80b4c7c5ddf6ffdd634974642d182...d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-21 00:41:11 +00:00
Onuralp SEZER 1d0747fbfe Merge pull request #1816 from roboflow/feat/process-video-progress-bar
feat(supervision): Add frame limitations + progressbar for `sv.process_video`
2025-04-15 12:08:25 +03:00
Onuralp SEZER c3618652cd Merge pull request #1819 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-04-15 12:05:31 +03:00
pre-commit-ci[bot] 1496888d92 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.4 → v0.11.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.4...v0.11.5)
2025-04-14 17:22:40 +00:00
Onuralp SEZER 058dc169f1 Merge pull request #1817 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-04-07 20:42:53 +03:00
pre-commit-ci[bot] 0d534346bf chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.2 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4)
2025-04-07 17:34:35 +00:00
soumik12345 e73cc438e1 fix: variable video_frames_generator 2025-04-07 21:45:47 +05:30
pre-commit-ci[bot] 6a378a32f7 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-04-07 16:13:08 +00:00
Soumik RakshitandOnuralp SEZER 1534501a1d update: supervision/utils/video.py
Co-authored-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-04-07 21:42:45 +05:30
Soumik RakshitandOnuralp SEZER 941700b9f8 update: supervision/utils/video.py
Co-authored-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-04-07 21:42:35 +05:30
Soumik RakshitandOnuralp SEZER 4743701286 update: supervision/utils/video.py
Co-authored-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-04-07 21:42:18 +05:30
soumik12345 b58862d9f3 chore: address feedback 2025-04-07 19:44:50 +05:30
soumik12345 4b245dd5f1 add: max_frames and profressbar options to supervision 2025-04-07 19:10:51 +05:30
Onuralp SEZER 32bf9be5d1 Merge pull request #1815 from roboflow/dependabot/github_actions/develop/actions/create-github-app-token-2.0.2
⬆️ Bump actions/create-github-app-token from 1.12.0 to 2.0.2
2025-04-07 03:53:55 +03:00
dependabot[bot] f56eb2503e ⬆️ Bump actions/create-github-app-token from 1.12.0 to 2.0.2
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1.12.0 to 2.0.2.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/d72941d797fd3113feb6b93fd0dec494b13a2547...3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 00:11:28 +00:00
Onuralp SEZER b1c0c1b00a Merge pull request #1812 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-5.4.1
⬆️ Bump astral-sh/setup-uv from 5.4.0 to 5.4.1
2025-03-31 04:57:44 +03:00
Onuralp SEZER 4c88106d14 Merge pull request #1813 from roboflow/dependabot/github_actions/develop/actions/create-github-app-token-1.12.0
⬆️ Bump actions/create-github-app-token from 1.11.7 to 1.12.0
2025-03-31 04:57:23 +03:00
dependabot[bot] 3d0b4cba65 ⬆️ Bump actions/create-github-app-token from 1.11.7 to 1.12.0
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1.11.7 to 1.12.0.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/af35edadc00be37caa72ed9f3e6d5f7801bfdf09...d72941d797fd3113feb6b93fd0dec494b13a2547)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 00:31:09 +00:00
dependabot[bot] f7fd508400 ⬆️ Bump astral-sh/setup-uv from 5.4.0 to 5.4.1
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5.4.0 to 5.4.1.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/22695119d769bdb6f7032ad67b9bca0ef8c4a174...0c5e2b8115b80b4c7c5ddf6ffdd634974642d182)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 00:31:06 +00:00
Onuralp SEZER 32b10b5335 Merge pull request #1809 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-03-24 20:32:10 +03:00
pre-commit-ci[bot] 5f981bf4d9 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.0 → v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.0...v0.11.2)
2025-03-24 17:26:28 +00:00
Onuralp SEZER 5634632944 Merge pull request #1808 from roboflow/dependabot/pip/develop/mkdocstrings-gte-0.25.2-and-lt-0.30.0
⬆️ Update mkdocstrings requirement from <0.29.0,>=0.25.2 to >=0.25.2,<0.30.0
2025-03-24 13:25:25 +03:00
Onuralp SEZER fc62e6a0bc Merge pull request #1807 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-5.4.0
⬆️ Bump astral-sh/setup-uv from 5.3.1 to 5.4.0
2025-03-24 13:25:04 +03:00
Onuralp SEZER 837772392c Merge pull request #1806 from roboflow/dependabot/github_actions/develop/actions/create-github-app-token-1.11.7
⬆️ Bump actions/create-github-app-token from 1.11.6 to 1.11.7
2025-03-24 13:24:40 +03:00
dependabot[bot] 386fb2e15f ⬆️ 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.29.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-24 00:52:55 +00:00
dependabot[bot] ad59b39257 ⬆️ Bump astral-sh/setup-uv from 5.3.1 to 5.4.0
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5.3.1 to 5.4.0.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/f94ec6bedd8674c4426838e6b50417d36b6ab231...22695119d769bdb6f7032ad67b9bca0ef8c4a174)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-24 00:38:37 +00:00
dependabot[bot] 57966ce9ec ⬆️ Bump actions/create-github-app-token from 1.11.6 to 1.11.7
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1.11.6 to 1.11.7.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/21cfef2b496dd8ef5b904c159339626a10ad380e...af35edadc00be37caa72ed9f3e6d5f7801bfdf09)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-24 00:38:33 +00:00
Piotr Skalski ca6609571a Merge pull request #1796 from roboflow/dependabot/pip/develop/mkdocstrings-gte-0.25.2-and-lt-0.29.0
⬆️ Update mkdocstrings requirement from <0.27.0,>=0.25.2 to >=0.25.2,<0.29.0
2025-03-21 16:57:49 +01:00
Onuralp SEZER 6690bd678a Merge pull request #1775 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2025-03-21 18:43:50 +03:00
Piotr Skalski 1c489eff98 Merge pull request #1804 from blakeburch/add-segment-tracking
Add segment tracking
2025-03-21 16:19:25 +01:00
pre-commit-ci[bot] f1e067041e fix(pre_commit): 🎨 auto format pre-commit hooks 2025-03-20 19:58:09 +00:00
Blake Burch 73d69172db Add segment tracking 2025-03-20 14:46:07 -05:00
pre-commit-ci[bot] 8881b5c588 fix(pre_commit): 🎨 auto format pre-commit hooks 2025-03-17 17:29:14 +00:00
pre-commit-ci[bot] 83d9868350 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/PyCQA/bandit: 1.8.0 → 1.8.3](https://github.com/PyCQA/bandit/compare/1.8.0...1.8.3)
- [github.com/astral-sh/ruff-pre-commit: v0.8.6 → v0.11.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.6...v0.11.0)
- [github.com/codespell-project/codespell: v2.3.0 → v2.4.1](https://github.com/codespell-project/codespell/compare/v2.3.0...v2.4.1)
2025-03-17 17:28:37 +00:00
Onuralp SEZER c9a3069297 Merge pull request #1802 from roboflow/dependabot/github_actions/develop/actions/create-github-app-token-1.11.6
⬆️ Bump actions/create-github-app-token from 1.11.5 to 1.11.6
2025-03-10 09:59:51 +03:00
dependabot[bot] 8864762ff1 ⬆️ Bump actions/create-github-app-token from 1.11.5 to 1.11.6
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1.11.5 to 1.11.6.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/0d564482f06ca65fa9e77e2510873638c82206f2...21cfef2b496dd8ef5b904c159339626a10ad380e)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 00:27:31 +00:00
Onuralp SEZER 39a12db1d4 Merge pull request #1798 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-5.3.1
⬆️ Bump astral-sh/setup-uv from 5.3.0 to 5.3.1
2025-03-03 05:21:51 +03:00
dependabot[bot] 55fafd0a40 ⬆️ Bump astral-sh/setup-uv from 5.3.0 to 5.3.1
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5.3.0 to 5.3.1.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/1edb52594c857e2b5b13128931090f0640537287...f94ec6bedd8674c4426838e6b50417d36b6ab231)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 00:16:42 +00:00
Piotr Skalski cc28a51c18 Merge pull request #1797 from roboflow/docs/keypoints_yolo
docs: 📝 Update documentation for ultralytics KeyPoints to include YOLO11-pose and adjust example to latest model
2025-02-25 11:00:17 +01:00
Onuralp SEZER 9938c1d2ad docs: 📝 Update documentation for ultralytics KeyPoints to include YOLO11-pose and adjust example to latest model
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-02-24 11:38:21 +03:00
Onuralp SEZER 51dba14fee Merge branch 'develop' into dependabot/pip/develop/mkdocstrings-gte-0.25.2-and-lt-0.29.0 2025-02-24 06:26:54 +03:00
Onuralp SEZER 78d70085cb pacakge: 📦 Update mkdocs configuration and bump mkdocstrings version to <0.29.0
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2025-02-24 06:26:01 +03:00
Onuralp SEZER e2cb82a7da Merge pull request #1794 from roboflow/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.12.4
⬆️ Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4
2025-02-24 04:57:08 +03:00
Onuralp SEZER 78e1c2ceba Merge pull request #1793 from roboflow/dependabot/github_actions/develop/actions/create-github-app-token-1.11.5
⬆️ Bump actions/create-github-app-token from 1.11.1 to 1.11.5
2025-02-24 04:48:52 +03:00
Onuralp SEZER 898f2ba72c Merge pull request #1795 from roboflow/dependabot/github_actions/develop/astral-sh/setup-uv-5.3.0
⬆️ Bump astral-sh/setup-uv from 5.2.2 to 5.3.0
2025-02-24 04:02:16 +03:00
dependabot[bot] 11f2a005e2 ⬆️ 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.28.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 00:45:58 +00:00
dependabot[bot] 3ba7c1b8e2 ⬆️ Bump astral-sh/setup-uv from 5.2.2 to 5.3.0
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5.2.2 to 5.3.0.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/4db96194c378173c656ce18a155ffc14a9fc4355...1edb52594c857e2b5b13128931090f0640537287)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 00:41:32 +00:00
dependabot[bot] 3562bbf2ed ⬆️ Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.3 to 1.12.4.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.3...76f52bc884231f62b9a034ebfe128415bbaabdfc)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 00:41:28 +00:00
dependabot[bot] 408a9ad0ff ⬆️ Bump actions/create-github-app-token from 1.11.1 to 1.11.5
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1.11.1 to 1.11.5.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/c1a285145b9d317df6ced56c09f525b5c2b6f755...0d564482f06ca65fa9e77e2510873638c82206f2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 00:41:26 +00:00
Piotr Skalski acf1ef6d90 Merge pull request #1786 from Armaggheddon/refactor/heatmap-perf
perf: improved hsv color mapping in HeatMapAnnotator by 20x
2025-02-19 15:02:13 +01:00
Armaggheddon fefd005c2c perf: improved hsv color mapping in HeatMapAnnotator by 20x 2025-02-10 20:59:45 +01:00
31 changed files with 296 additions and 142 deletions
+2 -2
View File
@@ -34,13 +34,13 @@ jobs:
fetch-depth: 0
- name: 🐍 Install uv and set Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
- name: 🔑 Create GitHub App token (mkdocs)
id: mkdocs_token
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
with:
app-id: ${{ secrets.MKDOCS_APP_ID }}
private-key: ${{ secrets.MKDOCS_PEM }}
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
+2 -2
View File
@@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
@@ -38,6 +38,6 @@ jobs:
uv run twine check --strict dist/*
- name: 🚀 Publish to PyPi
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
attestations: true
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
fetch-depth: 0
- name: 🐍 Install uv and set Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
python-version: ${{ matrix.python-version }}
+3 -3
View File
@@ -25,14 +25,14 @@ repos:
- id: mixed-line-ending
- repo: https://github.com/PyCQA/bandit
rev: '1.8.0'
rev: '1.8.3'
hooks:
- id: bandit
args: ["-c", "pyproject.toml"]
additional_dependencies: ["bandit[toml]"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6
rev: v0.11.6
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
@@ -48,7 +48,7 @@ repos:
# args: ["--number"]
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
rev: v2.4.1
hooks:
- id: codespell
additional_dependencies:
+6
View File
@@ -95,6 +95,12 @@ status: new
:::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>
+4
View File
@@ -0,0 +1,4 @@
!function(){var i="analytics",analytics=window[i]=window[i]||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","screen","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware","register"];analytics.factory=function(e){return function(){if(window[i].initialized)return window[i][e].apply(window[i],arguments);var n=Array.prototype.slice.call(arguments);if(["track","screen","alias","group","page","identify"].indexOf(e)>-1){var c=document.querySelector("link[rel='canonical']");n.push({__t:"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer})}n.unshift(e);analytics.push(n);return analytics}};for(var n=0;n<analytics.methods.length;n++){var key=analytics.methods[n];analytics[key]=analytics.factory(key)}analytics.load=function(key,n){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.setAttribute("data-global-segment-analytics-key",i);t.src="https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js";var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(t,r);analytics._loadOptions=n};analytics._writeKey="rMvrPeZBJYyOPJSGCNhMlnTJb8VhFiWU";;analytics.SNIPPET_VERSION="5.2.0";
analytics.load("eohFog7VZiAhGJGEr5Sh7BM1mFKmUvDC");
document$.subscribe(analytics.page);
}}();
+7 -1
View File
@@ -149,9 +149,12 @@ plugins:
group_by_category: true
docstring_style: google
show_symbol_type_heading: true
show_root_heading: True
show_symbol_type_toc: true
show_category_heading: true
domains: [std, py]
inventories:
- url: https://docs.python-requests.org/en/master/objects.inv
domains: [std, py]
- git-committers:
repository: roboflow/supervision
branch: develop
@@ -176,10 +179,13 @@ markdown_extensions:
check_paths: true
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
extra_javascript:
- "javascripts/init_kapa_widget.js"
- "javascripts/cookbooks-card.js"
- "javascripts/segment.js"
- "https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.8/purify.min.js"
# Messages shown during document build
+2 -2
View File
@@ -2,7 +2,7 @@
name = "supervision"
description = "A set of easy-to-use utils that will come in handy in any Computer Vision project"
license = { text = "MIT" }
version = "0.26.0rc4"
version = "0.26.0rc7"
readme = "README.md"
requires-python = ">=3.8"
authors = [
@@ -69,7 +69,7 @@ dev = [
]
docs = [
"mkdocs-material[imaging]>=9.5.5",
"mkdocstrings>=0.25.2,<0.27.0",
"mkdocstrings>=0.25.2,<0.30.0",
"mkdocstrings-python>=1.10.9",
"mike>=2.0.0",
"mkdocs-jupyter>=0.24.3",
+2
View File
@@ -76,6 +76,7 @@ from supervision.detection.utils import (
xcycwh_to_xyxy,
xywh_to_xyxy,
xyxy_to_polygons,
xyxy_to_xcycarh,
xyxy_to_xywh,
)
from supervision.detection.vlm import LMM, VLM
@@ -225,5 +226,6 @@ __all__ = [
"xcycwh_to_xyxy",
"xywh_to_xyxy",
"xyxy_to_polygons",
"xyxy_to_xyah",
"xyxy_to_xywh",
]
+5 -5
View File
@@ -9,6 +9,7 @@ from PIL import Image, ImageDraw, ImageFont
from supervision.annotators.base import BaseAnnotator, ImageType
from supervision.annotators.utils import (
PENDING_TRACK_ID,
ColorLookup,
Trace,
resolve_color,
@@ -1130,7 +1131,7 @@ class LabelAnnotator(BaseAnnotator):
detections: Detections, custom_labels: Optional[List[str]]
) -> List[str]:
if custom_labels is not None:
return custom_labels
return [str(label) for label in custom_labels]
labels = []
for idx in range(len(detections)):
@@ -1739,6 +1740,7 @@ class TraceAnnotator(BaseAnnotator):
"The `tracker_id` field is missing in the provided detections."
" See more: https://supervision.roboflow.com/latest/how_to/track_objects"
)
detections = detections[detections.tracker_id != PENDING_TRACK_ID]
self.trace.put(detections)
for detection_idx in range(len(detections)):
@@ -1857,11 +1859,9 @@ class HeatMapAnnotator(BaseAnnotator):
temp = temp.astype(np.uint8)
if self.kernel_size is not None:
temp = cv2.blur(temp, (self.kernel_size, self.kernel_size))
hsv = np.zeros(scene.shape)
hsv = np.full(scene.shape, 255, dtype=np.uint8)
hsv[..., 0] = temp
hsv[..., 1] = 255
hsv[..., 2] = 255
temp = cv2.cvtColor(hsv.astype(np.uint8), cv2.COLOR_HSV2BGR)
temp = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
mask = cv2.cvtColor(self.heat_mask.astype(np.uint8), cv2.COLOR_GRAY2BGR) > 0
scene[mask] = cv2.addWeighted(temp, self.opacity, scene, 1 - self.opacity, 0)[
mask
+5
View File
@@ -7,6 +7,9 @@ from supervision.detection.core import Detections
from supervision.draw.color import Color, ColorPalette
from supervision.geometry.core import Position
PENDING_TRACK_COLOR = Color.GREY
PENDING_TRACK_ID = -1
class ColorLookup(Enum):
"""
@@ -136,6 +139,8 @@ def resolve_color(
detection_idx=detection_idx,
color_lookup=color_lookup,
)
if color_lookup == ColorLookup.TRACK and idx == PENDING_TRACK_ID:
return PENDING_TRACK_COLOR
return get_color_by_index(color=color, idx=idx)
+7 -7
View File
@@ -715,7 +715,7 @@ class Detections:
"""
if "error" in azure_result:
raise ValueError(
f'Azure API returned an error {azure_result["error"]["message"]}'
f"Azure API returned an error {azure_result['error']['message']}"
)
xyxy, confidences, class_ids = [], [], []
@@ -1346,9 +1346,9 @@ class Detections:
if len(self) == 0:
return self
assert (
self.confidence is not None
), "Detections confidence must be given for NMS to be executed."
assert self.confidence is not None, (
"Detections confidence must be given for NMS to be executed."
)
if class_agnostic:
predictions = np.hstack((self.xyxy, self.confidence.reshape(-1, 1)))
@@ -1402,9 +1402,9 @@ class Detections:
if len(self) == 0:
return self
assert (
self.confidence is not None
), "Detections confidence must be given for NMM to be executed."
assert self.confidence is not None, (
"Detections confidence must be given for NMM to be executed."
)
if class_agnostic:
predictions = np.hstack((self.xyxy, self.confidence.reshape(-1, 1)))
+1 -2
View File
@@ -226,8 +226,7 @@ def box_non_max_merge(
for merge_group in merge_groups:
if len(merge_group) == 0:
raise ValueError(
f"Empty group detected when non-max-merging "
f"detections: {merge_groups}"
f"Empty group detected when non-max-merging detections: {merge_groups}"
)
return merge_groups
+50
View File
@@ -397,6 +397,56 @@ def xcycwh_to_xyxy(xcycwh: np.ndarray) -> np.ndarray:
return xyxy
def xyxy_to_xcycarh(xyxy: np.ndarray) -> np.ndarray:
"""
Converts bounding box coordinates from `(x_min, y_min, x_max, y_max)`
into measurement space to format `(center x, center y, aspect ratio, height)`,
where the aspect ratio is `width / height`.
Args:
xyxy (np.ndarray): Bounding box in format `(x1, y1, x2, y2)`.
Expected shape is `(N, 4)`.
Returns:
np.ndarray: Bounding box in format
`(center x, center y, aspect ratio, height)`. Shape `(N, 4)`.
Examples:
```python
import numpy as np
import supervision as sv
xyxy = np.array([
[10, 20, 40, 60],
[15, 25, 50, 70]
])
sv.xyxy_to_xcycarh(xyxy=xyxy)
# array([
# [25. , 40. , 0.75, 40. ],
# [32.5 , 47.5 , 0.77777778, 45. ]
# ])
```
"""
if xyxy.size == 0:
return np.empty((0, 4), dtype=float)
x1, y1, x2, y2 = xyxy.T
width = x2 - x1
height = y2 - y1
center_x = x1 + width / 2
center_y = y1 + height / 2
aspect_ratio = np.divide(
width,
height,
out=np.zeros_like(width, dtype=float),
where=height != 0,
)
result = np.column_stack((center_x, center_y, aspect_ratio, height))
return result.astype(float)
def mask_to_xyxy(masks: np.ndarray) -> np.ndarray:
"""
Converts a 3D `np.array` of 2D bool masks into a 2D `np.array` of bounding boxes.
+6 -6
View File
@@ -294,18 +294,18 @@ def from_florence_2(
return xyxy, labels, None, None
if task in ["<REGION_TO_CATEGORY>", "<REGION_TO_DESCRIPTION>"]:
assert isinstance(
result, str
), f"Expected string as <REGION_TO_CATEGORY> result, got {type(result)}"
assert isinstance(result, str), (
f"Expected string as <REGION_TO_CATEGORY> result, got {type(result)}"
)
if result == "No object detected.":
return np.empty((0, 4), dtype=np.float32), np.array([]), None, None
pattern = re.compile(r"<loc_(\d+)><loc_(\d+)><loc_(\d+)><loc_(\d+)>")
match = pattern.search(result)
assert (
match is not None
), f"Expected string to end in location tags, but got {result}"
assert match is not None, (
f"Expected string to end in location tags, but got {result}"
)
w, h = resolution_wh
xyxy = np.array([match.groups()], dtype=np.float32)
+14 -9
View File
@@ -83,15 +83,16 @@ class Color:
# Color(r=255, g=255, b=255)
```
| Constant | Hex Code | RGB |
|------------|------------|------------------|
| `WHITE` | `#FFFFFF` | `(255, 255, 255)`|
| `BLACK` | `#000000` | `(0, 0, 0)` |
| `RED` | `#FF0000` | `(255, 0, 0)` |
| `GREEN` | `#00FF00` | `(0, 255, 0)` |
| `BLUE` | `#0000FF` | `(0, 0, 255)` |
| `YELLOW` | `#FFFF00` | `(255, 255, 0)` |
| `ROBOFLOW` | `#A351FB` | `(163, 81, 251)` |
| Constant | Hex Code | RGB |
|------------|------------|-------------------|
| `WHITE` | `#FFFFFF` | `(255, 255, 255)` |
| `BLACK` | `#000000` | `(0, 0, 0)` |
| `GREY` | `#808080` | `(128, 128, 128)` |
| `RED` | `#FF0000` | `(255, 0, 0)` |
| `GREEN` | `#00FF00` | `(0, 255, 0)` |
| `BLUE` | `#0000FF` | `(0, 0, 255)` |
| `YELLOW` | `#FFFF00` | `(255, 255, 0)` |
| `ROBOFLOW` | `#A351FB` | `(163, 81, 251)` |
"""
r: int
@@ -235,6 +236,10 @@ class Color:
def BLACK(cls) -> Color:
return Color.from_hex("#000000")
@classproperty
def GREY(cls) -> Color:
return Color.from_hex("#808080")
@classproperty
def RED(cls) -> Color:
return Color.from_hex("#FF0000")
+3 -3
View File
@@ -23,8 +23,8 @@ class KeyPoints:
=== "Ultralytics"
Use [`sv.KeyPoints.from_ultralytics`](/latest/keypoint/core/#supervision.keypoint.core.KeyPoints.from_ultralytics)
method, which accepts [YOLOv8](https://github.com/ultralytics/ultralytics)
pose result.
method, which accepts [YOLOv8-pose](https://docs.ultralytics.com/models/yolov8/), [YOLO11-pose](https://docs.ultralytics.com/models/yolo11/)
[pose](https://docs.ultralytics.com/tasks/pose/) result.
```python
import cv2
@@ -32,7 +32,7 @@ class KeyPoints:
from ultralytics import YOLO
image = cv2.imread(<SOURCE_IMAGE_PATH>)
model = YOLO('yolov8s-pose.pt')
model = YOLO('yolo11s-pose.pt')
result = model(image)[0]
key_points = sv.KeyPoints.from_ultralytics(result)
+1 -2
View File
@@ -670,8 +670,7 @@ class MeanAverageRecallResult:
ax.set_ylim(0, 1)
ax.set_ylabel("Value", fontweight="bold")
title = (
f"Mean Average Recall, by Object Size"
f"\n(target: {self.metric_target.value})"
f"Mean Average Recall, by Object Size\n(target: {self.metric_target.value})"
)
ax.set_title(title, fontweight="bold")
+25 -1
View File
@@ -7,6 +7,7 @@ from typing import Callable, Generator, Optional, Tuple
import cv2
import numpy as np
from tqdm.auto import tqdm
@dataclass
@@ -195,6 +196,9 @@ def process_video(
source_path: str,
target_path: str,
callback: Callable[[np.ndarray, int], np.ndarray],
max_frames: Optional[int] = None,
show_progress: bool = False,
progress_message: str = "Processing video",
) -> None:
"""
Process a video file by applying a callback function on each frame
@@ -207,6 +211,9 @@ def process_video(
a numpy ndarray representation of a video frame and an
int index of the frame and returns a processed numpy ndarray
representation of the frame.
max_frames (Optional[int]): The maximum number of frames to process.
show_progress (bool): Whether to show a progress bar.
progress_message (str): The message to display in the progress bar.
Examples:
```python
@@ -223,12 +230,29 @@ def process_video(
```
"""
source_video_info = VideoInfo.from_video_path(video_path=source_path)
video_frames_generator = get_video_frames_generator(
source_path=source_path, end=max_frames
)
with VideoSink(target_path=target_path, video_info=source_video_info) as sink:
total_frames = (
min(source_video_info.total_frames, max_frames)
if max_frames is not None
else source_video_info.total_frames
)
for index, frame in enumerate(
get_video_frames_generator(source_path=source_path)
tqdm(
video_frames_generator,
total=total_frames,
disable=not show_progress,
desc=progress_message,
)
):
result_frame = callback(frame, index)
sink.write_frame(frame=result_frame)
else:
for index, frame in enumerate(video_frames_generator):
result_frame = callback(frame, index)
sink.write_frame(frame=result_frame)
class FPSMonitor:
+1 -1
View File
@@ -54,7 +54,7 @@ def validate_confidence(confidence: Any, n: int) -> None:
def validate_keypoint_confidence(confidence: Any, n: int, m: int) -> None:
expected_shape = f"({n,m})"
expected_shape = f"({n, m})"
actual_shape = str(getattr(confidence, "shape", None))
if confidence is not None:
+3 -3
View File
@@ -408,8 +408,8 @@ def assert_csv_equal(file_name, expected_rows):
with open(file_name, mode="r", newline="") as file:
reader = csv.reader(file)
for i, row in enumerate(reader):
assert (
[str(item) for item in expected_rows[i]] == row
), f"Row in CSV didn't match expected output: {row} != {expected_rows[i]}"
assert [str(item) for item in expected_rows[i]] == row, (
f"Row in CSV didn't match expected output: {row} != {expected_rows[i]}"
)
os.remove(file_name)
+3 -3
View File
@@ -242,8 +242,8 @@ def test_json_sink(
def assert_json_equal(file_name, expected_rows):
with open(file_name, "r") as file:
data = json.load(file)
assert (
data == expected_rows
), f"Data in JSON file didn't match expected output: {data} != {expected_rows}"
assert data == expected_rows, (
f"Data in JSON file didn't match expected output: {data} != {expected_rows}"
)
os.remove(file_name)
+18 -18
View File
@@ -250,12 +250,12 @@ def test_line_zone_one_detection_default_anchors(
crossed_in_list.append(crossed_in[0])
crossed_out_list.append(crossed_out[0])
assert (
crossed_in_list == expected_crossed_in
), f"expected {expected_crossed_in}, got {crossed_in_list}"
assert (
crossed_out_list == expected_crossed_out
), f"expected {expected_crossed_out}, got {crossed_out_list}"
assert crossed_in_list == expected_crossed_in, (
f"expected {expected_crossed_in}, got {crossed_in_list}"
)
assert crossed_out_list == expected_crossed_out, (
f"expected {expected_crossed_out}, got {crossed_out_list}"
)
@pytest.mark.parametrize(
@@ -415,12 +415,12 @@ def test_line_zone_one_detection(
crossed_in_list.append(crossed_in[0])
crossed_out_list.append(crossed_out[0])
assert (
crossed_in_list == expected_crossed_in
), f"expected {expected_crossed_in}, got {crossed_in_list}"
assert (
crossed_out_list == expected_crossed_out
), f"expected {expected_crossed_out}, got {crossed_out_list}"
assert crossed_in_list == expected_crossed_in, (
f"expected {expected_crossed_in}, got {crossed_in_list}"
)
assert crossed_out_list == expected_crossed_out, (
f"expected {expected_crossed_out}, got {crossed_out_list}"
)
@pytest.mark.parametrize(
@@ -600,12 +600,12 @@ def test_line_zone_one_detection_long_horizon(
crossed_in_list.append(crossed_in[0])
crossed_out_list.append(crossed_out[0])
assert (
crossed_in_list == expected_crossed_in
), f"expected {expected_crossed_in}, got {crossed_in_list}"
assert (
crossed_out_list == expected_crossed_out
), f"expected {expected_crossed_out}, got {crossed_out_list}"
assert crossed_in_list == expected_crossed_in, (
f"expected {expected_crossed_in}, got {crossed_in_list}"
)
assert crossed_out_list == expected_crossed_out, (
f"expected {expected_crossed_out}, got {crossed_out_list}"
)
@pytest.mark.parametrize(
+70 -18
View File
@@ -21,6 +21,7 @@ from supervision.detection.utils import (
scale_boxes,
xcycwh_to_xyxy,
xywh_to_xyxy,
xyxy_to_xcycarh,
xyxy_to_xywh,
)
@@ -389,13 +390,13 @@ def test_process_roboflow_result(
)
for key in result[5]:
if isinstance(result[5][key], np.ndarray):
assert np.array_equal(
result[5][key], expected_result[5][key]
), f"Mismatch in arrays for key {key}"
assert np.array_equal(result[5][key], expected_result[5][key]), (
f"Mismatch in arrays for key {key}"
)
else:
assert (
result[5][key] == expected_result[5][key]
), f"Mismatch in non-array data for key {key}"
assert result[5][key] == expected_result[5][key], (
f"Mismatch in non-array data for key {key}"
)
@pytest.mark.parametrize(
@@ -1042,13 +1043,13 @@ def test_merge_data(
for key in result:
if isinstance(result[key], np.ndarray):
assert np.array_equal(
result[key], expected_result[key]
), f"Mismatch in arrays for key {key}"
assert np.array_equal(result[key], expected_result[key]), (
f"Mismatch in arrays for key {key}"
)
else:
assert (
result[key] == expected_result[key]
), f"Mismatch in non-array data for key {key}"
assert result[key] == expected_result[key], (
f"Mismatch in non-array data for key {key}"
)
@pytest.mark.parametrize(
@@ -1215,13 +1216,13 @@ def test_get_data_item(
result = get_data_item(data=data, index=index)
for key in result:
if isinstance(result[key], np.ndarray):
assert np.array_equal(
result[key], expected_result[key]
), f"Mismatch in arrays for key {key}"
assert np.array_equal(result[key], expected_result[key]), (
f"Mismatch in arrays for key {key}"
)
else:
assert (
result[key] == expected_result[key]
), f"Mismatch in non-array data for key {key}"
assert result[key] == expected_result[key], (
f"Mismatch in non-array data for key {key}"
)
@pytest.mark.parametrize(
@@ -1405,6 +1406,57 @@ def test_xyxy_to_xywh(xyxy: np.ndarray, expected_result: np.ndarray) -> None:
np.testing.assert_array_equal(result, expected_result)
@pytest.mark.parametrize(
"xyxy, expected_result",
[
# Empty and zero cases
(np.array([]).reshape(0, 4), np.array([]).reshape(0, 4)), # empty array
(
np.array([[0, 0, 0, 0]]),
np.array([[0, 0, 0.0, 0]]),
), # zero size bounding box
(
np.array([[10, 10, 10, 10]]),
np.array([[10, 10, 0.0, 0]]),
), # point (x1=x2, y1=y2)
# Zero width/height cases
(np.array([[50, 50, 80, 50]]), np.array([[65, 50, 0.0, 0]])), # zero height
(np.array([[50, 50, 50, 80]]), np.array([[50, 65, 0.0, 30]])), # zero width
# Standard cases
(np.array([[10, 20, 40, 60]]), np.array([[25, 40, 0.75, 40]])), # standard case
(
np.array([[-30, -40, -10, -20]]),
np.array([[-20, -30, 1.0, 20]]),
), # all negative values
(
np.array([[0.1, 0.2, 0.4, 0.6]]),
np.array([[0.25, 0.4, 0.75, 0.4]]),
), # values between 0-1
# Different aspect ratios
(
np.array([[10, 20, 50, 100]]),
np.array([[30, 60, 0.5, 80]]),
), # tall rectangle (height > width)
(
np.array([[20, 10, 100, 50]]),
np.array([[60, 30, 2.0, 40]]),
), # wide rectangle (width > height)
(
np.array([[50, 50, 150, 150]]),
np.array([[100, 100, 1.0, 100]]),
), # height == width
# Multiple boxes in one array
(
np.array([[0, 0, 0, 0], [10, 20, 40, 60]]),
np.array([[0, 0, 0.0, 0], [25, 40, 0.75, 40]]),
), # one zero-sized box and one normal box
],
)
def test_xyxy_to_xcycarh(xyxy: np.ndarray, expected_result: np.ndarray) -> None:
result = xyxy_to_xcycarh(xyxy)
np.testing.assert_allclose(result, expected_result)
@pytest.mark.parametrize(
"xcycwh, expected_result",
[
@@ -180,6 +180,6 @@ def test_generate_offset(
)
# Verify that the generated offsets match the expected offsets
assert np.array_equal(
offsets, expected_offsets
), f"Expected {expected_offsets}, got {offsets}"
assert np.array_equal(offsets, expected_offsets), (
f"Expected {expected_offsets}, got {offsets}"
)
+36 -36
View File
@@ -22,15 +22,15 @@ def test_ensure_cv2_image_for_processing_when_pillow_image_submitted(
param_a: int,
param_b: str,
) -> np.ndarray:
assert np.allclose(
image, empty_cv2_image
), "Expected conversion to OpenCV image to happen"
assert (
param_a == param_a_value
), f"Parameter a expected to be {param_a_value} in target function"
assert (
param_b == param_b_value
), f"Parameter b expected to be {param_b_value} in target function"
assert np.allclose(image, empty_cv2_image), (
"Expected conversion to OpenCV image to happen"
)
assert param_a == param_a_value, (
f"Parameter a expected to be {param_a_value} in target function"
)
assert param_b == param_b_value, (
f"Parameter b expected to be {param_b_value} in target function"
)
return image
# when
@@ -61,15 +61,15 @@ def test_ensure_cv2_image_for_processing_when_cv2_image_submitted(
param_a: int,
param_b: str,
) -> np.ndarray:
assert np.allclose(
image, empty_cv2_image
), "Expected conversion to OpenCV image to happen"
assert (
param_a == param_a_value
), f"Parameter a expected to be {param_a_value} in target function"
assert (
param_b == param_b_value
), f"Parameter b expected to be {param_b_value} in target function"
assert np.allclose(image, empty_cv2_image), (
"Expected conversion to OpenCV image to happen"
)
assert param_a == param_a_value, (
f"Parameter a expected to be {param_a_value} in target function"
)
assert param_b == param_b_value, (
f"Parameter b expected to be {param_b_value} in target function"
)
return image
# when
@@ -91,9 +91,9 @@ def test_cv2_to_pillow(
# then
difference = ImageChops.difference(result, empty_pillow_image)
assert (
difference.getbbox() is None
), "Conversion to PIL.Image expected not to change the content of image"
assert difference.getbbox() is None, (
"Conversion to PIL.Image expected not to change the content of image"
)
def test_pillow_to_cv2(
@@ -103,9 +103,9 @@ def test_pillow_to_cv2(
result = pillow_to_cv2(image=empty_pillow_image)
# then
assert np.allclose(
result, empty_cv2_image
), "Conversion to OpenCV image expected not to change the content of image"
assert np.allclose(result, empty_cv2_image), (
"Conversion to OpenCV image expected not to change the content of image"
)
def test_images_to_cv2_when_empty_input_provided() -> None:
@@ -128,9 +128,9 @@ def test_images_to_cv2_when_only_cv2_images_provided(
# then
assert len(result) == 5, "Expected the same number of output element as input ones"
for result_element in result:
assert (
result_element is empty_cv2_image
), "Expected CV images not to be touched by conversion"
assert result_element is empty_cv2_image, (
"Expected CV images not to be touched by conversion"
)
def test_images_to_cv2_when_only_pillow_images_provided(
@@ -146,9 +146,9 @@ def test_images_to_cv2_when_only_pillow_images_provided(
# then
assert len(result) == 5, "Expected the same number of output element as input ones"
for result_element in result:
assert np.allclose(
result_element, empty_cv2_image
), "Output images expected to be equal to empty OpenCV image"
assert np.allclose(result_element, empty_cv2_image), (
"Output images expected to be equal to empty OpenCV image"
)
def test_images_to_cv2_when_mixed_input_provided(
@@ -163,9 +163,9 @@ def test_images_to_cv2_when_mixed_input_provided(
# then
assert len(result) == 2, "Expected the same number of output element as input ones"
assert np.allclose(
result[0], empty_cv2_image
), "PIL image should be converted to OpenCV one, equal to example empty image"
assert (
result[1] is empty_cv2_image
), "Expected CV images not to be touched by conversion"
assert np.allclose(result[0], empty_cv2_image), (
"PIL image should be converted to OpenCV one, equal to example empty image"
)
assert result[1] is empty_cv2_image, (
"Expected CV images not to be touched by conversion"
)
+9 -9
View File
@@ -21,9 +21,9 @@ def test_resize_image_for_opencv_image() -> None:
)
# then
assert np.allclose(
result, expected_result
), "Expected output shape to be (w, h): (1024, 768)"
assert np.allclose(result, expected_result), (
"Expected output shape to be (w, h): (1024, 768)"
)
def test_resize_image_for_pillow_image() -> None:
@@ -41,9 +41,9 @@ def test_resize_image_for_pillow_image() -> None:
# then
assert result.size == (1024, 768), "Expected output shape to be (w, h): (1024, 768)"
difference = ImageChops.difference(result, expected_result)
assert (
difference.getbbox() is None
), "Expected no difference in resized image content as the image is all zeros"
assert difference.getbbox() is None, (
"Expected no difference in resized image content as the image is all zeros"
)
def test_letterbox_image_for_opencv_image() -> None:
@@ -95,9 +95,9 @@ def test_letterbox_image_for_pillow_image() -> None:
1024,
), "Expected output shape to be (w, h): (1024, 1024)"
difference = ImageChops.difference(result, expected_result)
assert (
difference.getbbox() is None
), "Expected padding to be added top and bottom with padding added top and bottom"
assert difference.getbbox() is None, (
"Expected padding to be added top and bottom with padding added top and bottom"
)
def test_create_tiles_with_one_image(
Generated
+4 -2
View File
@@ -1,4 +1,5 @@
version = 1
revision = 1
requires-python = ">=3.8"
resolution-markers = [
"python_full_version >= '3.12' and sys_platform == 'darwin'",
@@ -4828,7 +4829,7 @@ wheels = [
[[package]]
name = "supervision"
version = "0.26.0rc3"
version = "0.26.0rc4"
source = { editable = "." }
dependencies = [
{ name = "defusedxml" },
@@ -4894,7 +4895,7 @@ requires-dist = [
{ name = "mkdocs-git-revision-date-localized-plugin", marker = "extra == 'docs'", specifier = ">=1.2.4" },
{ name = "mkdocs-jupyter", marker = "extra == 'docs'", specifier = ">=0.24.3" },
{ name = "mkdocs-material", extras = ["imaging"], marker = "extra == 'docs'", specifier = ">=9.5.5" },
{ name = "mkdocstrings", marker = "extra == 'docs'", specifier = ">=0.25.2,<0.27.0" },
{ name = "mkdocstrings", marker = "extra == 'docs'", specifier = ">=0.25.2,<0.29.0" },
{ name = "mkdocstrings-python", marker = "extra == 'docs'", specifier = ">=1.10.9" },
{ name = "nbconvert", marker = "extra == 'dev'", specifier = ">=7.14.2" },
{ name = "notebook", marker = "extra == 'dev'", specifier = ">=6.5.3,<8.0.0" },
@@ -4911,6 +4912,7 @@ requires-dist = [
{ name = "twine", marker = "extra == 'build'", specifier = ">=5.1.1,<7.0.0" },
{ name = "wheel", marker = "extra == 'build'", specifier = ">=0.40,<0.46" },
]
provides-extras = ["metrics", "dev", "docs", "build"]
[[package]]
name = "terminado"