Compare commits

...
139 Commits
Author SHA1 Message Date
SkalskiP 73013d6e47 bump version from 0.19.0rc4 to 0.19.0rc5 2024-02-29 21:17:33 +01:00
Onuralp SEZER 41c78cceed Merge pull request #963 from roboflow/feat/plot_image/pillow
feat(ImageType): 🚀 sv.plot_images_grid and sv.plot_image can accept ImageType
2024-02-29 23:11:22 +03:00
Onuralp SEZER ce3356287e feat(ImageType): 🚀 sv.plot_images_grid and sv.plot_image can accept ImageType
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-29 23:09:01 +03:00
SkalskiP 0aff293841 bump version from 0.19.0rc3 to 0.19.0rc4 2024-02-29 20:04:24 +01:00
Onuralp SEZER b13e3e0b8e Merge pull request #962 from roboflow/feat/supervision/warnings
fix: 🐞 Custom warning type 'SupervisionWarning' added
2024-02-29 19:27:04 +03:00
Onuralp SEZER 18085340e2 feat: ⚠️ cleaner warning format added
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-29 19:25:10 +03:00
Onuralp SEZER 7d65a9445a fix: 🐞 Custom warning type 'SupervisionWarning' added
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-29 18:52:38 +03:00
Onuralp SEZER a68e5b4a6d Merge pull request #886 from Kadermiyanyedi/update-byte-track-class-argument-names
[ByteTrack] - change the names and documenting input arguments #787
2024-02-29 14:45:50 +03:00
Onuralp SEZER d3383fc02f feat: ✨ deprecated_parameters ⚠️ added and warning filter for show ALL warnings
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-29 14:42:38 +03:00
Piotr Skalski 6613f57a81 Merge pull request #961 from roboflow/ci/pypi/regex
ci: 👷 remove duplicated publish tag regex
2024-02-29 11:38:53 +01:00
Onuralp SEZER 00c84d4530 Merge branch 'develop' into update-byte-track-class-argument-names 2024-02-29 13:35:49 +03:00
Onuralp SEZER cefd9e100c ci: 👷 remove duplicated publish tag regex
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-29 12:54:22 +03:00
Piotr Skalski 07763bb2d0 Merge pull request #935 from NickHerrig/cookbooks/add-visuals
Cookbooks/add visuals
2024-02-29 10:36:16 +01:00
Piotr Skalski af03010a07 Merge pull request #960 from roboflow/small_deprecated_parameter_cleanup
update `deprecated_parameter` docs
2024-02-29 10:19:36 +01:00
pre-commit-ci[bot] f12182b016 fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-29 09:15:25 +00:00
SkalskiP 25deda23f2 ready for test in colab 2024-02-29 10:11:29 +01:00
Onuralp SEZER a790040c84 Merge pull request #910 from LeviVasconcelos/polygonzone-add-multiple-anchors-support
Polygonzone add multiple anchors support
2024-02-28 22:23:54 +03:00
Onuralp SEZER d0ad5fe1d4 fix: 🐞 depricated supervision version add and abbreviation dropped
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-28 22:10:06 +03:00
Piotr Skalski 0c0685987a Merge pull request #942 from roboflow/feat/PolygonZoneAnnotator/LabelVisibility
feat(PolygonZoneAnnotator): ✨ make display of zone label optional default is true
2024-02-28 14:54:55 +01:00
Onuralp SEZER 5f85339851 feat(PolygonZoneAnnotator): ✨ make display of zone label optional default is true
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-28 16:36:31 +03:00
Piotr Skalski 13cb923541 Merge pull request #944 from LinasKo/fix/smoother-removes-detections-tracker-id
Fix smoother removing tracking_id from detections
2024-02-28 14:25:31 +01:00
Linas Kondrackis 5e1d9bbd40 smoother: check len of detections - not tracked_detections 2024-02-28 15:22:15 +02:00
James cb8f4af8bf Merge pull request #955 from roboflow/fix/doc/percentage
fix(docs): 🐞 PercentageBarAnnotator example doc code usage fixed
2024-02-28 12:31:28 +00:00
Onuralp SEZER 165ed424bf fix(docs): 🐞 PercentageBarAnnotator example doc code usage fixed
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-28 15:27:18 +03:00
Onuralp SEZER 96225cda0c Merge pull request #875 from LinasKo/feature/annotators-accept-PIL-images
Decorators around annotate functions, convert PIL images to np.ndarray
2024-02-28 14:34:14 +03:00
Piotr Skalski c039a90053 Merge pull request #952 from roboflow/fix/mask_iou_batch_memory_limit
Bugfix mask_iou_batch memory limit 5MB -> 5GB
2024-02-28 12:18:44 +01:00
PacificDou d9ccbda0a2 change memory limit unit to MB 2024-02-28 10:40:32 +00:00
PacificDou 49d4a4a9fd memory limit 5MB -> 5GB 2024-02-28 09:52:25 +00:00
Onuralp SEZER 97c01aa1a7 Merge pull request #951 from roboflow/dependabot/pip/mkdocstrings-0.24.1
⬆️ Bump mkdocstrings from 0.24.0 to 0.24.1
2024-02-28 03:57:53 +03:00
dependabot[bot] 3f9f87f645 ⬆️ Bump mkdocstrings from 0.24.0 to 0.24.1
Bumps [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) from 0.24.0 to 0.24.1.
- [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.24.0...0.24.1)

---
updated-dependencies:
- dependency-name: mkdocstrings
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-28 00:56:45 +00:00
Onuralp SEZER 2ba70f644c Merge branch 'develop' into feature/annotators-accept-PIL-images 2024-02-27 12:51:33 +03:00
Onuralp SEZER fa65d5f34e ci: 👷 minimum pillow and poetry version adjusted for min ver
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-27 12:50:21 +03:00
Onuralp SEZER a9f0154ca3 Merge pull request #949 from roboflow/dependabot/pip/notebook-7.1.1
⬆️ Bump notebook from 7.1.0 to 7.1.1
2024-02-27 12:33:43 +03:00
James b6f67e607e Merge pull request #889 from roboflow/ruff/config-updates
ci: 👷 ruff name rules updated
2024-02-27 09:33:01 +00:00
dependabot[bot] a5bb5a6aa8 ⬆️ Bump notebook from 7.1.0 to 7.1.1
Bumps [notebook](https://github.com/jupyter/notebook) from 7.1.0 to 7.1.1.
- [Release notes](https://github.com/jupyter/notebook/releases)
- [Changelog](https://github.com/jupyter/notebook/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/notebook/compare/@jupyter-notebook/tree@7.1.0...@jupyter-notebook/tree@7.1.1)

---
updated-dependencies:
- dependency-name: notebook
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-27 00:19:02 +00:00
Levi Vasconcelos 8b443d1b45 pre-commit
pre-commit
2024-02-26 17:41:58 -03:00
Levi Vasconcelos 61adff2c9a review: fix @deprecated_parameter parameter names 2024-02-26 17:41:10 -03:00
Levi Vasconcelos d4cee86e2b reviews: add custom message option to @deprecated_parameter; add docstring 2024-02-26 17:41:10 -03:00
Levi Vasconcelos cb46751c9a reviews: use test_utils.mock_detections 2024-02-26 17:41:10 -03:00
Levi Vasconcelos 5e7463dc73 reviews: removing test for deprecation 2024-02-26 17:41:10 -03:00
Levi Vasconcelos 9b50c92ec0 pre-commit on tests 2024-02-26 17:41:10 -03:00
Levi Vasconcelos 7ebbcd6c8e add polygon_zone unit tests 2024-02-26 17:41:10 -03:00
Levi Vasconcelos 069f6f22ca pre-commit reformatting
pre-commit reformatting
2024-02-26 17:41:10 -03:00
Levi Vasconcelos 5bfd8429a8 update documentation
add polygon_zone unit tests
2024-02-26 17:41:10 -03:00
Levi Vasconcelos e8ab777dfd add multiple anchors support: use np.all 2024-02-26 17:41:10 -03:00
Levi Vasconcelos d63837181f allow API backward compatibility 2024-02-26 17:41:10 -03:00
Levi Vasconcelos c523fc163a add multiple anchors support
add multiple anchors support

remove old trigger
2024-02-26 17:41:10 -03:00
Linas Kondrackis 2e6e61b778 Re-add Pillow 2024-02-26 21:09:02 +02:00
Linas Kondrackis 4ee56be8a0 Merge branch 'develop' into feature/annotators-accept-PIL-images 2024-02-26 21:01:16 +02:00
Onuralp SEZER e5dfc4c221 Merge pull request #946 from roboflow/dependabot/pip/mkdocs-git-committers-plugin-2-2.3.0
⬆️ Bump mkdocs-git-committers-plugin-2 from 2.2.3 to 2.3.0
2024-02-26 21:15:48 +03:00
Onuralp SEZER 02c1cb001c Merge pull request #945 from roboflow/dependabot/pip/mkdocs-material-9.5.11
⬆️ Bump mkdocs-material from 9.5.10 to 9.5.11
2024-02-26 21:14:08 +03:00
Onuralp SEZER 86a309d255 Merge pull request #947 from roboflow/dependabot/pip/pytest-8.0.2
⬆️ Bump pytest from 8.0.1 to 8.0.2
2024-02-26 21:13:34 +03:00
Linas Kondrackis fefd3386c1 Fix formatting 2024-02-26 20:06:57 +02:00
dependabot[bot] 54a4a3606f ⬆️ Bump pytest from 8.0.1 to 8.0.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.1 to 8.0.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.0.1...8.0.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 01:50:41 +00:00
dependabot[bot] d8396c10ea ⬆️ Bump mkdocs-git-committers-plugin-2 from 2.2.3 to 2.3.0
Bumps [mkdocs-git-committers-plugin-2](https://github.com/ojacques/mkdocs-git-committers-plugin-2) from 2.2.3 to 2.3.0.
- [Release notes](https://github.com/ojacques/mkdocs-git-committers-plugin-2/releases)
- [Commits](https://github.com/ojacques/mkdocs-git-committers-plugin-2/compare/2.2.3...2.3.0)

---
updated-dependencies:
- dependency-name: mkdocs-git-committers-plugin-2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 01:43:58 +00:00
dependabot[bot] 5255a25f03 ⬆️ Bump mkdocs-material from 9.5.10 to 9.5.11
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.5.10 to 9.5.11.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.10...9.5.11)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 01:37:07 +00:00
Linas Kondrackis afcb77965c Fix smoother removing tracking_id from detections
* Addresses issue #928 matching implementation in ByteTrack,
  but sidestepping the underlying cause outlined in #943.
2024-02-25 20:33:24 +02:00
pre-commit-ci[bot] 451e0200cb fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-23 03:23:20 +00:00
Nick Herrig b0667ce6cb Remove tqdm bar so mkdocs builds 2024-02-22 21:21:53 -06:00
PacificDou b2e085dd21 Merge pull request #938 from roboflow/mask-iou-batch-memory-issue
Limit memory usage for mask_iou_batch
2024-02-22 20:41:40 +01:00
pre-commit-ci[bot] a3a8fcb433 fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-22 18:00:04 +00:00
PacificDou 7d46c64628 limit memory usage for mask_iou_batch 2024-02-22 17:54:48 +00:00
pre-commit-ci[bot] 419c9e375b fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-22 02:03:18 +00:00
Nick Herrig 59bfc68b6f Add visuals to object tracking cookbook 2024-02-21 19:56:34 -06:00
Nick Herrig 8383b445f1 Add visualizations to annotate with detections cookbook 2024-02-21 18:10:41 -06:00
Onuralp SEZER 8599345a3c Merge pull request #934 from roboflow/dependabot/pip/cryptography-42.0.4
⬆️ Bump cryptography from 42.0.2 to 42.0.4
2024-02-22 00:19:40 +03:00
Onuralp SEZER 69fadf026b Merge pull request #931 from roboflow/dependabot/pip/nbconvert-7.16.1
⬆️ Bump nbconvert from 7.16.0 to 7.16.1
2024-02-22 00:19:22 +03:00
dependabot[bot] 4b2a9bf607 ⬆️ Bump cryptography from 42.0.2 to 42.0.4
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.2 to 42.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.2...42.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-21 20:49:06 +00:00
Nick Herrig a1d4cb8b33 Center html video, similar to count-object-crossing cookbook 2024-02-21 11:00:18 -06:00
Nick Herrig e9d0635a74 Add video display for supervision asset download example 2024-02-21 10:05:57 -06:00
dependabot[bot] dd07502543 ⬆️ Bump nbconvert from 7.16.0 to 7.16.1
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.16.0 to 7.16.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.16.0...v7.16.1)

---
updated-dependencies:
- dependency-name: nbconvert
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-21 00:15:43 +00:00
Onuralp SEZER 56d3e8ef0b Merge pull request #917 from roboflow/dependabot/pip/tox-4.13.0
⬆️ Bump tox from 4.12.1 to 4.13.0
2024-02-20 22:14:26 +03:00
Onuralp SEZER c328cf0469 Merge pull request #918 from roboflow/dependabot/pip/matplotlib-3.7.5
⬆️ Bump matplotlib from 3.7.4 to 3.7.5
2024-02-20 22:14:12 +03:00
Onuralp SEZER e34d274d8f Merge pull request #919 from roboflow/dependabot/pip/ruff-0.2.2
⬆️ Bump ruff from 0.2.1 to 0.2.2
2024-02-20 22:13:54 +03:00
Onuralp SEZER 88f0c68929 Merge pull request #920 from roboflow/dependabot/pip/pytest-8.0.1
⬆️ Bump pytest from 8.0.0 to 8.0.1
2024-02-20 22:13:40 +03:00
Onuralp SEZER 34d73e8847 Merge pull request #924 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2024-02-20 22:08:52 +03:00
Onuralp SEZER 56a7f8a55f Merge pull request #927 from roboflow/dependabot/pip/mkdocs-material-9.5.10
⬆️ Bump mkdocs-material from 9.5.9 to 9.5.10
2024-02-20 22:08:37 +03:00
dependabot[bot] afacc19236 ⬆️ Bump mkdocs-material from 9.5.9 to 9.5.10
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.5.9 to 9.5.10.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.9...9.5.10)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-20 00:58:56 +00:00
pre-commit-ci[bot] 59ba52fd80 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.2.1 → v0.2.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.1...v0.2.2)
2024-02-19 17:48:58 +00:00
Piotr Skalski 5ffb3424f3 Merge pull request #922 from roboflow/cookbooks/style-update
new cookbook z-index fix for author avatar
2024-02-19 12:41:38 +01:00
SkalskiP ac7d36b215 new cookbook z-index fix for author avatar 2024-02-19 12:37:25 +01:00
James cf3a954416 Merge pull request #908 from roboflow/cookbooks/author-avatar-zindex
fix: 🐞 cookbook z-index fix for author avatar
2024-02-19 10:00:45 +00:00
James 6615c553e5 Merge pull request #870 from roboflow/docs/home-page
docs: 📝 h1 title Home removed from index.md
2024-02-19 10:00:21 +00:00
dependabot[bot] 0f36679ac7 ⬆️ Bump pytest from 8.0.0 to 8.0.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.0 to 8.0.1.
- [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.0.0...8.0.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 01:19:38 +00:00
dependabot[bot] 97a986cd11 ⬆️ Bump ruff from 0.2.1 to 0.2.2
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.2.1 to 0.2.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.2.1...v0.2.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 01:09:46 +00:00
dependabot[bot] a21d54fab3 ⬆️ Bump matplotlib from 3.7.4 to 3.7.5
Bumps [matplotlib](https://github.com/matplotlib/matplotlib) from 3.7.4 to 3.7.5.
- [Release notes](https://github.com/matplotlib/matplotlib/releases)
- [Commits](https://github.com/matplotlib/matplotlib/compare/v3.7.4...v3.7.5)

---
updated-dependencies:
- dependency-name: matplotlib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 01:02:38 +00:00
dependabot[bot] b80a88ee25 ⬆️ Bump tox from 4.12.1 to 4.13.0
Bumps [tox](https://github.com/tox-dev/tox) from 4.12.1 to 4.13.0.
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.12.1...4.13.0)

---
updated-dependencies:
- dependency-name: tox
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 00:58:49 +00:00
Onuralp SEZER c1c528d378 Merge pull request #914 from roboflow/dependabot/pip/cryptography-42.0.2
⬆️ Bump cryptography from 42.0.0 to 42.0.2
2024-02-17 21:46:06 +03:00
dependabot[bot] 1c1a6236ea ⬆️ Bump cryptography from 42.0.0 to 42.0.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.0 to 42.0.2.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.0...42.0.2)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-17 00:54:06 +00:00
Piotr Skalski df3f8464b1 Merge pull request #911 from roboflow/cookbooks/zero-shot-object-detection-with-yolo-world
🧑‍🍳 Zero-Shot Object Detection with YOLO-World Cookbook
2024-02-16 14:29:01 +01:00
pre-commit-ci[bot] 8625c7217c fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-16 13:26:34 +00:00
SkalskiP 382b4e0801 🧑‍🍳 Zero-Shot Object Detection with YOLO-World Cookbook 2024-02-16 14:23:20 +01:00
Onuralp SEZER 6d2d0c01a3 fix: 🐞 cookbook z-index fix for author avatar
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-15 20:43:11 +03:00
sansyoandpre-commit-ci[bot] 15b099cb71 Add Support for Center Left,Right Text Position for LabelAnnotator (#905)
* Added Position.CENTER_LEFT
* Added Position.CENTER_RIGHT
---------
Author: sansyo <moutoutan@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-02-15 18:17:28 +03:00
Onuralp SEZER 6ba9e70b69 Merge pull request #904 from NickHerrig/feature/fix-cookbook
Fix google colab link in object tracking cookbook
2024-02-15 14:20:00 +03:00
Nick Herrig 14771fa326 Fix google colab link in object tracking cookbook 2024-02-14 21:56:33 -06:00
Onuralp SEZER 95398c2a8e Merge pull request #901 from Kadermiyanyedi/add-class-name-to-detection-data
[Detections] - from_inference should include 'class_name' key in Detections.data even if result is empty #837
2024-02-14 23:39:05 +03:00
Kader Miyanyedi 75bb07078c fix(detection): add class name to detection data even if empty
Signed-off-by: Kader Miyanyedi <Kadermiyanyedi@hotmail.com>
2024-02-14 23:36:48 +03:00
Kader Miyanyedi ba7077918d docs(byte_tracker): improve byte track argument doc string descriptions 2024-02-14 21:25:28 +03:00
Onuralp SEZER 6b16970d50 Merge pull request #898 from roboflow/dependabot/pip/notebook-7.1.0
⬆️ Bump notebook from 7.0.8 to 7.1.0
2024-02-14 17:25:25 +03:00
Linas Kondrackis 20b412b7e1 Docs fix: ImageType displayed on multiple lines 2024-02-14 15:42:50 +02:00
Linas Kondrackis 3f965c9121 Remove check-docstring-first from pre-commit hook
* Add docstring for ImageType type
* As discussed in https://github.com/roboflow/supervision/pull/875#issuecomment-1941388238
2024-02-14 13:52:50 +02:00
Linas Kondrackis 08418246c2 Add Pillow dependency, add docsrings for ImageType
* PR #875
2024-02-14 13:52:15 +02:00
dependabot[bot] e1607b4590 ⬆️ Bump notebook from 7.0.8 to 7.1.0
Bumps [notebook](https://github.com/jupyter/notebook) from 7.0.8 to 7.1.0.
- [Release notes](https://github.com/jupyter/notebook/releases)
- [Changelog](https://github.com/jupyter/notebook/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/notebook/compare/@jupyter-notebook/tree@7.0.8...@jupyter-notebook/tree@7.1.0)

---
updated-dependencies:
- dependency-name: notebook
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-14 01:12:14 +00:00
Onuralp SEZER be2d75c312 ci: 👷 check-docstring-first removed
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-13 16:06:27 +03:00
Onuralp SEZER a697e71ccd ci: 👷 ruff name rules updated
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-13 15:59:59 +03:00
Onuralp SEZER e3f0ca6937 Merge pull request #885 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2024-02-12 21:54:20 +03:00
Kader Miyanyedi dafa2a42de refactor(byte_tracker): change byte tracker class argument names to more clear 2024-02-12 21:21:26 +03:00
pre-commit-ci[bot] c96022b97a chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.2.0 → v0.2.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.0...v0.2.1)
2024-02-12 17:38:59 +00:00
Piotr Skalski 899be6a5a4 Merge pull request #884 from roboflow/cookbooks/contributing-guidelines
`CONTRIBUTING.md` updates.
2024-02-12 18:26:21 +01:00
pre-commit-ci[bot] 94b0e9cd22 fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-12 17:25:12 +00:00
SkalskiP 8ac3b5f8d2 CONTRIBUTING.md updates. 2024-02-12 18:23:56 +01:00
Piotr Skalski cebf726997 Merge pull request #883 from roboflow/cookbooks/count-objects-crossing-the-line-3
`Count People Crossing the Line` cookbook updates.
2024-02-12 17:02:18 +01:00
pre-commit-ci[bot] 8ddfcdcd9a fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-12 16:00:48 +00:00
SkalskiP 5997c39ac7 Count People Crossing the Line cookbook updates. 2024-02-12 16:43:40 +01:00
Piotr Skalski 39b5563465 Merge pull request #882 from roboflow/docs/line-zone-docs-improvement
`LineZone`, `LineZoneAnnotator` documentation improvements
2024-02-12 13:53:33 +01:00
pre-commit-ci[bot] 1b07974e93 fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-12 12:51:07 +00:00
SkalskiP ba81a09b2c LineZone, LineZoneAnnotator documentation improvements 2024-02-12 13:43:58 +01:00
Onuralp SEZER 2e898f137e Merge pull request #879 from roboflow/dependabot/pip/tqdm-4.66.2
⬆️ Bump tqdm from 4.66.1 to 4.66.2
2024-02-12 15:40:26 +03:00
dependabot[bot] c7e8534650 ⬆️ Bump tqdm from 4.66.1 to 4.66.2
Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.66.1 to 4.66.2.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.66.1...v4.66.2)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 10:30:41 +00:00
Onuralp SEZER fd2b3c4e8e Merge pull request #877 from roboflow/dependabot/pip/mkdocs-material-9.5.9
⬆️ Bump mkdocs-material from 9.5.8 to 9.5.9
2024-02-12 13:21:16 +03:00
Onuralp SEZER 632d078f4b Merge pull request #878 from roboflow/dependabot/pip/notebook-7.0.8
⬆️ Bump notebook from 7.0.7 to 7.0.8
2024-02-12 13:20:54 +03:00
Onuralp SEZER cbd77b10f9 Merge pull request #880 from roboflow/dependabot/pip/twine-5.0.0
⬆️ Bump twine from 4.0.2 to 5.0.0
2024-02-12 13:19:54 +03:00
dependabot[bot] 48500cd350 ⬆️ Bump twine from 4.0.2 to 5.0.0
Bumps [twine](https://github.com/pypa/twine) from 4.0.2 to 5.0.0.
- [Release notes](https://github.com/pypa/twine/releases)
- [Changelog](https://github.com/pypa/twine/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pypa/twine/compare/4.0.2...5.0.0)

---
updated-dependencies:
- dependency-name: twine
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 00:55:18 +00:00
dependabot[bot] ac53125bb6 ⬆️ Bump notebook from 7.0.7 to 7.0.8
Bumps [notebook](https://github.com/jupyter/notebook) from 7.0.7 to 7.0.8.
- [Release notes](https://github.com/jupyter/notebook/releases)
- [Changelog](https://github.com/jupyter/notebook/blob/@jupyter-notebook/tree@7.0.8/CHANGELOG.md)
- [Commits](https://github.com/jupyter/notebook/compare/@jupyter-notebook/tree@7.0.7...@jupyter-notebook/tree@7.0.8)

---
updated-dependencies:
- dependency-name: notebook
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 00:50:34 +00:00
dependabot[bot] 0f2a18efd1 ⬆️ Bump mkdocs-material from 9.5.8 to 9.5.9
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.5.8 to 9.5.9.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.8...9.5.9)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 00:48:54 +00:00
Linas Kondrackis c8f7622e91 Remove ImgType docstring
* Bad decision, but makes the pre-commit hook happy
2024-02-10 16:39:38 +02:00
Linas Kondrackis c2dd5031ba Decorators around annotate functions, convert PIL images to np.ndarray and back, if required 2024-02-10 14:43:00 +02:00
Piotr Skalski 2f9fee6451 Merge pull request #872 from roboflow/cookbooks/count-pople-crossing-the-line-2
[Cookbooks] - Count People Crossing the Line 2
2024-02-09 19:11:55 +01:00
pre-commit-ci[bot] b6dc988e37 fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-09 18:10:48 +00:00
SkalskiP 2ea2231324 ready 2024-02-09 19:09:10 +01:00
Piotr Skalski 78d6890508 Merge pull request #869 from roboflow/cookbooks/count-objects-crossing-the-line
[Cookbooks] - Count Objects Crossing the Line
2024-02-09 18:50:57 +01:00
SkalskiP d8584333ef Merge remote-tracking branch 'origin/cookbooks/count-objects-crossing-the-line' into cookbooks/count-objects-crossing-the-line 2024-02-09 18:50:02 +01:00
SkalskiP 69213b19d7 up 2024-02-09 18:49:55 +01:00
Onuralp SEZER 0d312f3cd7 docs: 📝 h1 title Home removed from index.md
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2024-02-09 20:17:53 +03:00
pre-commit-ci[bot] 01e7330e6e fix(pre_commit): 🎨 auto format pre-commit hooks 2024-02-09 16:57:32 +00:00
SkalskiP 9d71636051 cleaning up Nick's cookbooks 2024-02-09 17:57:18 +01:00
SkalskiP 569157f0f0 Merge remote-tracking branch 'origin/develop' into cookbooks/count-objects-crossing-the-line
# Conflicts:
#	docs/theme/cookbooks.html
2024-02-09 17:43:19 +01:00
SkalskiP 6cf9ece3a8 initial changes for count objects crossing the line cookbook 2024-02-09 17:25:55 +01:00
33 changed files with 3428 additions and 839 deletions
-2
View File
@@ -3,8 +3,6 @@ on:
push:
tags:
- '[0-9]+.[0-9]+[0-9]+.[0-9]'
- '[0-9]+.[0-9]+[0-9]+.[0-9]'
- '[0-9]+.[0-9]+[0-9]+.[0-9]'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
+1
View File
@@ -37,6 +37,7 @@ jobs:
matplotlib==3.5.0 \
numpy==1.21.2 \
opencv-python==4.5.5.64 \
Pillow==10.1.0 \
packaging==23.2 \
pluggy==1.3.0 \
pyparsing==3.1.1 \
+1 -2
View File
@@ -14,7 +14,6 @@ repos:
exclude: test/.*\.py
- id: check-yaml
exclude: mkdocs.yml
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-toml
- id: check-case-conflict
@@ -47,7 +46,7 @@ repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0
rev: v0.2.2
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
+14
View File
@@ -112,6 +112,20 @@ To run the documentation, install the project requirements with `poetry install
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/nodebooks`](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.
+10 -2
View File
@@ -2,6 +2,14 @@
comments: true
---
# LineZone
<div class="md-typeset">
<h2>LineZone</h2>
</div>
:::supervision.detection.line_counter.LineZone
:::supervision.detection.line_zone.LineZone
<div class="md-typeset">
<h2>LineZoneAnnotator</h2>
</div>
:::supervision.detection.line_zone.LineZoneAnnotator
+3 -1
View File
@@ -2,7 +2,9 @@
comments: true
---
# PolygonZone
<div class="md-typeset">
<h2>PolygonZone</h2>
</div>
:::supervision.detection.tools.polygon_zone.PolygonZone
-1
View File
@@ -1,6 +1,5 @@
---
comments: true
status: new
---
# Detection Smoother
+11 -10
View File
@@ -1,19 +1,20 @@
---
template: index.html
comments: true
hide:
- navigation
- toc
---
<div align="center">
<p>
<a align="center" href="" target="_blank">
<img
width="850"
src="https://media.roboflow.com/open-source/supervision/rf-supervision-banner.png?updatedAt=1678995927529"
>
</a>
</p>
<div class="md-typeset">
<h1></h1>
</div>
<div align="center" id="logo">
<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>
## 👋 Hello
@@ -45,7 +46,7 @@ You can install `supervision` with pip in a
If you require the full version of `supervision` with GUI support you can install the desktop version. This version includes the GUI components of OpenCV, allowing you to display images and videos on the screen.
```bash
pip install supervision[desktop]
pip install "supervision[desktop]"
```
!!! example "git clone (for development)"
+1 -1
View File
@@ -55,7 +55,7 @@ document.addEventListener("DOMContentLoaded", function () {
let authorAvatarsHTML = authorDataArray.map((authorData, index) => {
const marginLeft = index === 0 ? '0' : '-10px';
const zIndex = 100 - index;
const zIndex = 4 - index;
return `
<div
class="author-container"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+29 -26
View File
@@ -4,38 +4,20 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Experimenting with Supervision Assets\n",
"# Download Supervision Assets\n",
"\n",
"---\n",
"\n",
"<p align=\"center\">\n",
" <a href=\"https://colab.research.google.com/github/roboflow/supervision/blob/develop/docs/notebooks/supervision-assets.ipynb\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Colab\"></a>\n",
"</p>\n",
"[![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/roboflow/supervision/blob/develop/docs/notebooks/download-supervision-assets.ipynb)\n",
"\n",
"When experimenting with interesting and useful features of the Supervision package, its important to have some sort of image or video data to experiment with. Luckily for us, Supervision ships with [Assets](https://supervision.roboflow.com/latest/assets/)! Assets is a collection of videos that you can utilize to start experimenting with the various features Supervision has to offer. Let's take a look at how to use this resource.\n",
"When experimenting with interesting and useful features of the Supervision package, it's important to have some sort of image or video data to experiment with. Luckily for us, Supervision ships with [Assets](https://supervision.roboflow.com/latest/assets/)! Assets is a collection of videos that you can utilize to start experimenting with the various features Supervision has to offer. Let's take a look at how to use this resource.\n",
"\n",
"## Install with Pip\n",
"\n",
"If you're running this code outside a Jupyter notebook, it's generally a best practice to create a virtual environment so that your projects deppendencies are isolated. Run the following ing your command line of choice to create and source one.\n",
"\n",
"```shell\n",
"\n",
"python -m venv venv\n",
"source venv/bin/activate\n",
"\n",
"``` "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that we've got a virtual enviornment installed and sourced, let's install the pip package with the assets \"extra\" package. Make sure to remove the \"!\" if running this in your command line."
"## Install Dependencies"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"metadata": {
"vscode": {
"languageId": "shellscript"
@@ -63,7 +45,7 @@
"source": [
"from supervision.assets import download_assets, VideoAssets\n",
"\n",
"# Download a video asset from the supervision package.\n",
"# Download the a video of the subway.\n",
"path_to_video = download_assets(VideoAssets.SUBWAY)"
]
},
@@ -71,7 +53,28 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We're now equipt with a video asset from Supervision to run some experiements on! For more information on available video assets, visit the [Supervision API Reference](https://supervision.roboflow.com/latest/assets/#videoassets). Happy building!"
"With this, we now have a high quality video asset for use in demos. Let's take a look at what we downloaded. Keep in mind that the video preview below works only in the web version of the cookbooks and not in Google Colab.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div style=\"display: flex; justify-content: center;\">\n",
" <video controls width=\"320\" height=\"240\">\n",
" <source\n",
" src=\"https://media.roboflow.com/supervision/video-examples/subway.mp4\"\n",
" type=\"video/mp4\"\n",
" >\n",
" </video>\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We're now equipt with a video asset from Supervision to run some experiments on! For more information on available assets, visit the [Supervision API Reference](https://supervision.roboflow.com/latest/assets). Happy building!"
]
}
],
@@ -91,7 +94,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.11.8"
}
},
"nbformat": 4,
+225 -60
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
View File
@@ -12,6 +12,8 @@
</div>
<div class="custom-grid">
<p class="card repo-card" data-url="/develop/notebooks/quickstart" data-name="Supervision Quickstart" data-labels="ANNOTATOR,DETECTION,SAM" data-version="v0.18.0" data-author="SkalskiP,onuralpszr"></p>
<p class="card repo-card" data-url="/develop/notebooks/count-objects-crossing-the-line" data-name="Count Objects Crossing the Line" data-labels="ANNOTATORS,LINE ZONE,TRACKING" data-version="v0.18.0" data-author="SkalskiP"></p>
<p class="card repo-card" data-url="/develop/notebooks/zero-shot-object-detection-with-yolo-world" data-name="Zero-Shot Object Detection with YOLO-World" data-labels="ANNOTATORS,DETECTION,INFERENCE" data-version="v0.19.0" data-author="SkalskiP"></p>
<p class="card repo-card" data-url="/develop/notebooks/download-supervision-assets" data-name="Downloading Supervision Assets" data-labels="ASSETS" data-version="v0.18.0" data-author="nickherrig"></p>
<p class="card repo-card" data-url="/develop/notebooks/annotate-video-with-detections" data-name="Annotate Video with Detections" data-labels="INFERENCE,YOLOV8" data-version="v0.18.0" data-author="nickherrig"></p>
<p class="card repo-card" data-url="/develop/notebooks/object-tracking" data-name="Object Tracking" data-labels="TRACKING, ANNOTATOR" data-version="v0.18.0" data-author="nickherrig"></p>
+15
View File
@@ -0,0 +1,15 @@
{% extends "main.html" %}
{% block content %}
{{ super() }}
<style>
.md-content__button {
display: none;
}
#logo {
position: relative;
top: -60px;
left: 50%;
transform: translateX(-50%);
}
</style>
{% endblock %}
Generated
+604 -501
View File
File diff suppressed because it is too large Load Diff
+12 -11
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "supervision"
version = "0.19.0rc3"
version = "0.19.0rc5"
description = "A set of easy-to-use utils that will come in handy in any Computer Vision project"
authors = ["Piotr Skalski <piotr.skalski92@gmail.com>"]
maintainers = ["Piotr Skalski <piotr.skalski92@gmail.com>"]
@@ -43,14 +43,15 @@ defusedxml = "^0.7.1"
opencv-python = { version = ">=4.5.5.64", optional = true }
opencv-python-headless = ">=4.5.5.64"
requests = { version = ">=2.26.0,<=2.31.0", optional = true }
tqdm = { version = ">=4.62.3,<=4.66.1", optional = true }
tqdm = { version = ">=4.62.3,<=4.66.2", optional = true }
pillow = ">=9.4"
[tool.poetry.extras]
desktop = ["opencv-python"]
assets = ["requests","tqdm"]
[tool.poetry.group.dev.dependencies]
twine = "^4.0.2"
twine = ">=4.0.2,<6.0.0"
pytest = ">=7.2.2,<9.0.0"
wheel = ">=0.40,<0.43"
build = ">=0.10,<1.1"
@@ -111,12 +112,12 @@ exclude = '''
[tool.ruff]
target-version = "py38"
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
select = ["E", "F"]
ignore = []
lint.select = ["E", "F"]
lint.ignore = []
# Allow autofix for all enabled rules (when `--fix`) is provided.
fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
unfixable = []
lint.fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
lint.unfixable = []
# Exclude a variety of commonly ignored directories.
exclude = [
@@ -151,17 +152,17 @@ line-length = 88
indent-width = 4
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[tool.ruff.flake8-quotes]
[tool.ruff.lint.flake8-quotes]
inline-quotes = "double"
multiline-quotes = "double"
docstring-quotes = "double"
[tool.ruff.pydocstyle]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["E402","F401"]
"supervision/assets/list.py" = ["E501"]
+1 -1
View File
@@ -35,7 +35,7 @@ from supervision.dataset.core import (
)
from supervision.detection.annotate import BoxAnnotator
from supervision.detection.core import Detections
from supervision.detection.line_counter import LineZone, LineZoneAnnotator
from supervision.detection.line_zone import LineZone, LineZoneAnnotator
from supervision.detection.tools.csv_sink import CSVSink
from supervision.detection.tools.inference_slicer import InferenceSlicer
from supervision.detection.tools.polygon_zone import PolygonZone, PolygonZoneAnnotator
+12 -1
View File
@@ -1,11 +1,22 @@
from abc import ABC, abstractmethod
from typing import TypeVar
import numpy as np
from PIL import Image
from supervision.detection.core import Detections
ImageType = TypeVar("ImageType", np.ndarray, Image.Image)
"""
An image of type `np.ndarray` or `PIL.Image.Image`.
Unlike a `Union`, ensures the type remains consistent. If a function
takes an `ImageType` argument and returns an `ImageType`, when you
pass an `np.ndarray`, you will get an `np.ndarray` back.
"""
class BaseAnnotator(ABC):
@abstractmethod
def annotate(self, scene: np.ndarray, detections: Detections) -> np.ndarray:
def annotate(self, scene: ImageType, detections: Detections) -> ImageType:
pass
+164 -74
View File
@@ -4,8 +4,13 @@ from typing import List, Optional, Tuple, Union
import cv2
import numpy as np
from supervision.annotators.base import BaseAnnotator
from supervision.annotators.utils import ColorLookup, Trace, resolve_color
from supervision.annotators.base import BaseAnnotator, ImageType
from supervision.annotators.utils import (
ColorLookup,
Trace,
resolve_color,
scene_to_annotator_img_type,
)
from supervision.config import CLASS_NAME_DATA_FIELD, ORIENTED_BOX_COORDINATES
from supervision.detection.core import Detections
from supervision.detection.utils import clip_boxes, mask_to_polygons
@@ -37,23 +42,26 @@ class BoundingBoxAnnotator(BaseAnnotator):
self.thickness: int = thickness
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with bounding boxes based on the provided detections.
Args:
scene (np.ndarray): The image where bounding boxes will be drawn.
scene (ImageType): The image where bounding boxes will be drawn. `ImageType`
is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -115,23 +123,27 @@ class OrientedBoxAnnotator(BaseAnnotator):
self.thickness: int = thickness
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with oriented bounding boxes based on the provided detections.
Args:
scene (np.ndarray): The image where bounding boxes will be drawn.
scene (ImageType): The image where bounding boxes will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -199,23 +211,27 @@ class MaskAnnotator(BaseAnnotator):
self.opacity = opacity
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with masks based on the provided detections.
Args:
scene (np.ndarray): The image where masks will be drawn.
scene (ImageType): The image where masks will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -282,23 +298,27 @@ class PolygonAnnotator(BaseAnnotator):
self.thickness: int = thickness
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with polygons based on the provided detections.
Args:
scene (np.ndarray): The image where polygons will be drawn.
scene (ImageType): The image where polygons will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -364,23 +384,27 @@ class ColorAnnotator(BaseAnnotator):
self.color_lookup: ColorLookup = color_lookup
self.opacity = opacity
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with box masks based on the provided detections.
Args:
scene (np.ndarray): The image where bounding boxes will be drawn.
scene (ImageType): The image where bounding boxes will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -454,23 +478,27 @@ class HaloAnnotator(BaseAnnotator):
self.color_lookup: ColorLookup = color_lookup
self.kernel_size: int = kernel_size
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with halos based on the provided detections.
Args:
scene (np.ndarray): The image where masks will be drawn.
scene (ImageType): The image where masks will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -548,23 +576,27 @@ class EllipseAnnotator(BaseAnnotator):
self.end_angle: int = end_angle
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with ellipses based on the provided detections.
Args:
scene (np.ndarray): The image where ellipses will be drawn.
scene (ImageType): The image where ellipses will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -635,23 +667,27 @@ class BoxCornerAnnotator(BaseAnnotator):
self.corner_length: int = corner_length
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with box corners based on the provided detections.
Args:
scene (np.ndarray): The image where box corners will be drawn.
scene (ImageType): The image where box corners will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -719,23 +755,27 @@ class CircleAnnotator(BaseAnnotator):
self.thickness: int = thickness
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with circles based on the provided detections.
Args:
scene (np.ndarray): The image where box corners will be drawn.
scene (ImageType): The image where box corners will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -805,23 +845,27 @@ class DotAnnotator(BaseAnnotator):
self.position: Position = position
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with dots based on the provided detections.
Args:
scene (np.ndarray): The image where dots will be drawn.
scene (ImageType): The image where dots will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -929,26 +973,44 @@ class LabelAnnotator:
center_x + text_w // 2,
center_y + text_h,
)
elif position == Position.CENTER_LEFT:
return (
center_x - text_w,
center_y - text_h // 2,
center_x,
center_y + text_h // 2,
)
elif position == Position.CENTER_RIGHT:
return (
center_x,
center_y - text_h // 2,
center_x + text_w,
center_y + text_h // 2,
)
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
labels: List[str] = None,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with labels based on the provided detections.
Args:
scene (np.ndarray): The image where labels will be drawn.
scene (ImageType): The image where labels will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
labels (List[str]): Optional. Custom labels for each detection.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1049,20 +1111,24 @@ class BlurAnnotator(BaseAnnotator):
"""
self.kernel_size: int = kernel_size
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene by blurring regions based on the provided detections.
Args:
scene (np.ndarray): The image where blurring will be applied.
scene (ImageType): The image where blurring will be applied.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1130,24 +1196,28 @@ class TraceAnnotator:
self.thickness = thickness
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Draws trace paths on the frame based on the detection coordinates provided.
Args:
scene (np.ndarray): The image on which the traces will be drawn.
scene (ImageType): The image on which the traces will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): The detections which include coordinates for
which the traces will be drawn.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1233,16 +1303,20 @@ class HeatMapAnnotator:
self.top_hue = top_hue
self.low_hue = low_hue
def annotate(self, scene: np.ndarray, detections: Detections) -> np.ndarray:
@scene_to_annotator_img_type
def annotate(self, scene: ImageType, detections: Detections) -> ImageType:
"""
Annotates the scene with a heatmap based on the provided detections.
Args:
scene (np.ndarray): The image where the heatmap will be drawn.
scene (ImageType): The image where the heatmap will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
Returns:
Annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1305,21 +1379,25 @@ class PixelateAnnotator(BaseAnnotator):
"""
self.pixel_size: int = pixel_size
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene by pixelating regions based on the provided
detections.
Args:
scene (np.ndarray): The image where pixelating will be applied.
scene (ImageType): The image where pixelating will be applied.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1389,23 +1467,27 @@ class TriangleAnnotator(BaseAnnotator):
self.position: Position = position
self.color_lookup: ColorLookup = color_lookup
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with triangles based on the provided detections.
Args:
scene (np.ndarray): The image where triangles will be drawn.
scene (ImageType): The image where triangles will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1481,24 +1563,28 @@ class RoundBoxAnnotator(BaseAnnotator):
raise ValueError("roundness attribute must be float between (0, 1.0]")
self.roundness: float = roundness
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with bounding boxes with rounded edges
based on the provided detections.
Args:
scene (np.ndarray): The image where rounded bounding boxes will be drawn.
scene (ImageType): The image where rounded bounding boxes will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1614,20 +1700,23 @@ class PercentageBarAnnotator(BaseAnnotator):
if border_thickness is None:
self.border_thickness = int(0.15 * self.height)
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
custom_values: Optional[np.ndarray] = None,
) -> np.ndarray:
) -> ImageType:
"""
Annotates the given scene with percentage bars based on the provided
detections. The percentage bars visually represent the confidence or custom
values associated with each detection.
Args:
scene (np.ndarray): The image where percentage bars will be drawn.
scene (ImageType): The image where percentage bars will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): Object detections to annotate.
custom_color_lookup (Optional[np.ndarray]): Custom color lookup array.
Allows to override the default color mapping strategy.
@@ -1638,7 +1727,8 @@ class PercentageBarAnnotator(BaseAnnotator):
to be displayed.
Returns:
The annotated image.
The annotated image, matching the type of `scene` (`numpy.ndarray`
or `PIL.Image.Image`)
Example:
```python
@@ -1647,7 +1737,7 @@ class PercentageBarAnnotator(BaseAnnotator):
image = ...
detections = sv.Detections(...)
percentage_bar_annotator = sv.BoundingBoxAnnotator()
percentage_bar_annotator = sv.PercentageBarAnnotator()
annotated_frame = percentage_bar_annotator.annotate(
scene=image.copy(),
detections=detections
+34
View File
@@ -1,8 +1,12 @@
from enum import Enum
from functools import wraps
from typing import Optional, Union
import cv2
import numpy as np
from PIL import Image
from supervision.annotators.base import ImageType
from supervision.detection.core import Detections
from supervision.draw.color import Color, ColorPalette
from supervision.geometry.core import Position
@@ -119,3 +123,33 @@ class Trace:
def get(self, tracker_id: int) -> np.ndarray:
return self.xy[self.tracker_id == tracker_id]
def pillow_to_cv2(image: Image.Image) -> np.ndarray:
scene = np.array(image)
scene = cv2.cvtColor(scene, cv2.COLOR_RGB2BGR)
return scene
def scene_to_annotator_img_type(annotate_func):
"""
Decorates `BaseAnnotator.annotate` implementations, converts scene to
an image type used internally by the annotators, converts back when annotation
is complete.
"""
@wraps(annotate_func)
def wrapper(self, scene: ImageType, *args, **kwargs):
if isinstance(scene, np.ndarray):
return annotate_func(self, scene, *args, **kwargs)
if isinstance(scene, Image.Image):
scene = pillow_to_cv2(scene)
annotated = annotate_func(self, scene, *args, **kwargs)
annotated = cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB)
annotated = Image.fromarray(annotated)
return annotated
raise ValueError(f"Unsupported image type: {type(scene)}")
return wrapper
+10 -5
View File
@@ -1,8 +1,9 @@
from typing import List, Optional, Union
import cv2
import numpy as np
from supervision.annotators.base import ImageType
from supervision.annotators.utils import scene_to_annotator_img_type
from supervision.detection.core import Detections
from supervision.draw.color import Color, ColorPalette
from supervision.utils.internal import deprecated
@@ -45,18 +46,21 @@ class BoxAnnotator:
self.text_thickness: int = text_thickness
self.text_padding: int = text_padding
@scene_to_annotator_img_type
def annotate(
self,
scene: np.ndarray,
scene: ImageType,
detections: Detections,
labels: Optional[List[str]] = None,
skip_label: bool = False,
) -> np.ndarray:
) -> ImageType:
"""
Draws bounding boxes on the frame using the detections provided.
Args:
scene (np.ndarray): The image on which the bounding boxes will be drawn
scene (ImageType): The image on which the bounding boxes will be drawn.
`ImageType` is a flexible type, accepting either `numpy.ndarray`
or `PIL.Image.Image`.
detections (Detections): The detections for which the
bounding boxes will be drawn
labels (Optional[List[str]]): An optional list of labels
@@ -64,7 +68,8 @@ class BoxAnnotator:
corresponding `class_id` will be used as label.
skip_label (bool): Is set to `True`, skips bounding box label annotation.
Returns:
np.ndarray: The image with the bounding boxes drawn on it
ImageType: The image with the bounding boxes drawn on it, matching the
type of `scene` (`numpy.ndarray` or `PIL.Image.Image`)
Example:
```python
+3 -1
View File
@@ -487,7 +487,9 @@ class Detections:
)
if np.asarray(xyxy).shape[0] == 0:
return cls.empty()
empty_detection = cls.empty()
empty_detection.data = {CLASS_NAME_DATA_FIELD: np.empty(0)}
return empty_detection
return cls(
xyxy=xyxy,
@@ -14,6 +14,12 @@ class LineZone:
This class is responsible for counting the number of objects that cross a
predefined line.
<video controls>
<source
src="https://media.roboflow.com/supervision/cookbooks/count-objects-crossing-the-line-result-1280x720.mp4"
type="video/mp4">
</video>
!!! warning
LineZone uses the `tracker_id`. Read
@@ -25,7 +31,28 @@ class LineZone:
to inside.
out_count (int): The number of objects that have crossed the line from inside
to outside.
"""
Example:
```python
import supervision as sv
from ultralytics import YOLO
model = YOLO(<SOURCE_MODEL_PATH>)
tracker = sv.ByteTrack()
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
start, end = sv.Point(x=0, y=1080), sv.Point(x=3840, y=1080)
line_zone = sv.LineZone(start=start, end=end)
for frame in frames_generator:
result = model(frame)[0]
detections = sv.Detections.from_ultralytics(result)
detections = tracker.update_with_detections(detections)
crossed_in, crossed_out = line_zone.trigger(detections)
line_zone.in_count, line_zone.out_count
# 7, 2
```
""" # noqa: E501 // docs
def __init__(
self,
+46 -20
View File
@@ -1,5 +1,5 @@
from dataclasses import replace
from typing import Optional, Tuple
from typing import Iterable, Optional, Tuple
import cv2
import numpy as np
@@ -10,6 +10,7 @@ from supervision.draw.color import Color
from supervision.draw.utils import draw_polygon, draw_text
from supervision.geometry.core import Position
from supervision.geometry.utils import get_polygon_center
from supervision.utils.internal import deprecated_parameter
class PolygonZone:
@@ -20,21 +21,32 @@ class PolygonZone:
polygon (np.ndarray): A polygon represented by a numpy array of shape
`(N, 2)`, containing the `x`, `y` coordinates of the points.
frame_resolution_wh (Tuple[int, int]): The frame resolution (width, height)
triggering_position (Position): The position within the bounding
box that triggers the zone (default: Position.BOTTOM_CENTER)
triggering_anchors (Iterable[sv.Position]): A list of positions specifying
which anchors of the detections bounding box to consider when deciding on
whether the detection fits within the PolygonZone
(default: (sv.Position.BOTTOM_CENTER,)).
current_count (int): The current count of detected objects within the zone
mask (np.ndarray): The 2D bool mask for the polygon zone
"""
@deprecated_parameter(
old_parameter="triggering_position",
new_parameter="triggering_anchors",
map_function=lambda x: [x],
warning_message="`{old_parameter}` in `{function_name}` is deprecated and will "
"be remove in `supervision-0.23.0`. Use '{new_parameter}' "
"instead.",
)
def __init__(
self,
polygon: np.ndarray,
frame_resolution_wh: Tuple[int, int],
triggering_position: Position = Position.BOTTOM_CENTER,
triggering_anchors: Iterable[Position] = (Position.BOTTOM_CENTER,),
):
self.polygon = polygon.astype(int)
self.frame_resolution_wh = frame_resolution_wh
self.triggering_position = triggering_position
self.triggering_anchors = triggering_anchors
self.current_count = 0
width, height = frame_resolution_wh
@@ -59,10 +71,20 @@ class PolygonZone:
xyxy=detections.xyxy, resolution_wh=self.frame_resolution_wh
)
clipped_detections = replace(detections, xyxy=clipped_xyxy)
clipped_anchors = np.ceil(
clipped_detections.get_anchors_coordinates(anchor=self.triggering_position)
).astype(int)
is_in_zone = self.mask[clipped_anchors[:, 1], clipped_anchors[:, 0]]
all_clipped_anchors = np.array(
[
np.ceil(clipped_detections.get_anchors_coordinates(anchor)).astype(int)
for anchor in self.triggering_anchors
]
)
is_in_zone = (
self.mask[all_clipped_anchors[:, :, 1], all_clipped_anchors[:, :, 0]]
.transpose()
.astype(bool)
)
is_in_zone = np.all(is_in_zone, axis=1)
self.current_count = int(np.sum(is_in_zone))
return is_in_zone.astype(bool)
@@ -83,6 +105,7 @@ class PolygonZoneAnnotator:
font (int): The font type for the text on the polygon,
default is cv2.FONT_HERSHEY_SIMPLEX
center (Tuple[int, int]): The center of the polygon for text placement
display_in_zone_count (bool): Show the label of the zone or not. Default is True
"""
def __init__(
@@ -94,6 +117,7 @@ class PolygonZoneAnnotator:
text_scale: float = 0.5,
text_thickness: int = 1,
text_padding: int = 10,
display_in_zone_count: bool = True,
):
self.zone = zone
self.color = color
@@ -104,6 +128,7 @@ class PolygonZoneAnnotator:
self.text_padding = text_padding
self.font = cv2.FONT_HERSHEY_SIMPLEX
self.center = get_polygon_center(polygon=zone.polygon)
self.display_in_zone_count = display_in_zone_count
def annotate(self, scene: np.ndarray, label: Optional[str] = None) -> np.ndarray:
"""
@@ -124,16 +149,17 @@ class PolygonZoneAnnotator:
thickness=self.thickness,
)
annotated_frame = draw_text(
scene=annotated_frame,
text=str(self.zone.current_count) if label is None else label,
text_anchor=self.center,
background_color=self.color,
text_color=self.text_color,
text_scale=self.text_scale,
text_thickness=self.text_thickness,
text_padding=self.text_padding,
text_font=self.font,
)
if self.display_in_zone_count:
annotated_frame = draw_text(
scene=annotated_frame,
text=str(self.zone.current_count) if label is None else label,
text_anchor=self.center,
background_color=self.color,
text_color=self.text_color,
text_scale=self.text_scale,
text_thickness=self.text_thickness,
text_padding=self.text_padding,
text_font=self.font,
)
return annotated_frame
+5 -1
View File
@@ -115,4 +115,8 @@ class DetectionsSmoother:
if track is not None:
tracked_detections.append(track)
return Detections.merge(tracked_detections)
detections = Detections.merge(tracked_detections)
if len(detections) == 0:
detections.tracker_id = np.array([], dtype=int)
return detections
+51 -2
View File
@@ -59,8 +59,11 @@ def box_iou_batch(boxes_true: np.ndarray, boxes_detection: np.ndarray) -> np.nda
return area_inter / (area_true[:, None] + area_detection - area_inter)
def mask_iou_batch(masks_true: np.ndarray, masks_detection: np.ndarray) -> np.ndarray:
def _mask_iou_batch_split(
masks_true: np.ndarray, masks_detection: np.ndarray
) -> np.ndarray:
"""
Internal function.
Compute Intersection over Union (IoU) of two sets of masks -
`masks_true` and `masks_detection`.
@@ -74,9 +77,9 @@ def mask_iou_batch(masks_true: np.ndarray, masks_detection: np.ndarray) -> np.nd
intersection_area = np.logical_and(masks_true[:, None], masks_detection).sum(
axis=(2, 3)
)
masks_true_area = masks_true.sum(axis=(1, 2))
masks_detection_area = masks_detection.sum(axis=(1, 2))
union_area = masks_true_area[:, None] + masks_detection_area - intersection_area
return np.divide(
@@ -87,6 +90,52 @@ def mask_iou_batch(masks_true: np.ndarray, masks_detection: np.ndarray) -> np.nd
)
def mask_iou_batch(
masks_true: np.ndarray,
masks_detection: np.ndarray,
memory_limit: int = 1024 * 5,
) -> np.ndarray:
"""
Compute Intersection over Union (IoU) of two sets of masks -
`masks_true` and `masks_detection`.
Args:
masks_true (np.ndarray): 3D `np.ndarray` representing ground-truth masks.
masks_detection (np.ndarray): 3D `np.ndarray` representing detection masks.
memory_limit (int, optional): memory limit in MB, default is 1024 * 5 MB (5GB).
Returns:
np.ndarray: Pairwise IoU of masks from `masks_true` and `masks_detection`.
"""
memory = (
masks_true.shape[0]
* masks_true.shape[1]
* masks_true.shape[2]
* masks_detection.shape[0]
/ 1024
/ 1024
)
if memory <= memory_limit:
return _mask_iou_batch_split(masks_true, masks_detection)
ious = []
step = max(
memory_limit
* 1024
* 1024
// (
masks_detection.shape[0]
* masks_detection.shape[1]
* masks_detection.shape[2]
),
1,
)
for i in range(0, masks_true.shape[0], step):
ious.append(_mask_iou_batch_split(masks_true[i : i + step], masks_detection))
return np.vstack(ious)
def resize_masks(masks: np.ndarray, max_dimension: int = 640) -> np.ndarray:
"""
Resize all masks in the array to have a maximum dimension of max_dimension,
+46 -14
View File
@@ -6,6 +6,7 @@ from supervision.detection.core import Detections
from supervision.tracker.byte_tracker import matching
from supervision.tracker.byte_tracker.basetrack import BaseTrack, TrackState
from supervision.tracker.byte_tracker.kalman_filter import KalmanFilter
from supervision.utils.internal import deprecated_parameter
class STrack(BaseTrack):
@@ -172,26 +173,57 @@ class ByteTrack:
</video>
Parameters:
track_thresh (float, optional): Detection confidence threshold
for track activation.
track_buffer (int, optional): Number of frames to buffer when a track is lost.
match_thresh (float, optional): Threshold for matching tracks with detections.
track_activation_threshold (float, optional): Detection confidence threshold
for track activation. Increasing track_activation_threshold improves accuracy
and stability but might miss true detections. Decreasing it increases
completeness but risks introducing noise and instability.
lost_track_buffer (int, optional): Number of frames to buffer when a track is lost.
Increasing lost_track_buffer enhances occlusion handling, significantly
reducing the likelihood of track fragmentation or disappearance caused
by brief detection gaps.
minimum_matching_threshold (float, optional): Threshold for matching tracks with detections.
Increasing minimum_matching_threshold improves accuracy but risks fragmentation.
Decreasing it improves completeness but risks false positives and drift.
frame_rate (int, optional): The frame rate of the video.
""" # noqa: E501 // docs
@deprecated_parameter(
old_parameter="track_buffer",
new_parameter="lost_track_buffer",
map_function=lambda x: x,
warning_message="`{old_parameter}` in `{function_name}` is deprecated and will "
"be remove in `supervision-0.23.0`. Use '{new_parameter}' "
"instead.",
)
@deprecated_parameter(
old_parameter="track_thresh",
new_parameter="track_activation_threshold",
map_function=lambda x: x,
warning_message="`{old_parameter}` in `{function_name}` is deprecated and will "
"be remove in `supervision-0.23.0`. Use '{new_parameter}' "
"instead.",
)
@deprecated_parameter(
old_parameter="match_thresh",
new_parameter="minimum_matching_threshold",
map_function=lambda x: x,
warning_message="`{old_parameter}` in `{function_name}` is deprecated and will "
"be remove in `supervision-0.23.0`. Use '{new_parameter}' "
"instead.",
)
def __init__(
self,
track_thresh: float = 0.25,
track_buffer: int = 30,
match_thresh: float = 0.8,
track_activation_threshold: float = 0.25,
lost_track_buffer: int = 30,
minimum_matching_threshold: float = 0.8,
frame_rate: int = 30,
):
self.track_thresh = track_thresh
self.match_thresh = match_thresh
self.track_activation_threshold = track_activation_threshold
self.minimum_matching_threshold = minimum_matching_threshold
self.frame_id = 0
self.det_thresh = self.track_thresh + 0.1
self.max_time_lost = int(frame_rate / 30.0 * track_buffer)
self.det_thresh = self.track_activation_threshold + 0.1
self.max_time_lost = int(frame_rate / 30.0 * lost_track_buffer)
self.kalman_filter = KalmanFilter()
self.tracked_tracks: List[STrack] = []
@@ -295,9 +327,9 @@ class ByteTrack:
scores = tensors[:, 4]
bboxes = tensors[:, :4]
remain_inds = scores > self.track_thresh
remain_inds = scores > self.track_activation_threshold
inds_low = scores > 0.1
inds_high = scores < self.track_thresh
inds_high = scores < self.track_activation_threshold
inds_second = np.logical_and(inds_low, inds_high)
dets_second = bboxes[inds_second]
@@ -335,7 +367,7 @@ class ByteTrack:
dists = matching.fuse_score(dists, detections)
matches, u_track, u_detection = matching.linear_assignment(
dists, thresh=self.match_thresh
dists, thresh=self.minimum_matching_threshold
)
for itracked, idet in matches:
+100 -1
View File
@@ -1,5 +1,104 @@
import functools
import os
import warnings
from typing import Callable
class SupervisionWarnings(Warning):
"""Supervision warning category.
Set the deprecation warnings visibility for Supervision library.
You can set the environment variable SUPERVISON_DEPRECATION_WARNING to '0' to
disable the deprecation warnings.
"""
pass
def format_warning(msg, category, filename, lineno, line=None):
"""
Format a warning the same way as the default formatter, but also include the
category name in the output.
"""
return f"{category.__name__}: {msg}\n"
warnings.formatwarning = format_warning
if os.getenv("SUPERVISON_DEPRECATION_WARNING") == "0":
warnings.simplefilter("ignore", SupervisionWarnings)
else:
warnings.simplefilter("always", SupervisionWarnings)
def deprecated_parameter(
old_parameter: str,
new_parameter: str,
map_function: Callable = lambda x: x,
warning_message: str = "Warning: '{old_parameter}' in '{function_name}' is "
"deprecated: use '{new_parameter}' instead.",
**message_kwargs,
):
"""
A decorator to mark a function's parameter as deprecated and issue a warning when
used.
Parameters:
old_parameter (str): The name of the deprecated parameter.
new_parameter (str): The name of the parameter that should be used instead.
map_function (Callable, optional): A function used to map the value of the old
parameter to the new parameter. Defaults to the identity function.
warning_message (str, optional): The warning message to be displayed when the
deprecated parameter is used. Defaults to a generic warning message with
placeholders for the old parameter, new parameter, and function name.
**message_kwargs: Additional keyword arguments that can be used to customize
the warning message.
Returns:
Callable: A decorator function that can be applied to mark a function's
parameter as deprecated.
Examples:
```python
@deprecated_parameter(
old_parameter=<OLD_PARAMETER_NAME>,
new_parameter=<NEW_PARAMETER_NAME>
)
def example_function(<NEW_PARAMETER_NAME>):
pass
# call function using deprecated parameter
example_function(<OLD_PARAMETER_NAME>=<OLD_PARAMETER_VALUE>)
```
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if old_parameter in kwargs:
if args and hasattr(args[0], "__class__"):
class_name = args[0].__class__.__name__
function_name = f"{class_name}.{func.__name__}"
else:
function_name = func.__name__
warnings.warn(
message=warning_message.format(
function_name=function_name,
old_parameter=old_parameter,
new_parameter=new_parameter,
**message_kwargs,
),
category=SupervisionWarnings,
stacklevel=2,
)
kwargs[new_parameter] = map_function(kwargs.pop(old_parameter))
return func(*args, **kwargs)
return wrapper
return decorator
def deprecated(reason: str):
@@ -8,7 +107,7 @@ def deprecated(reason: str):
def wrapper(*args, **kwargs):
warnings.warn(
f"{func.__name__} is deprecated: {reason}",
category=DeprecationWarning,
category=SupervisionWarnings,
stacklevel=2,
)
return func(*args, **kwargs)
+19 -6
View File
@@ -2,17 +2,21 @@ from typing import List, Optional, Tuple
import cv2
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from supervision.annotators.base import ImageType
from supervision.annotators.utils import pillow_to_cv2
def plot_image(
image: np.ndarray, size: Tuple[int, int] = (12, 12), cmap: Optional[str] = "gray"
image: ImageType, size: Tuple[int, int] = (12, 12), cmap: Optional[str] = "gray"
) -> None:
"""
Plots image using matplotlib.
Args:
image (np.ndarray): The frame to be displayed.
image (ImageType): The frame to be displayed ImageType
is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`.
size (Tuple[int, int]): The size of the plot.
cmap (str): the colormap to use for single channel images.
@@ -27,6 +31,9 @@ def plot_image(
sv.plot_image(image=image, size=(16, 16))
```
"""
if isinstance(image, Image.Image):
image = pillow_to_cv2(image)
plt.figure(figsize=size)
if image.ndim == 2:
@@ -39,7 +46,7 @@ def plot_image(
def plot_images_grid(
images: List[np.ndarray],
images: List[ImageType],
grid_size: Tuple[int, int],
titles: Optional[List[str]] = None,
size: Tuple[int, int] = (12, 12),
@@ -49,7 +56,8 @@ def plot_images_grid(
Plots images in a grid using matplotlib.
Args:
images (List[np.ndarray]): A list of images as numpy arrays.
images (List[ImageType]): A list of images as ImageType
is a flexible type, accepting either `numpy.ndarray` or `PIL.Image.Image`.
grid_size (Tuple[int, int]): A tuple specifying the number
of rows and columns for the grid.
titles (Optional[List[str]]): A list of titles for each image.
@@ -65,9 +73,10 @@ def plot_images_grid(
```python
import cv2
import supervision as sv
from PIL import Image
image1 = cv2.imread("path/to/image1.jpg")
image2 = cv2.imread("path/to/image2.jpg")
image2 = Image.open("path/to/image2.jpg")
image3 = cv2.imread("path/to/image3.jpg")
images = [image1, image2, image3]
@@ -79,6 +88,10 @@ def plot_images_grid(
"""
nrows, ncols = grid_size
for idx, img in enumerate(images):
if isinstance(img, Image.Image):
images[idx] = pillow_to_cv2(img)
if len(images) > nrows * ncols:
raise ValueError(
"The number of images exceeds the grid size. Please increase the grid size"
+8 -8
View File
@@ -28,7 +28,7 @@ class VideoInfo:
```python
import supervision as sv
video_info = sv.VideoInfo.from_video_path(video_path='video.mp4')
video_info = sv.VideoInfo.from_video_path(video_path=<SOURCE_VIDEO_FILE>)
video_info
# VideoInfo(width=3840, height=2160, fps=25, total_frames=538)
@@ -75,14 +75,14 @@ class VideoSink:
```python
import supervision as sv
video_info = sv.VideoInfo.from_video_path('source.mp4')
frames_generator = sv.get_video_frames_generator('source.mp4')
video_info = sv.VideoInfo.from_video_path(<SOURCE_VIDEO_PATH>)
frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>)
with sv.VideoSink(target_path='target.mp4', video_info=video_info) as sink:
with sv.VideoSink(target_path=<TARGET_VIDEO_PATH>, video_info=video_info) as sink:
for frame in frames_generator:
sink.write_frame(frame=frame)
```
"""
""" # noqa: E501 // docs
def __init__(self, target_path: str, video_info: VideoInfo, codec: str = "mp4v"):
self.target_path = target_path
@@ -147,7 +147,7 @@ def get_video_frames_generator(
```python
import supervision as sv
for frame in sv.get_video_frames_generator(source_path='source_video.mp4'):
for frame in sv.get_video_frames_generator(source_path=<SOURCE_VIDEO_PATH>):
...
```
"""
@@ -191,8 +191,8 @@ def process_video(
...
process_video(
source_path='...',
target_path='...',
source_path=<SOURCE_VIDEO_PATH>,
target_path=<TARGET_VIDEO_PATH>,
callback=callback
)
```
+92
View File
@@ -0,0 +1,92 @@
from contextlib import ExitStack as DoesNotRaise
from test.test_utils import mock_detections
import numpy as np
import pytest
import supervision as sv
DETECTION_BOXES = np.array(
[
[35.0, 35.0, 65.0, 65.0],
[60.0, 60.0, 90.0, 90.0],
[85.0, 85.0, 115.0, 115.0],
[110.0, 110.0, 140.0, 140.0],
[135.0, 135.0, 165.0, 165.0],
[160.0, 160.0, 190.0, 190.0],
[185.0, 185.0, 215.0, 215.0],
[210.0, 210.0, 240.0, 240.0],
[235.0, 235.0, 265.0, 265.0],
],
dtype=np.float32,
)
DETECTIONS = mock_detections(
xyxy=DETECTION_BOXES, class_id=np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])
)
POLYGON = np.array([[100, 100], [200, 100], [200, 200], [100, 200]])
FRAME_RESOLUTION = (300, 300)
@pytest.mark.parametrize(
"detections, polygon_zone, expected_results, exception",
[
(
DETECTIONS,
sv.PolygonZone(
POLYGON,
FRAME_RESOLUTION,
triggering_anchors=(
sv.Position.TOP_LEFT,
sv.Position.TOP_RIGHT,
sv.Position.BOTTOM_LEFT,
sv.Position.BOTTOM_RIGHT,
),
),
np.array(
[False, False, False, True, True, True, False, False, False], dtype=bool
),
DoesNotRaise(),
), # Test all four corners
(
DETECTIONS,
sv.PolygonZone(
POLYGON,
FRAME_RESOLUTION,
),
np.array(
[False, False, True, True, True, True, False, False, False], dtype=bool
),
DoesNotRaise(),
), # Test default behaviour when no anchors are provided
(
DETECTIONS,
sv.PolygonZone(
POLYGON, FRAME_RESOLUTION, triggering_position=sv.Position.BOTTOM_CENTER
),
np.array(
[False, False, True, True, True, True, False, False, False], dtype=bool
),
DoesNotRaise(),
), # Test default behaviour with deprecated api.
(
sv.Detections.empty(),
sv.PolygonZone(
POLYGON,
FRAME_RESOLUTION,
),
np.array([], dtype=bool),
DoesNotRaise(),
), # Test empty detections
],
)
def test_polygon_zone_trigger(
detections: sv.Detections,
polygon_zone: sv.PolygonZone,
expected_results: np.ndarray,
exception: Exception,
) -> None:
with exception:
in_zone = polygon_zone.trigger(detections)
assert np.all(in_zone == expected_results)