Compare commits

...
295 Commits
Author SHA1 Message Date
Piotr Skalski 36ab9dcb8e Merge pull request #627 from roboflow/develop
`supervision-0.17.0` release
2023-12-06 15:50:31 +01:00
SkalskiP 01d6c5386a Update Supervision package to version 0.17.0
The package version has been updated from 0.17.0rc8 to 0.17.0. Alongside the version, the changelog has also been updated to reflect the newly introduced or modified features, improvements in existing features, and bug fixes.
2023-12-06 15:48:03 +01:00
SkalskiP 7a1863835b Refactor Detections function's docstrings in core.py 2023-12-06 15:26:04 +01:00
Piotr Skalski fb66e57103 Update README.md 2023-12-06 14:37:45 +01:00
SkalskiP b87e07a06b Bump version to 0.17.0rc8
The version of the supervision package in pyproject.toml has been updated from `0.17.0rc7` to `0.17.0rc8`.
2023-12-06 14:03:34 +01:00
Piotr Skalski ba79dba26e Merge pull request #652 from roboflow/feature/add_triangle_annotator
Add `TriangleAnnotator` to annotators
2023-12-06 14:01:42 +01:00
SkalskiP 721935144b Merge remote-tracking branch 'origin/feature/add_triangle_annotator' into feature/add_triangle_annotator 2023-12-06 13:59:14 +01:00
SkalskiP 26ad007b7c Add TriangleAnnotator example to documentation 2023-12-06 13:59:05 +01:00
pre-commit-ci[bot] c46ff15143 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-06 12:52:06 +00:00
SkalskiP f73829e941 The function was initially determining the center point of the triangle, which did not align with the desired annotation style. The changes now ensure that 'xy' refers to the coordinate of the triangle's tip instead of its center. 2023-12-06 13:51:01 +01:00
pre-commit-ci[bot] bf5d8ac29c fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-06 12:46:12 +00:00
SkalskiP 84713239ee Adjusted the default position value in the TriangleAnnotator class. 2023-12-06 13:45:56 +01:00
pre-commit-ci[bot] 8d9228f7fd fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-06 12:43:56 +00:00
SkalskiP 4400ae05eb Merge remote-tracking branch 'origin/feature/add_triangle_annotator' into feature/add_triangle_annotator
# Conflicts:
#	supervision/annotators/core.py
2023-12-06 13:43:37 +01:00
SkalskiP 366d39db48 Refactor vertices calculation in TriangleAnnotator 2023-12-06 13:42:52 +01:00
pre-commit-ci[bot] a618b7c369 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-06 12:34:55 +00:00
SkalskiP f94a8cb9a1 Add TriangleAnnotator to annotators
Added the ability to draw triangle markers on an image based on the provided detections with the TriangleAnnotator class. This is useful when needing to specifically mark or highlight certain areas of an image. The user can now specify both the color of the annotation and the metrics of the triangle such as base and height, as well as its position.
2023-12-06 13:32:48 +01:00
Piotr Skalski 186727243f Merge pull request #511 from abhishek7kalra/traceannotator
Fixed TraceAnnotator to respect the postion argument.
2023-12-06 13:16:50 +01:00
pre-commit-ci[bot] 7ea8e75a78 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-06 11:53:45 +00:00
SkalskiP 27979cf756 Simpler fix with self.trace = Trace(max_size=trace_length, anchor=position) 2023-12-06 12:50:46 +01:00
Piotr Skalski a8c1431392 Merge pull request #651 from roboflow/feature/scale_boxes_utility
Add `scale_boxes` function to detection utils
2023-12-06 12:37:00 +01:00
SkalskiP 58c8620a6f Add examples to move_boxes and scale_boxes functions 2023-12-06 12:32:59 +01:00
pre-commit-ci[bot] 9468f00997 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-06 11:23:31 +00:00
SkalskiP 55f5f6a97a The update introduces two new functions, move_boxes and scale_boxes, to the detection utilities in the supervision package. 2023-12-06 12:23:15 +01:00
pre-commit-ci[bot] a530b2ba5e fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-06 11:20:43 +00:00
SkalskiP 7cbf16be8a Add scale_boxes function to detection utils
Added a new function scale_boxes to the detection utilities in order to scale the dimensions of bounding boxes. This function accepts bounding boxes and a scaling factor as input and returns the scaled bounding boxes. It can enlarge or shrink the input bounding boxes based on the value of the passed factor. The function was also documented in the utils.md file and necessary tests were added to assure its correctness.
2023-12-06 12:16:22 +01:00
Piotr Skalski a112292ed0 Merge pull request #648 from roboflow/collab-fix-v2
fix(versions): 🐞 min numpy version changed to 1.21.2
2023-12-05 14:30:55 +01:00
Onuralp SEZER a64f3ff178 Merge pull request #624 from roboflow/dependabot/pip/wheel-0.42.0
⬆️ Bump wheel from 0.41.3 to 0.42.0
2023-12-05 16:28:46 +03:00
Piotr Skalski 07fc5609da Merge pull request #571 from roboflow/add-azure-analyze-image
Add `from_azure_analyze_image` data loader
2023-12-05 14:00:53 +01:00
SkalskiP 39117f19c4 Merge remote-tracking branch 'origin/add-azure-analyze-image' into add-azure-analyze-image 2023-12-05 13:57:44 +01:00
SkalskiP cb5e9c0df0 Added error handling in Detections.from_azure_analyze_image method 2023-12-05 13:57:27 +01:00
pre-commit-ci[bot] 38b87d6098 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-05 12:46:33 +00:00
SkalskiP a31f964947 Revise Detections.from_azure_analyze_image method for class mapping flexibility 2023-12-05 13:46:15 +01:00
dependabot[bot] 38297f85a5 ⬆️ Bump wheel from 0.41.3 to 0.42.0
Bumps [wheel](https://github.com/pypa/wheel) from 0.41.3 to 0.42.0.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.41.3...0.42.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-05 12:44:47 +00:00
Onuralp SEZER 5cf91676f6 Merge pull request #644 from roboflow/dependabot/pip/ruff-0.1.7
⬆️ Bump ruff from 0.1.6 to 0.1.7
2023-12-05 15:32:23 +03:00
Onuralp SEZER c3c934f8c1 fix(versions): 🐞 min numpy version changed to 1.21.2
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-12-05 15:03:16 +03:00
SkalskiP f46326b7e4 Merge branch 'develop' into add-azure-analyze-image 2023-12-05 13:02:10 +01:00
Piotr Skalski 679fee9f16 Merge pull request #646 from roboflow/rename-boxmask-annotator
Rename `BoxMaskAnnotator` to `ColorAnnotator`
2023-12-05 12:54:49 +01:00
SkalskiP 4774ace3c2 Merge branch 'develop' into rename-boxmask-annotator 2023-12-05 12:47:48 +01:00
Piotr Skalski 2e7ecdd418 Merge pull request #647 from roboflow/collab-min-max-version-fix
fix(format): 🐞 removal of numpy,matplotlib,pillow max versions for flexible to collab updates
2023-12-05 12:46:18 +01:00
Onuralp SEZER 918970e7d6 fix(format): 🐞 removal of numpy,matplotlib,pillow max versions for flexible to collab updates
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-12-05 14:41:47 +03:00
SkalskiP 87979384ed Update project version in pyproject.toml file
The project version in the pyproject.toml file has been updated from 0.17.0rc6 to 0.17.0rc7.
2023-12-05 12:14:28 +01:00
Piotr Skalski 83603e3677 Merge pull request #633 from roboflow/add-piexlate-annotator
Add `PixelateAnnotator`
2023-12-05 12:05:39 +01:00
pre-commit-ci[bot] 566a9296d0 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-05 11:04:16 +00:00
SkalskiP 9612fe7849 Refactor PixelateAnnotator and update docs 2023-12-05 12:03:59 +01:00
James Gallagher 7f2b62a5ce show transparent image 2023-12-05 10:42:31 +00:00
James Gallagher 9c10308abc change heading 2023-12-05 10:42:05 +00:00
James Gallagher d53181bb97 rename variable 2023-12-05 10:41:20 +00:00
pre-commit-ci[bot] 9d836faa8a fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-05 10:39:27 +00:00
James Gallagher c46e0f5c97 rename BoxMaskAnnotator to ColorAnnotator 2023-12-05 10:38:32 +00:00
dependabot[bot] c322cf8001 ⬆️ Bump ruff from 0.1.6 to 0.1.7
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.6 to 0.1.7.
- [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.1.6...v0.1.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-05 00:29:12 +00:00
Piotr Skalski b69eea47a9 Update 🔥 quick start section in README.md 2023-12-04 21:37:30 +01:00
Piotr Skalski fe9b422185 Update 🔥 quick start section in README.md 2023-12-04 21:28:01 +01:00
Piotr Skalski d6fd1b0644 Merge pull request #643 from roboflow/og-images
Add open graph images to documentation.
2023-12-04 18:49:22 +01:00
James Gallagher 1ef1622126 add lenny 2023-12-04 17:03:05 +00:00
James Gallagher e45e1e277b resubmit mkdocs pr 2023-12-04 17:02:44 +00:00
Piotr Skalski b1ac5bc876 Merge pull request #566 from roboflow/min-ver-settings
build(deps): 🚀 min and max supervision package requirements are added
2023-12-04 18:02:04 +01:00
Onuralp SEZER 178d91eaa0 Merge pull request #639 from roboflow/add-open-graph-images
Add mkdocs-material[imaging] dependency
2023-12-04 19:31:26 +03:00
Onuralp SEZER 726ad1dbb1 Merge branch 'develop' into min-ver-settings 2023-12-04 19:23:20 +03:00
SkalskiP e08e4ee389 Rename calculate_dynamic_font_scale to calculate_dynamic_text_scale 2023-12-04 17:05:49 +01:00
SkalskiP 23a58ef99e Rename calculate_dynamic_font_scale to calculate_dynamic_text_scale 2023-12-04 17:04:07 +01:00
SkalskiP bd4208ce84 Update project version to 0.17.0rc5
The project version in the `pyproject.toml` file has been updated to `0.17.0rc5` from `0.17.0rc4`.
2023-12-04 16:48:04 +01:00
Piotr Skalski dd16f917d5 Merge pull request #637 from roboflow/feature/dynamic_font_scale_and_line_thicness_calculation
dynamic font scale and line thickness calculation based on image resolution
2023-12-04 16:36:48 +01:00
Piotr Skalski 31d60734bf Merge pull request #638 from roboflow/revert-636-add-open-graph-images
Revert "Add open graph images"
2023-12-04 16:26:14 +01:00
Piotr Skalski 4483970638 Revert "Add open graph images" 2023-12-04 16:22:38 +01:00
James Gallagher 1710021ece add mkdocs-material[imaging] dependency 2023-12-04 15:22:23 +00:00
Piotr Skalski 144df44ccc Merge pull request #636 from roboflow/add-open-graph-images
Add open graph images
2023-12-04 16:16:37 +01:00
James Gallagher 92761752a0 respond to feedback 2023-12-04 15:09:23 +00:00
James Gallagher b047e061e7 respond to feedback 2023-12-04 15:08:51 +00:00
pre-commit-ci[bot] 72497f3f85 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-04 14:57:58 +00:00
SkalskiP 478c3adfe2 Merge remote-tracking branch 'origin/feature/dynamic_font_scale_and_line_thicness_calculation' into feature/dynamic_font_scale_and_line_thicness_calculation 2023-12-04 15:57:43 +01:00
SkalskiP 81d0876838 Added two new utility functions in the supervision module for dynamic font-size scaling and line thickness calculations. 2023-12-04 15:57:27 +01:00
Piotr Skalski 66720c58fd Merge pull request #635 from roboflow/add-code-snippet-copy
Add code snippet copy feature to docs
2023-12-04 15:30:26 +01:00
pre-commit-ci[bot] b16e479a14 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-04 14:29:14 +00:00
SkalskiP 9f5773aa70 This commit adds descriptions for two new utility functions: calculate_dynamic_font_scale and calculate_dynamic_line_thickness. 2023-12-04 15:27:01 +01:00
SkalskiP d2d590834e Added dynamic font scale and line thickness calculations in utils.py. 2023-12-04 15:18:55 +01:00
pre-commit-ci[bot] f046940bb5 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-04 14:08:00 +00:00
James Gallagher e7e542d160 add required import 2023-12-04 14:07:25 +00:00
James Gallagher dd19c4e185 work on annotator 2023-12-04 14:05:49 +00:00
James Gallagher dfb703219e work on annotator 2023-12-04 14:04:59 +00:00
James Gallagher ec8f10d6a8 add open graph images 2023-12-04 13:35:27 +00:00
capjamesg 242ac0cd06 add code snippet copy feature to docs 2023-12-04 13:20:13 +00:00
pre-commit-ci[bot] 8946d44dcb fix(pre_commit): 🎨 auto format pre-commit hooks 2023-12-04 13:16:58 +00:00
capjamesg 718f1b077d add pixelate annotator 2023-12-04 13:15:45 +00:00
Onuralp SEZER 93eb48c2a0 Merge pull request #629 from roboflow/dependabot/pip/cryptography-41.0.6
⬆️ Bump cryptography from 41.0.4 to 41.0.6
2023-12-01 23:33:09 +03:00
dependabot[bot] f6265ebbda ⬆️ Bump cryptography from 41.0.4 to 41.0.6
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.4 to 41.0.6.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.4...41.0.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-01 20:25:38 +00:00
Piotr Skalski b94e2796bd Merge pull request #631 from roboflow/dependabot/github_actions/actions/first-interaction-1.3.0 2023-11-30 11:44:28 +01:00
dependabot[bot] e77d06d817 ⬆️ Bump actions/first-interaction from 1.2.0 to 1.3.0
Bumps [actions/first-interaction](https://github.com/actions/first-interaction) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/actions/first-interaction/releases)
- [Commits](https://github.com/actions/first-interaction/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: actions/first-interaction
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-30 00:38:11 +00:00
Piotr Skalski b63457e5fa Merge pull request #478 from roboflow/add-classification-annotator
Add `sv.Classifications.from_clip` data loader
2023-11-27 15:33:29 +01:00
SkalskiP 575a7a301d Refactored the code in core.py to optimize softmax calculation and improve the related docstrings. 2023-11-27 15:27:39 +01:00
James Gallagher fa8f31931c fix dict data type 2023-11-27 14:16:52 +00:00
James Gallagher b4b332a0e2 fix dict data type 2023-11-27 14:14:56 +00:00
SkalskiP 02502baab3 Update docstrings and softmax calculation in core.py 2023-11-27 15:04:06 +01:00
SkalskiP 2aebe13583 Merge branch 'develop' into add-classification-annotator 2023-11-27 14:50:15 +01:00
James Gallagher 6ed04252d6 fix merge conflict 2023-11-27 13:45:16 +00:00
pre-commit-ci[bot] 491209d7bd fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-27 13:45:06 +00:00
James Gallagher 444f8d01c1 remove classification annotator 2023-11-27 13:44:52 +00:00
James Gallagher f91fad5600 fix merge conflict 2023-11-27 13:42:31 +00:00
Piotr Skalski 1589d8fd43 Merge pull request #572 from roboflow/add-timm-classification-loader
Add timm data loader for `sv.Classifications`
2023-11-27 13:05:58 +01:00
SkalskiP 1d66840cad Optimize imports in core.py
Adjustments have been made to the import statements in the 'core.py' file of the 'classification' module.
2023-11-27 12:58:34 +01:00
SkalskiP 05602cd2a0 Refactor code for clarity and better variable use
The variable names and usage within the 'ultralytics' and 'timm' functions were updated for improved code readability. The docstrings were also refined to better explain the function parameters. Instances where YOLO was redundantly called were also eliminated.
2023-11-27 12:51:05 +01:00
James fc9acc456b Merge branch 'develop' into add-classification-annotator 2023-11-27 11:18:40 +00:00
James Gallagher b6c85a3f4b fix precommit issue 2023-11-27 11:15:55 +00:00
James Gallagher ce92069ba6 fix precommit 2023-11-27 10:57:00 +00:00
Piotr Skalski 2dcf2cc2ae Merge pull request #621 from kim-jeonghyun/fix_typo_from_mmdetection
fix: 📝 typo in from_mmdetection docstring
2023-11-26 20:41:44 +01:00
kim-jeonghyun 619ec018bc fix: 📝 typo in from_mmdetection docstring 2023-11-26 20:33:37 +09:00
SkalskiP 5333eb2684 Update project version in pyproject.toml
The version of the project has been updated from "0.17.0rc3" to "0.17.0rc4".
2023-11-26 11:33:56 +01:00
Piotr Skalski d5d70052bb Merge pull request #620 from roboflow/feature/add_color_as_hex
Add 'as_hex' method and corresponding test to `Color` class.
2023-11-26 11:29:25 +01:00
pre-commit-ci[bot] 242ac5f7db fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-26 10:27:43 +00:00
SkalskiP e6f0ae8514 Add 'as_hex' method and corresponding test to Color class. 2023-11-26 11:25:59 +01:00
Onuralp SEZER 10c44b0143 Merge pull request #613 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2023-11-21 18:06:51 +03:00
Onuralp SEZER 2a3f592090 Merge pull request #608 from roboflow/dependabot/pip/ruff-0.1.6
⬆️ Bump ruff from 0.1.5 to 0.1.6
2023-11-21 15:18:54 +03:00
pre-commit-ci[bot] 7941527a75 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.1.5 → v0.1.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.5...v0.1.6)
2023-11-20 17:36:14 +00:00
Piotr Skalski 42661a0563 Merge pull request #612 from karanjakhar/fixing-typos
fixing typo TRACE -> TRACK
2023-11-20 12:25:51 +01:00
SkalskiP 32077eb11d Bump version in pyproject.toml
The version in the pyproject.toml file has been updated from 0.17.0rc2 to 0.17.0rc3.
2023-11-20 12:21:37 +01:00
karanjakhar d20083de85 fixing typo TRACE -> TRACK 2023-11-20 15:32:18 +05:30
dependabot[bot] 564f1b1026 ⬆️ Bump ruff from 0.1.5 to 0.1.6
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.5 to 0.1.6.
- [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.1.5...v0.1.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-20 01:09:24 +00:00
Piotr Skalski 145313ab8f Merge pull request #606 from xenteros/feature/Make_sv.MaskAnnotator_as_fast_as_annotators_in_popular_detection_frameworks_#472
Feature/make sv.mask annotator as fast as annotators in popular detection frameworks #472
2023-11-17 17:20:22 +01:00
xenteros 1267cf7fb0 Reformatted Code with pre-commit 2023-11-16 22:34:52 +01:00
xenteros c2101db5d2 Optimize sv.MaskAnnotator by reducing number of calls to cv2.addWeighted
* Combined all colored masks before applying them to the scene
* Made sure that returned ndarray is np.uint8 for video writer simplicity
2023-11-16 22:27:32 +01:00
Piotr Skalski fe4657f0d0 Merge pull request #605 from roboflow/feature/add_center_of_mass_text_positioning
Add centroid calculation for binary masks
2023-11-16 16:26:57 +01:00
SkalskiP 6c756c411b Add calculate_masks_centroids function import in __init__.py 2023-11-16 16:25:48 +01:00
SkalskiP 0725d5a1a9 Cast get_anchors_coordinates return to integer. 2023-11-16 15:50:37 +01:00
SkalskiP fa3b43f20a Merge remote-tracking branch 'origin/feature/add_center_of_mass_text_positioning' into feature/add_center_of_mass_text_positioning 2023-11-16 15:37:17 +01:00
SkalskiP 5e091396f2 Refactor center_coordinates conversion to tuple 2023-11-16 15:36:36 +01:00
pre-commit-ci[bot] 66448ea862 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-16 14:33:57 +00:00
SkalskiP b33d68da00 Merge remote-tracking branch 'origin/feature/add_center_of_mass_text_positioning' into feature/add_center_of_mass_text_positioning
# Conflicts:
#	supervision/annotators/core.py
2023-11-16 15:31:56 +01:00
SkalskiP 6956dad17d Swap enumeration arguments in loop 2023-11-16 15:30:03 +01:00
pre-commit-ci[bot] b92ffeff82 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-16 14:24:19 +00:00
SkalskiP 7750856c18 Fix method names and improve code formatting
Renamed methods to improve clarity. `get_anchor_coordinates` changed to `get_anchors_coordinates` and `calculate_centroids` changed to `calculate_masks_centroids`. Indentation for method arguments was adjusted in `core.py` and other files for better readability. Functionality remains the same, these changes are meant to improve code maintainability and readability.
2023-11-16 15:23:55 +01:00
pre-commit-ci[bot] 72ab46687f fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-16 12:59:16 +00:00
SkalskiP 50e561a4fb Add centroid calculation for binary masks
Added `calculate_centroids` function to compute center of mass for binary mask representations. Method added to `utils.py` and method import added to `core.py`. `Position` enumeration updated with `CENTER_OF_MASS` constant. Test function is added with test cases covering different mask scenarios. Update allows for masks to carry center of mass information too, useful in object detection.
2023-11-16 13:52:32 +01:00
Piotr Skalski bb7695a774 Merge pull request #603 from roboflow/gh-pages-permission-fix
fix: 🐞 gh-pages permission fix for deployment
2023-11-15 20:50:58 +01:00
Onuralp SEZER 95006dca14 fix: 🐞 gh-pages permission fix for deployment 2023-11-15 22:11:32 +03:00
Onuralp SEZER b3dec1a734 Merge branch 'develop' into min-ver-settings 2023-11-15 21:39:37 +03:00
Piotr Skalski 5456c666c7 Merge pull request #602 from roboflow/feature/adding-polygon-annotator
Add PolygonAnnotator and update documentation
2023-11-15 17:54:11 +01:00
SkalskiP 2ed4e16ab5 Added a visual and code example for PolygonAnnotator in supervision/annotators/core.py and docs/annotators.md. 2023-11-15 17:49:17 +01:00
SkalskiP c1beb0f5fd Add PolygonAnnotator to supervision annotators 2023-11-15 17:30:06 +01:00
pre-commit-ci[bot] 777e8d3e5b fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-15 16:11:11 +00:00
SkalskiP e40532cf3e Add PolygonAnnotator and update documentation
Implemented the PolygonAnnotator class in the core.py file under the supervision/annotators directory to support drawing polygons over detected objects. This was done by dividing the masks into multiple polygons and drawing them on the image.
2023-11-15 17:09:27 +01:00
Onuralp SEZER 550e86bc6d Merge pull request #598 from roboflow/dependabot/pip/mkdocstrings-0.24.0
⬆️ Bump mkdocstrings from 0.23.0 to 0.24.0
2023-11-15 17:07:13 +03:00
Onuralp SEZER 6af17b235f Merge pull request #589 from roboflow/dependabot/pip/mypy-1.7.0
⬆️ Bump mypy from 1.6.1 to 1.7.0
2023-11-15 17:06:48 +03:00
Onuralp SEZER de867bb166 Merge pull request #593 from roboflow/dependabot/github_actions/actions/github-script-7
⬆️ Bump actions/github-script from 6 to 7
2023-11-15 17:06:25 +03:00
Onuralp SEZER ca84d3129c Merge pull request #592 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2023-11-15 17:06:03 +03:00
Onuralp SEZER 9c9bc77e12 Merge pull request #600 from roboflow/fix/incorrectly-autoformatted-case-test
Updated tests to reflect changes in file content handling
2023-11-15 17:05:11 +03:00
Onuralp SEZER b9573605c7 fix(test): 🧪 pre-commit's whitespace exclude and test case fix for whiespace
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-11-15 17:01:57 +03:00
pre-commit-ci[bot] 8025b468a2 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-15 13:42:25 +00:00
SkalskiP d3fb4ad932 Ignoring W291 for test_file.py 2023-11-15 14:41:38 +01:00
pre-commit-ci[bot] fcfb57612f fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-15 13:37:51 +00:00
SkalskiP c28aa5aebd Updated tests to reflect changes in file content handling 2023-11-15 14:37:02 +01:00
Piotr Skalski 109d048a38 Merge pull request #584 from SummitStudiosDev/develop
Ignore Empty Newlines in Yolo Label File
2023-11-15 14:32:34 +01:00
dependabot[bot] 6ad1f701dd ⬆️ Bump mkdocstrings from 0.23.0 to 0.24.0
Bumps [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) from 0.23.0 to 0.24.0.
- [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.23.0...0.24.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-15 00:32:33 +00:00
dependabot[bot] 7f081f4314 ⬆️ Bump actions/github-script from 6 to 7
Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-14 00:36:36 +00:00
pre-commit-ci[bot] dd39360221 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/psf/black: 23.10.1 → 23.11.0](https://github.com/psf/black/compare/23.10.1...23.11.0)
- [github.com/astral-sh/ruff-pre-commit: v0.1.4 → v0.1.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.4...v0.1.5)
2023-11-13 17:46:54 +00:00
dependabot[bot] 7de7281e0e ⬆️ Bump mypy from 1.6.1 to 1.7.0
Bumps [mypy](https://github.com/python/mypy) from 1.6.1 to 1.7.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.6.1...v1.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 00:53:30 +00:00
Onuralp SEZER e8f0ceab71 fix: 🐞 test fix
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-11-10 22:07:47 +03:00
Onuralp SEZER 94a95110ce fix: 🐞 pre-commit fix and ignore removed (not needed)
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-11-10 21:47:40 +03:00
pre-commit-ci[bot] 08a48a4f5d fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-10 18:26:26 +00:00
SkalskiP 95f4b5c0b8 Add linting rule exceptions for test_file.py
Added linting rule exceptions for 'test/utils/test_file.py' in 'pyproject.toml'. Specifically, the 'W291' error which checks for trailing whitespace is ignored for this test file. This is necessary to test whether 'read_txt_file' function in 'test_utils.py' correctly ignores trailing whitespaces in varies test scenarios.
2023-11-10 10:25:59 -08:00
pre-commit-ci[bot] 6211139201 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-10 18:15:39 +00:00
SkalskiP e416ef4c0e Refactor import paths and improve text file reading
Refactored import paths for test utility methods across multiple test files to align with a recent package restructure. Enriched 'read_txt_file' functionality in 'file.py' allowing to optionally skip empty lines, enhancing flexibility for various use-cases. Added tests for the new 'read_txt_file' behavior in a new 'test_file.py'. Renamed 'utils.py' in test package to 'test_utils.py' for better differentiation from the util package in the source code.
2023-11-10 10:15:08 -08:00
pre-commit-ci[bot] 1dce43747f fix(pre_commit): 🎨 auto format pre-commit hooks 2023-11-10 04:41:51 +00:00
Cody Chen f9ead5543b Ignore empty newlines in yolo label file 2023-11-09 20:24:11 -08:00
Onuralp SEZER 5d19e246a4 Merge pull request #583 from roboflow/dependabot/pip/ruff-0.1.5
⬆️ Bump ruff from 0.1.4 to 0.1.5
2023-11-09 11:33:03 +03:00
Onuralp SEZER 052a9d33bb Merge pull request #582 from roboflow/dependabot/pip/black-23.11.0
⬆️ Bump black from 23.10.1 to 23.11.0
2023-11-09 11:32:45 +03:00
dependabot[bot] ed41153c19 ⬆️ Bump ruff from 0.1.4 to 0.1.5
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.4 to 0.1.5.
- [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.1.4...v0.1.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-09 00:48:59 +00:00
dependabot[bot] b89487d8e8 ⬆️ Bump black from 23.10.1 to 23.11.0
Bumps [black](https://github.com/psf/black) from 23.10.1 to 23.11.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.10.1...23.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-09 00:46:29 +00:00
Onuralp SEZER c8f557af0c Merge pull request #578 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2023-11-06 21:19:40 +03:00
pre-commit-ci[bot] 7946f54b95 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.1.3 → v0.1.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.3...v0.1.4)
2023-11-06 17:37:29 +00:00
Onuralp SEZER eeae6dafc0 Merge pull request #577 from roboflow/dependabot/pip/ruff-0.1.4
⬆️ Bump ruff from 0.1.3 to 0.1.4
2023-11-06 18:41:42 +03:00
Onuralp SEZER d07e6a3ed2 Merge pull request #576 from roboflow/dependabot/pip/mkdocs-material-9.4.8
⬆️ Bump mkdocs-material from 9.4.7 to 9.4.8
2023-11-06 18:41:15 +03:00
dependabot[bot] 06945856a3 ⬆️ Bump ruff from 0.1.3 to 0.1.4
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.3 to 0.1.4.
- [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.1.3...v0.1.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 00:57:31 +00:00
dependabot[bot] 899d88676b ⬆️ Bump mkdocs-material from 9.4.7 to 9.4.8
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.4.7 to 9.4.8.
- [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.4.7...9.4.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 00:54:42 +00:00
James Gallagher 82ed322fba add timm data loader 2023-11-03 18:25:09 +00:00
James Gallagher c438b16e74 update example 2023-11-03 16:11:16 +00:00
James Gallagher 3490c3e670 add azure data loader 2023-11-03 15:59:53 +00:00
Onuralp SEZER 583ad5f6e2 ci: 👷 ci job are renamed
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-11-03 14:11:12 +03:00
Piotr Skalski 26eac2cdc7 Merge pull request #565 from roboflow/hb-removal-readme
docs: 🚀 hacktoberfest 2023 finished.
2023-11-03 11:51:46 +01:00
Onuralp SEZER 9a0f35fcf9 ci: 👷 python3.8 and minimum version package CI added
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-11-02 22:19:35 +03:00
Onuralp SEZER 7a7b50eb12 build(deps): 🚀 min and max supervision package reqs are added
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-11-02 22:17:27 +03:00
Onuralp SEZER ad458cf705 docs: 🚀 hacktoberfest 2023 finished.
Thank you all who participate to hacktoberfest to make supervision awesome ! 🎉 🎉 🎉 🎉
2023-11-02 20:38:17 +03:00
Onuralp SEZER 9f3d688bab Merge pull request #560 from roboflow/dependabot/pip/mypy-1.6.1
⬆️ Bump mypy from 1.4.1 to 1.6.1
2023-11-01 18:34:00 +03:00
Onuralp SEZER 190bfbf0d0 Merge pull request #559 from roboflow/dependabot/pip/mkdocs-material-9.4.7
⬆️ Bump mkdocs-material from 9.4.6 to 9.4.7
2023-11-01 18:33:37 +03:00
dependabot[bot] f9b8709568 ⬆️ Bump mypy from 1.4.1 to 1.6.1
Bumps [mypy](https://github.com/python/mypy) from 1.4.1 to 1.6.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.4.1...v1.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 00:37:17 +00:00
dependabot[bot] 8d1e091a3b ⬆️ Bump mkdocs-material from 9.4.6 to 9.4.7
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.4.6 to 9.4.7.
- [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.4.6...9.4.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 00:35:42 +00:00
Piotr Skalski 92592c8edc Merge pull request #555 from fdloopes/540-bug-blur-annotator
fix: #540 bug blur annotator
2023-10-31 18:25:44 +01:00
pre-commit-ci[bot] e6a5c514f8 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-31 17:05:11 +00:00
SkalskiP ce7e3a1de4 Refactor clip_boxes function and enhance detections processing
Refactored the `clip_boxes` function for clarity by renaming arguments from `boxes_xyxy` and `frame_resolution_wh` to `xyxy` and `resolution_wh`, respectively. These change makes the function arguments more intuitive and improves code readability.

The processing of detections in `supervision/annotators/core.py` has been updated to include clipping of detection boxes to the image bounds before processing. This prevents errors and ensures detections beyond the image dimensions are handled correctly. Adjustments were also made in the test cases and in `polygon_zone.py` to match the updated `clip_boxes` function.
2023-10-31 18:04:13 +01:00
Piotr Skalski 4cb19e6618 Merge pull request #558 from roboflow/fix/kapa-roboflow-logo
Update init_kapa_widget.js
2023-10-31 17:32:31 +01:00
Piotr Skalski 6e039d7ebd Update init_kapa_widget.js 2023-10-31 17:30:02 +01:00
Piotr Skalski c100c8019a Merge pull request #552 from roboflow/add-docs-bot
Add Kapa documentation bot to supervision docs
2023-10-31 17:23:49 +01:00
Onuralp SEZER e3e30e305a Merge pull request #547 from roboflow/dependabot/pip/ruff-0.1.3
⬆️ Bump ruff from 0.1.2 to 0.1.3
2023-10-31 18:54:48 +03:00
dependabot[bot] 4a5d850f28 ⬆️ Bump ruff from 0.1.2 to 0.1.3
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.2 to 0.1.3.
- [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.1.2...v0.1.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 15:53:12 +00:00
Onuralp SEZER 092771d9a1 Merge pull request #545 from roboflow/dependabot/pip/flake8-6.1.0
⬆️ Bump flake8 from 6.0.0 to 6.1.0
2023-10-31 18:50:19 +03:00
Onuralp SEZER 321dc054df Merge pull request #546 from roboflow/dependabot/pip/notebook-7.0.6
⬆️ Bump notebook from 6.5.4 to 7.0.6
2023-10-31 18:49:30 +03:00
dependabot[bot] ec9aae686b ⬆️ Bump notebook from 6.5.4 to 7.0.6
Bumps [notebook](https://github.com/jupyter/notebook) from 6.5.4 to 7.0.6.
- [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/v6.5.4...@jupyter-notebook/tree@7.0.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 15:48:33 +00:00
Onuralp SEZER 7c2e9842e8 Merge pull request #543 from roboflow/dependabot/pip/pillow-10.1.0
⬆️ Bump pillow from 10.0.1 to 10.1.0
2023-10-31 18:47:58 +03:00
Onuralp SEZER 4d3820ba73 Merge pull request #554 from roboflow/dependabot/pip/wheel-0.41.3
⬆️ Bump wheel from 0.40.0 to 0.41.3
2023-10-31 18:46:45 +03:00
fdloopes 8b88f1f415 Add space after comma, following pre-commit pattern 2023-10-31 11:50:37 -03:00
Onuralp SEZER 37951b3617 Merge pull request #553 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2023-10-31 14:06:44 +03:00
dependabot[bot] 98fa8339c8 ⬆️ Bump wheel from 0.40.0 to 0.41.3
Bumps [wheel](https://github.com/pypa/wheel) from 0.40.0 to 0.41.3.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.40.0...0.41.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 01:05:37 +00:00
pre-commit-ci[bot] 030359cb44 chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/psf/black: 23.10.0 → 23.10.1](https://github.com/psf/black/compare/23.10.0...23.10.1)
- [github.com/astral-sh/ruff-pre-commit: v0.1.1 → v0.1.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.1...v0.1.3)
2023-10-30 17:39:35 +00:00
pre-commit-ci[bot] 9f265b4833 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-30 15:15:15 +00:00
James Gallagher c036aa9bd6 add kapa bot 2023-10-30 15:13:33 +00:00
fdloopes 7f69f6a168 Add np.maximum when retrieving detections coordinates within the BlurAnnotator.annotate() method. 2023-10-30 10:26:09 -03:00
Piotr Skalski d76dd771d7 Merge pull request #462 from Rajarshi-Misra/develop
Builds: Create "How to: track objects" docs page #442
2023-10-28 01:14:34 +02:00
pre-commit-ci[bot] 21fe102bbd fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-27 23:12:26 +00:00
SkalskiP 769f97cd7d Update object tracking documentation
Revise the contents of the 'How to Track Objects' documentation covering the use of supervision for object tracking in video analysis. The revision offers a more detailed guide, including running inference, tracking objects, annotating videos with unique tracking IDs, and annotating videos with traces. The new guide provides a structured walkthrough and tutorial on using Supervision's functionalities, aimed at helping users to annotate videos more effectively and understand the movement patterns and interactions of objects in the videos.
2023-10-28 01:12:09 +02:00
Onuralp SEZER 2de3e171f3 Merge pull request #542 from roboflow/dependabot/pip/pytest-7.4.3
⬆️ Bump pytest from 7.4.2 to 7.4.3
2023-10-26 07:20:56 +03:00
Onuralp SEZER 6a4bfcf094 Merge pull request #541 from roboflow/dependabot/pip/black-23.10.1
⬆️ Bump black from 23.7.0 to 23.10.1
2023-10-26 07:20:36 +03:00
dependabot[bot] 82e35479e7 ⬆️ Bump flake8 from 6.0.0 to 6.1.0
Bumps [flake8](https://github.com/pycqa/flake8) from 6.0.0 to 6.1.0.
- [Commits](https://github.com/pycqa/flake8/compare/6.0.0...6.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 00:26:40 +00:00
dependabot[bot] 3356defe95 ⬆️ Bump pillow from 10.0.1 to 10.1.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.0.1 to 10.1.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.0.1...10.1.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 00:25:05 +00:00
dependabot[bot] c04129f2b8 ⬆️ Bump pytest from 7.4.2 to 7.4.3
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.2 to 7.4.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.2...7.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 00:24:09 +00:00
dependabot[bot] 22b4444e9e ⬆️ Bump black from 23.7.0 to 23.10.1
Bumps [black](https://github.com/psf/black) from 23.7.0 to 23.10.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.7.0...23.10.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 00:23:12 +00:00
Piotr Skalski 5de77cee7d Merge pull request #534 from hugoles/patch-1
Rename script.sh to setup.sh
2023-10-25 15:15:06 +02:00
Onuralp SEZER f36b39b543 Merge pull request #537 from roboflow/dependabot/pip/ruff-0.1.2
⬆️ Bump ruff from 0.1.1 to 0.1.2
2023-10-25 14:23:04 +03:00
dependabot[bot] 8e91c62103 ⬆️ Bump ruff from 0.1.1 to 0.1.2
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.1 to 0.1.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.1.1...v0.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 11:18:29 +00:00
Onuralp SEZER ab0612917b Merge pull request #538 from roboflow/dependabot/pip/matplotlib-3.7.3
⬆️ Bump matplotlib from 3.7.2 to 3.7.3
2023-10-25 14:16:36 +03:00
Onuralp SEZER 4f31cf9f46 Merge pull request #536 from roboflow/dependabot/pip/opencv-python-headless-4.8.1.78
⬆️ Bump opencv-python-headless from 4.8.0.74 to 4.8.1.78
2023-10-25 14:15:58 +03:00
Onuralp SEZER d563d5db03 Merge pull request #535 from roboflow/dependabot/pip/mkdocstrings-0.23.0
⬆️ Bump mkdocstrings from 0.20.0 to 0.23.0
2023-10-25 14:15:08 +03:00
Onuralp SEZER f309b43c68 Merge pull request #539 from roboflow/dependabot/pip/pre-commit-3.5.0
⬆️ Bump pre-commit from 3.3.3 to 3.5.0
2023-10-25 14:14:32 +03:00
dependabot[bot] b17003855c ⬆️ Bump pre-commit from 3.3.3 to 3.5.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.3 to 3.5.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.3.3...v3.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 00:44:21 +00:00
dependabot[bot] 45a1905812 ⬆️ Bump matplotlib from 3.7.2 to 3.7.3
Bumps [matplotlib](https://github.com/matplotlib/matplotlib) from 3.7.2 to 3.7.3.
- [Release notes](https://github.com/matplotlib/matplotlib/releases)
- [Commits](https://github.com/matplotlib/matplotlib/compare/v3.7.2...v3.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 00:43:41 +00:00
dependabot[bot] cbcd0be74c ⬆️ Bump opencv-python-headless from 4.8.0.74 to 4.8.1.78
Bumps [opencv-python-headless](https://github.com/opencv/opencv-python) from 4.8.0.74 to 4.8.1.78.
- [Release notes](https://github.com/opencv/opencv-python/releases)
- [Commits](https://github.com/opencv/opencv-python/commits)

---
updated-dependencies:
- dependency-name: opencv-python-headless
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 00:42:13 +00:00
dependabot[bot] bda80934cc ⬆️ Bump mkdocstrings from 0.20.0 to 0.23.0
Bumps [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) from 0.20.0 to 0.23.0.
- [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.20.0...0.23.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-25 00:41:33 +00:00
Hugo Dutra b77bab39de Rename script.sh to setup.sh
changing the file name.
2023-10-24 12:37:52 -03:00
Onuralp SEZER 599a9b8a5b Merge pull request #531 from roboflow/dependabot/pip/ruff-0.1.1
⬆️ Bump ruff from 0.0.280 to 0.1.1
2023-10-24 17:23:59 +03:00
Piotr Skalski b9dbbbc0ec Merge pull request #533 from roboflow/assets-fix
Assets fix
2023-10-24 16:16:30 +02:00
pre-commit-ci[bot] 337abe1e71 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-24 14:15:07 +00:00
SkalskiP 9ece846f8e Update project version in pyproject.toml
Increased the version of the project from "0.17.0rc1" to "0.17.0rc2" in the 'pyproject.toml' file.
2023-10-24 16:11:46 +02:00
dependabot[bot] c23d00566b ⬆️ Bump ruff from 0.0.280 to 0.1.1
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.280 to 0.1.1.
- [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.0.280...v0.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 14:11:27 +00:00
SkalskiP 6837ef1d36 Refactor asset imports and improve documentation
Updated the import statements in the `supervision/assets/__init__.py`, `supervision/assets/downloader.py`, and `supervision/assets/list.py` files to use absolute paths for improved readability and reduced risk of import errors. Also added a usage example to the `download_assets` function to better illustrate its usage and return value.
2023-10-24 16:10:37 +02:00
Onuralp SEZER 26990513ba Merge pull request #528 from roboflow/dependabot/pip/build-1.0.3
⬆️ Bump build from 0.10.0 to 1.0.3
2023-10-24 17:09:44 +03:00
Onuralp SEZER bdf527809d Merge pull request #532 from roboflow/dependabot/pip/opencv-python-4.8.1.78
⬆️ Bump opencv-python from 4.8.0.74 to 4.8.1.78
2023-10-24 17:09:18 +03:00
dependabot[bot] 23a71e6f51 ⬆️ Bump build from 0.10.0 to 1.0.3
Bumps [build](https://github.com/pypa/build) from 0.10.0 to 1.0.3.
- [Release notes](https://github.com/pypa/build/releases)
- [Changelog](https://github.com/pypa/build/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/build/compare/0.10.0...1.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 14:02:20 +00:00
dependabot[bot] e61f1718a0 ⬆️ Bump opencv-python from 4.8.0.74 to 4.8.1.78
Bumps [opencv-python](https://github.com/opencv/opencv-python) from 4.8.0.74 to 4.8.1.78.
- [Release notes](https://github.com/opencv/opencv-python/releases)
- [Commits](https://github.com/opencv/opencv-python/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 14:00:32 +00:00
Onuralp SEZER bb79eebdae Merge pull request #530 from roboflow/dependabot/pip/mkdocs-material-9.4.6
⬆️ Bump mkdocs-material from 9.1.19 to 9.4.6
2023-10-24 17:00:17 +03:00
Onuralp SEZER cdb74c1b19 Merge pull request #529 from roboflow/dependabot/pip/pytest-7.4.2
⬆️ Bump pytest from 7.4.0 to 7.4.2
2023-10-24 16:59:15 +03:00
dependabot[bot] b1ceb1debf ⬆️ Bump mkdocs-material from 9.1.19 to 9.4.6
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.19 to 9.4.6.
- [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.1.19...9.4.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 13:59:09 +00:00
Onuralp SEZER 9fe343942f Merge pull request #526 from roboflow/dependabot/github_actions/actions/first-interaction-1.2.0
⬆️ Bump actions/first-interaction from 1.1.1 to 1.2.0
2023-10-24 16:58:35 +03:00
Onuralp SEZER b08d40cad4 Merge pull request #527 from roboflow/dependabot/github_actions/actions/checkout-4
⬆️ Bump actions/checkout from 3 to 4
2023-10-24 16:58:05 +03:00
dependabot[bot] 46a50e9595 ⬆️ Bump pytest from 7.4.0 to 7.4.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.0 to 7.4.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.0...7.4.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 13:57:57 +00:00
dependabot[bot] 7001721872 ⬆️ Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 13:56:24 +00:00
dependabot[bot] 8c2d18d752 ⬆️ Bump actions/first-interaction from 1.1.1 to 1.2.0
Bumps [actions/first-interaction](https://github.com/actions/first-interaction) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/actions/first-interaction/releases)
- [Commits](https://github.com/actions/first-interaction/compare/v1.1.1...v1.2.0)

---
updated-dependencies:
- dependency-name: actions/first-interaction
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 13:56:19 +00:00
Piotr Skalski fc8e2e2889 Merge pull request #479 from roboflow/dependabot-bot-add
ci(dependabot): 🤖 create dependabot.yml config for update github actions and python packages automatically.
2023-10-24 15:55:57 +02:00
Onuralp SEZER 14dfb32f44 Merge pull request #476 from roboflow/asset-addon
feat(assets): ✨ assets and assets downloader add-on for supervision[assets]
2023-10-24 16:53:38 +03:00
Piotr Skalski 8aee70872f Merge branch 'develop' into asset-addon 2023-10-24 15:50:56 +02:00
SkalskiP 671c8b3683 Update asset list and project version 2023-10-24 15:49:32 +02:00
SkalskiP edaef0b165 Merge remote-tracking branch 'origin/asset-addon' into asset-addon 2023-10-24 15:42:14 +02:00
SkalskiP 28fb656bca Update docstring formatting in VideoAssets enum
Updated the docstring comment's format inside the VideoAssets enum in supervision/assets/list.py. The update aligns with PEP 8 E501 error code that requires line too long (>80 characters).

Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-10-24 16:40:26 +03:00
SkalskiP e9866c2f25 "Add instructions for assets utility installation
Expanded the documentation to include instructions on how to install and use the Supervision assets utility. Instructions include steps for performing the installation using pip, allowing users to easily download video files for their demos.
2023-10-24 15:40:19 +02:00
SkalskiP e59d1bc9f3 Merge remote-tracking branch 'origin/asset-addon' into asset-addon
# Conflicts:
#	supervision/assets/list.py
2023-10-24 15:37:53 +02:00
SkalskiP b6001e389e Update docstring formatting in VideoAssets enum
Updated the docstring comment's format inside the VideoAssets enum in supervision/assets/list.py. The update aligns with PEP 8 E501 error code that requires line too long (>80 characters).

Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-10-24 16:07:48 +03:00
SkalskiP c529402068 Update docstring formatting in VideoAssets enum
Updated the docstring comment's format inside the VideoAssets enum in supervision/assets/list.py. The update aligns with PEP 8 E501 error code that requires line too long (>80 characters).
2023-10-24 15:05:00 +02:00
SkalskiP 9d68ee6a1e Merge remote-tracking branch 'origin/asset-addon' into asset-addon 2023-10-24 15:04:02 +02:00
SkalskiP 999c12162a Refactor imports in downloader.py
The 'Response' imported module from 'requests' in downloader.py is not needed.
2023-10-24 15:03:54 +02:00
pre-commit-ci[bot] 7d3082c93b fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-24 13:01:25 +00:00
SkalskiP 4cb7400c75 Merge remote-tracking branch 'origin/asset-addon' into asset-addon 2023-10-24 15:01:12 +02:00
SkalskiP 3f5f5fb070 Rename asset_list.py and update VideoAssets enumeration
The file asset_list.py has been renamed to list.py for better readability and simplicity. In the VideoAssets enumeration, additional information has been included. This includes specific details for each member of the enum, notably the filename of the related video and its URL.
2023-10-24 15:01:03 +02:00
pre-commit-ci[bot] 8689c294bf fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-24 12:34:28 +00:00
SkalskiP 3391eec078 Refactor and improve readability of downloader.py
The code for the downloader function in the supervision/assets/downloader.py file has been refactored and optimized. Package imports were cleaned up to remove unnecessary functions and the "path_exists" and "os_remove" functions were replaced with their pathlib equivalents to improve consistency.
2023-10-24 14:31:31 +02:00
SkalskiP 6887b0b412 "Correct md5 hash reference in downloader script
Updated the reference for the md5 hash in downloader.py.
2023-10-24 14:25:11 +02:00
SkalskiP a36abd4297 "Fix reference bug in video asset downloader
Updated 'asset_name' to 'filename' in downloader.py. The downloader was using the incorrect variable 'asset_name', causing failed video asset downloads. Correcting to 'filename' allows for accurate md5 check and download."
2023-10-24 14:21:58 +02:00
SkalskiP 7715ef2a17 The downloader was incorrectly using 'asset_name' instead of 'filename' leading to missed video asset downloads. The reference has been corrected to use 'filename' for proper checking and downloading. 2023-10-24 14:16:46 +02:00
SkalskiP 9b3dc37e28 Merge remote-tracking branch 'origin/asset-addon' into asset-addon 2023-10-24 14:14:26 +02:00
SkalskiP 24aefe6bcd Fix asset name checking in downloader module 2023-10-24 14:12:45 +02:00
pre-commit-ci[bot] 52452c019c fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-24 12:04:33 +00:00
SkalskiP dca6d1248f Merge remote-tracking branch 'origin/asset-addon' into asset-addon 2023-10-24 14:04:11 +02:00
SkalskiP 03fd015f39 Improve readability and maintainability in downloader.py 2023-10-24 14:04:00 +02:00
pre-commit-ci[bot] 7faddb52ca fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-24 11:23:24 +00:00
SkalskiP f987e4f786 Refactor video assets enum and variable names
Renamed enum and variables to improve clarity for VideoAssets in asset_list.py. For instance, MILK_1 is updated to MILK_BOTTLED_PLANT and PEOPLE_WALKING_BW to PEOPLE_WALKING. Also, the VIDEO_ASSETS dictionary type hint updated to Dict. Additionally, a new method 'list' added to class VideoAssets that returns a list of all enum values.
2023-10-24 13:23:05 +02:00
Onuralp SEZER a00a752d44 Merge pull request #522 from roboflow/pre-commit-ci-update-config
chore(pre_commit): ⬆ pre_commit autoupdate
2023-10-23 20:55:12 +03:00
pre-commit-ci[bot] 8bf721559f chore(pre_commit): ⬆ pre_commit autoupdate
updates:
- [github.com/psf/black: 23.9.1 → 23.10.0](https://github.com/psf/black/compare/23.9.1...23.10.0)
- [github.com/astral-sh/ruff-pre-commit: v0.0.292 → v0.1.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.292...v0.1.1)
2023-10-23 17:44:59 +00:00
abhishek7kalra 9f901bb61e Fixed position argument logic in TraceAnnotator 2023-10-21 18:16:58 +05:30
Abhishek Kalra ece7164ce6 Merge branch 'roboflow:develop' into develop 2023-10-21 16:34:04 +05:30
Piotr Skalski de45e9d67f Merge pull request #510 from roboflow/509-mask-annotator-from-sam-error
fix(notebook): 🐛📘 sam detection ColorLookup param and enum added and sv version updated
2023-10-21 12:28:12 +02:00
Onuralp SEZER b815c0e7fc fix(notebook): 🐛📘 sam detection ColorLookup param and enum added and sv version updated
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-10-21 10:36:30 +03:00
Piotr Skalski c158f96b75 Merge pull request #502 from roboflow/main
Merge pull request #493 from roboflow/develop
2023-10-19 12:39:55 +02:00
Abhishek Kalra e927a3c0a5 Merge pull request #2 from abhishek7kalra/linezonetrigger
change return type from list to nparray
2023-10-15 19:07:54 +05:30
Abhishek Kalra b1f85969a5 Merge pull request #1 from abhishek7kalra/linezonetrigger
Linezonetrigger
2023-10-15 18:12:42 +05:30
Onuralp SEZER f3b92163ad ci(dependabot): ⬆️ create dependabot.yml config for update github actions and python packages automatically 2023-10-14 18:08:46 +03:00
Rajarshi Misra e71232f6ff Merge branch 'roboflow:develop' into develop 2023-10-14 13:55:55 +05:30
pre-commit-ci[bot] 9e5d30732d fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-13 22:52:48 +00:00
capjamesg 9c2aaa0d2e add classification annotator and from_clip loader 2023-10-13 23:50:18 +01:00
Onuralp SEZER 2ab5941cbc feat(assets): ✨ assets and assets downloader add-on for supervision[assets]
Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
2023-10-14 01:39:25 +03:00
Rajarshi Misra 3dbbcf79ae Final 2023-10-13 22:55:41 +05:30
pre-commit-ci[bot] 47dcb19829 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-13 17:24:29 +00:00
Rajarshi Misra 9c96180a74 Update track_objects.md 2023-10-13 22:53:58 +05:30
Rajarshi Misra cd76b79ec5 Update track_objects.md 2023-10-13 18:51:53 +05:30
pre-commit-ci[bot] 377b3fdda7 fix(pre_commit): 🎨 auto format pre-commit hooks 2023-10-13 13:17:02 +00:00
Rajarshi Misra 9572469f5f Final changes left 2023-10-13 18:46:49 +05:30
Rajarshi Misra da7c056812 Merge branch 'roboflow:develop' into develop 2023-10-13 15:29:28 +05:30
Rajarshi Misra b1f207f2ee Update track_objects.md
Added all the subtopics and 'what is tracking'
2023-10-12 22:47:16 +05:30
Rajarshi Misra f82f297f2e Update track_objects.md
Typo
2023-10-12 19:58:55 +05:30
Rajarshi Misra 9a2a87a170 Just writing the title 2023-10-12 19:58:11 +05:30
50 changed files with 3049 additions and 1450 deletions
+16
View File
@@ -0,0 +1,16 @@
version: 2
updates:
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
commit-message:
prefix: ⬆️
# Python
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
commit-message:
prefix: ⬆️
+27
View File
@@ -0,0 +1,27 @@
attrs==23.1.0
certifi==2023.7.22
charset-normalizer==2.0.12
cycler==0.12.1
exceptiongroup==1.1.3
fonttools==4.43.1
idna==3.4
iniconfig==2.0.0
kiwisolver==1.4.5
matplotlib==3.5.0
numpy==1.21.2
opencv-python==4.5.5.64
packaging==23.2
Pillow==10.1.0
pluggy==1.3.0
pyparsing==3.1.1
pytest==7.2.0
python-dateutil==2.8.2
PyYAML==5.3
requests==2.26.0
scipy==1.9.0
setuptools-scm==8.0.4
six==1.16.0
tomli==2.0.1
tqdm==4.62.3
typing_extensions==4.8.0
urllib3==1.26.18
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clear cache
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
script: |
console.log("About to clear")
+8 -1
View File
@@ -6,14 +6,21 @@ on:
- master
- main
- develop
permissions:
contents: write
pages: write
pull-requests: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: 3.x
- run: pip install mkdocs-material
- run: pip install "mkdocstrings[python]"
- run: pip install "mkdocs-material[imaging]"
- run: mkdocs gh-deploy --force
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
steps:
- name: Checkout source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: 🐍 Set up Python 3.8 environment for build
uses: actions/setup-python@v4
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
python-version: [3.8]
steps:
- name: 🛎️ Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- name: 🐍 Set up Python ${{ matrix.python-version }}
+32
View File
@@ -0,0 +1,32 @@
name: Python 3.8 - Min Dep Test WorkFlow
on:
pull_request:
branches: [main, develop]
jobs:
build-min-dep-test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8"]
steps:
- name: 🛎️ Checkout
uses: actions/checkout@v4
- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
# id based on python version
id: python-setup
with:
python-version: ${{ matrix.python-version }}
check-latest: true
cache: 'pip'
cache-dependency-path: '**/requirements-dev-min.txt'
- name: 📦 Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r .github/requirements-dev-min.txt
- name: 🧪 Test
run: "python -m pytest ./test"
+2 -2
View File
@@ -5,14 +5,14 @@ on:
branches: [main, develop]
jobs:
build:
build-dev-test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10","3.11"]
steps:
- name: 🛎️ Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
# id based on python version
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
name: 👋 Welcome
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1.1.1
- uses: actions/first-interaction@v1.3.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: "Hello there, thank you for opening an Issue ! 🙏🏻 The team was notified and they will get back to you asap."
+3 -2
View File
@@ -11,6 +11,7 @@ repos:
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
exclude: test/.*\.py
- id: check-yaml
- id: check-docstring-first
- id: check-executables-have-shebangs
@@ -65,12 +66,12 @@ repos:
- repo: https://github.com/psf/black
rev: 23.9.1
rev: 23.11.0
hooks:
- id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.292
rev: v0.1.6
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
+50 -140
View File
@@ -24,10 +24,6 @@
</div>
<a href="https://github.com/roboflow/supervision/issues?q=is%3Aissue+label%3Ahacktoberfest+">
<img width="100%" src="https://media.roboflow.com/open-source/supervision/hacktoberfest-banner-3.png">
</a>
## 👋 hello
**We write your reusable computer vision tools.** Whether you need to load your dataset from your hard drive, draw detections on an image or video, or count how many detections are in a zone. You can count on us! 🤝
@@ -38,73 +34,62 @@ Pip install the supervision package in a
[**3.11>=Python>=3.8**](https://www.python.org/) environment.
```bash
pip install supervision[desktop]
pip install supervision
```
Read more about desktop, headless, and local installation in our [guide](https://roboflow.github.io/supervision/).
## 🔥 quickstart
### [detections processing](https://roboflow.github.io/supervision/detection/core/)
### models
Supervision was designed to be model agnostic. Just plug in any classification, detection, or segmentation model. For your convenience, we have created [connectors](https://supervision.roboflow.com/detection/core/#detections) for the most popular libraries like Ultralytics, Transformers, or MMDetection.
```python
>>> import cv2
>>> import supervision as sv
>>> from ultralytics import YOLO
>>> image = cv2.imread(...)
>>> model = YOLO('yolov8s.pt')
>>> result = model(IMAGE)[0]
>>> result = model(image)[0]
>>> detections = sv.Detections.from_ultralytics(result)
>>> len(detections)
5
```
<details close>
<summary>👉 more detections utils</summary>
### annotators
- Easily switch inference pipeline between supported object detection/instance segmentation models
Supervision offers a wide range of highly customizable [annotators](https://supervision.roboflow.com/annotators/), allowing you to compose the perfect visualization for your use case.
```python
>>> import supervision as sv
>>> from segment_anything import sam_model_registry, SamAutomaticMaskGenerator
```python
>>> import cv2
>>> import supervision as sv
>>> sam = sam_model_registry[MODEL_TYPE](checkpoint=CHECKPOINT_PATH).to(device=DEVICE)
>>> mask_generator = SamAutomaticMaskGenerator(sam)
>>> sam_result = mask_generator.generate(IMAGE)
>>> detections = sv.Detections.from_sam(sam_result=sam_result)
```
>>> image = cv2.imread(...)
>>> detections = sv.Detections(...)
- [Advanced filtering](https://roboflow.github.io/supervision/quickstart/detections/)
>>> bounding_box_annotator = sv.BoundingBoxAnnotator()
>>> annotated_frame = bounding_box_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
```python
>>> detections = detections[detections.class_id == 0]
>>> detections = detections[detections.confidence > 0.5]
>>> detections = detections[detections.area > 1000]
```
https://github.com/roboflow/supervision/assets/26109316/691e219c-0565-4403-9218-ab5644f39bce
- Image annotation
### datasets
```python
>>> import supervision as sv
>>> box_annotator = sv.BoxAnnotator()
>>> annotated_frame = box_annotator.annotate(
... scene=IMAGE,
... detections=detections
... )
```
</details>
### [datasets processing](https://roboflow.github.io/supervision/dataset/core/)
Supervision provides a set of [utils](https://supervision.roboflow.com/datasets/) that allow you to load, split, merge, and save datasets in one of the supported formats.
```python
>>> import supervision as sv
>>> dataset = sv.DetectionDataset.from_yolo(
... images_directory_path='...',
... annotations_directory_path='...',
... data_yaml_path='...'
... images_directory_path=...,
... annotations_directory_path=...,
... data_yaml_path=...
... )
>>> dataset.classes
@@ -117,38 +102,27 @@ Read more about desktop, headless, and local installation in our [guide](https:/
<details close>
<summary>👉 more dataset utils</summary>
- Load object detection/instance segmentation datasets in one of the supported formats
- load
```python
>>> dataset = sv.DetectionDataset.from_yolo(
... images_directory_path='...',
... annotations_directory_path='...',
... data_yaml_path='...'
... images_directory_path=...,
... annotations_directory_path=...,
... data_yaml_path=...
... )
>>> dataset = sv.DetectionDataset.from_pascal_voc(
... images_directory_path='...',
... annotations_directory_path='...'
... images_directory_path=...,
... annotations_directory_path=...
... )
>>> dataset = sv.DetectionDataset.from_coco(
... images_directory_path='...',
... annotations_path='...'
... images_directory_path=...,
... annotations_path=...
... )
```
- Loop over dataset entries
```python
>>> for name, image, labels in dataset:
... print(labels.xyxy)
array([[404. , 719. , 538. , 884.5 ],
[155. , 497. , 404. , 833.5 ],
[ 20.154999, 347.825 , 416.125 , 915.895 ]], dtype=float32)
```
- Split dataset for training, testing, and validation
- split
```python
>>> train_dataset, test_dataset = dataset.split(split_ratio=0.7)
@@ -158,7 +132,7 @@ Read more about desktop, headless, and local installation in our [guide](https:/
(700, 150, 150)
```
- Merge multiple datasets
- merge
```python
>>> ds_1 = sv.DetectionDataset(...)
@@ -180,103 +154,39 @@ Read more about desktop, headless, and local installation in our [guide](https:/
['cat', 'dog', 'person']
```
- Save object detection/instance segmentation datasets in one of the supported formats
- save
```python
>>> dataset.as_yolo(
... images_directory_path='...',
... annotations_directory_path='...',
... data_yaml_path='...'
... images_directory_path=...,
... annotations_directory_path=...,
... data_yaml_path=...
... )
>>> dataset.as_pascal_voc(
... images_directory_path='...',
... annotations_directory_path='...'
... images_directory_path=...,
... annotations_directory_path=...
... )
>>> dataset.as_coco(
... images_directory_path='...',
... annotations_path='...'
... images_directory_path=...,
... annotations_path=...
... )
```
- Convert labels between supported formats
- convert
```python
>>> sv.DetectionDataset.from_yolo(
... images_directory_path='...',
... annotations_directory_path='...',
... data_yaml_path='...'
... images_directory_path=...,
... annotations_directory_path=...,
... data_yaml_path=...
... ).as_pascal_voc(
... images_directory_path='...',
... annotations_directory_path='...'
... images_directory_path=...,
... annotations_directory_path=...
... )
```
- Load classification datasets in one of the supported formats
```python
>>> cs = sv.ClassificationDataset.from_folder_structure(
... root_directory_path='...'
... )
```
- Save classification datasets in one of the supported formats
```python
>>> cs.as_folder_structure(
... root_directory_path='...'
... )
```
</details>
### [model evaluation](https://roboflow.github.io/supervision/metrics/detection/)
```python
>>> import supervision as sv
>>> dataset = sv.DetectionDataset.from_yolo(...)
>>> def callback(image: np.ndarray) -> sv.Detections:
... ...
>>> confusion_matrix = sv.ConfusionMatrix.benchmark(
... dataset = dataset,
... callback = callback
... )
>>> confusion_matrix.matrix
array([
[0., 0., 0., 0.],
[0., 1., 0., 1.],
[0., 1., 1., 0.],
[1., 1., 0., 0.]
])
```
<details close>
<summary>👉 more metrics</summary>
- Mean average precision (mAP) for object detection tasks.
```python
>>> import supervision as sv
>>> dataset = sv.DetectionDataset.from_yolo(...)
>>> def callback(image: np.ndarray) -> sv.Detections:
... ...
>>> mean_average_precision = sv.MeanAveragePrecision.benchmark(
... dataset = dataset,
... callback = callback
... )
>>> mean_average_precision.map50_95
0.433
```
</details>
## 🎬 tutorials
Vendored
+2 -2
View File
@@ -226,7 +226,7 @@
"output_type": "stream",
"text": [
"\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/45.4 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.4/45.4 kB\u001b[0m \u001b[31m3.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h0.15.0\n"
"\u001b[?25h0.16.0\n"
]
}
],
@@ -540,7 +540,7 @@
}
],
"source": [
"mask_annotator = sv.MaskAnnotator(color_map=\"index\")\n",
"mask_annotator = sv.MaskAnnotator(color_lookup=sv.ColorLookup.INDEX)\n",
"\n",
"annotated_image = mask_annotator.annotate(image.copy(), detections=detections)\n",
"\n",
+80 -5
View File
@@ -40,7 +40,7 @@
</div>
=== "BoxMask"
=== "Color"
```python
>>> import supervision as sv
@@ -48,8 +48,8 @@
>>> image = ...
>>> detections = sv.Detections(...)
>>> box_mask_annotator = sv.BoxMaskAnnotator()
>>> annotated_frame = box_mask_annotator.annotate(
>>> color_annotator = sv.ColorAnnotator()
>>> annotated_frame = color_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
@@ -103,6 +103,27 @@
</div>
=== "Triangle"
```python
>>> import supervision as sv
>>> image = ...
>>> detections = sv.Detections(...)
>>> triangle_annotator = sv.TriangleAnnotator()
>>> annotated_frame = triangle_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
<div class="result" markdown>
![triangle-annotator-example](https://media.roboflow.com/supervision-annotator-examples/triangle-annotator-example.png){ align=center width="800" }
</div>
=== "Ellipse"
```python
@@ -166,6 +187,27 @@
</div>
=== "Polygon"
```python
>>> import supervision as sv
>>> image = ...
>>> detections = sv.Detections(...)
>>> polygon_annotator = sv.PolygonAnnotator()
>>> annotated_frame = polygon_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
<div class="result" markdown>
![polygon-annotator-example](https://media.roboflow.com/supervision-annotator-examples/polygon-annotator-example-purple.png){ align=center width="800" }
</div>
=== "Label"
```python
@@ -208,6 +250,27 @@
</div>
=== "Pixelate"
```python
>>> import supervision as sv
>>> image = ...
>>> detections = sv.Detections(...)
>>> pixelate_annotator = sv.PixelateAnnotator()
>>> annotated_frame = pixelate_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
<div class="result" markdown>
![pixelate-annotator-example](https://media.roboflow.com/supervision-annotator-examples/pixelate-annotator-example-10.png){ align=center width="800" }
</div>
=== "Trace"
```python
@@ -276,9 +339,9 @@
:::supervision.annotators.core.BoxCornerAnnotator
## BoxMaskAnnotator
## ColorAnnotator
:::supervision.annotators.core.BoxMaskAnnotator
:::supervision.annotators.core.ColorAnnotator
## CircleAnnotator
@@ -288,6 +351,10 @@
:::supervision.annotators.core.DotAnnotator
## TriangleAnnotator
:::supervision.annotators.core.TriangleAnnotator
## EllipseAnnotator
:::supervision.annotators.core.EllipseAnnotator
@@ -304,6 +371,10 @@
:::supervision.annotators.core.MaskAnnotator
## PolygonAnnotator
:::supervision.annotators.core.PolygonAnnotator
## LabelAnnotator
:::supervision.annotators.core.LabelAnnotator
@@ -312,6 +383,10 @@
:::supervision.annotators.core.BlurAnnotator
## PixelateAnnotator
:::supervision.annotators.core.PixelateAnnotator
## TraceAnnotator
:::supervision.annotators.core.TraceAnnotator
+21
View File
@@ -0,0 +1,21 @@
Supervision offers an assets download utility that allows you to download video files
that you can use in your demos.
## install extra
To install the Supervision assets utility, you can use `pip`. This utility is available
as an extra within the Supervision package.
!!! example "pip install"
```bash
pip install supervision[assets]
```
## download_assets
:::supervision.assets.downloader.download_assets
## VideoAssets
:::supervision.assets.list.VideoAssets
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+53
View File
@@ -1,3 +1,56 @@
### 0.17.0 <small>December 06, 2023</small>
- Added [#633](https://github.com/roboflow/supervision/pull/633): [`sv.PixelateAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.PixelateAnnotator) allowing to pixelate objects on images and videos.
- Added [#652](https://github.com/roboflow/supervision/pull/652): [`sv.TriangleAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.TriangleAnnotator) allowing to annotate images and videos with triangle markers.
- Added [#602](https://github.com/roboflow/supervision/pull/602): [`sv.PolygonAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.PolygonAnnotator) allowing to annotate images and videos with segmentation mask outline.
```python
>>> import supervision as sv
>>> image = ...
>>> detections = sv.Detections(...)
>>> polygon_annotator = sv.PolygonAnnotator()
>>> annotated_frame = polygon_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
- Added [#476](https://github.com/roboflow/supervision/pull/476): [`sv.assets`](https://supervision.roboflow.com/assets/) allowing download of video files that you can use in your demos.
```python
>>> from supervision.assets import download_assets, VideoAssets
>>> download_assets(VideoAssets.VEHICLES)
"vehicles.mp4"
```
- Added [#605](https://github.com/roboflow/supervision/pull/605): [`Position.CENTER_OF_MASS`](https://supervision.roboflow.com/geometry/core/#position) allowing to place labels in center of mass of segmentation masks.
- Added [#651](https://github.com/roboflow/supervision/pull/651): [`sv.scale_boxes`](https://supervision.roboflow.com/detection/utils/#supervision.detection.utils.scale_boxes) allowing to scale [`sv.Detections.xyxy`](https://supervision.roboflow.com/detection/core/#supervision.detection.core.Detections) values.
- Added [#637](https://github.com/roboflow/supervision/pull/637): [`sv.calculate_dynamic_text_scale`](https://supervision.roboflow.com/draw/utils/#supervision.draw.utils.calculate_dynamic_text_scale) and [`sv.calculate_dynamic_line_thickness`](https://supervision.roboflow.com/draw/utils/#supervision.draw.utils.calculate_dynamic_line_thickness) allowing text scale and line thickness to match image resolution.
- Added [#620](https://github.com/roboflow/supervision/pull/620): [`sv.Color.as_hex`](https://supervision.roboflow.com/draw/color/#supervision.draw.color.Color.as_hex) allowing to extract color value in HEX format.
- Added [#572](https://github.com/roboflow/supervision/pull/572): [`sv.Classifications.from_timm`](https://supervision.roboflow.com/classification/core/#supervision.classification.core.Classifications.from_timm) allowing to load classification result from [timm](https://huggingface.co/docs/hub/timm) models.
- Added [#478](https://github.com/roboflow/supervision/pull/478): [`sv.Classifications.from_clip`](https://supervision.roboflow.com/classification/core/#supervision.classification.core.Classifications.from_clip) allowing to load classification result from [clip](https://github.com/openai/clip) model.
- Added [#571](https://github.com/roboflow/supervision/pull/571): [`sv.Detections.from_azure_analyze_image`](https://supervision.roboflow.com/detection/core/#supervision.detection.core.Detections.from_azure_analyze_image) allowing to load detection results from [Azure Image Analysis](https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/concept-object-detection-40).
- Changed [#646](https://github.com/roboflow/supervision/pull/646): `sv.BoxMaskAnnotator` renaming it to [`sv.ColorAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.ColorAnnotator).
- Changed [#606](https://github.com/roboflow/supervision/pull/606): [`sv.MaskAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.MaskAnnotator) to make it **5x faster**.
- Fixed [#584](https://github.com/roboflow/supervision/pull/584): [`sv.DetectionDataset.from_yolo`](https://supervision.roboflow.com/datasets/#supervision.dataset.core.DetectionDataset.from_yolo) to ignore empty lines in annotation files.
- Fixed [#555](https://github.com/roboflow/supervision/pull/555): [`sv.BlurAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.BlurAnnotator) to trim negative coordinates before bluring detections.
- Fixed [#511](https://github.com/roboflow/supervision/pull/511): [`sv.TraceAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.TraceAnnotator) to respect trace position.
### 0.16.0 <small>October 19, 2023</small>
- Added [#422](https://github.com/roboflow/supervision/pull/422): [`sv.BoxMaskAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.BoxMaskAnnotator) allowing to annotate images and videos with mox masks.
+8
View File
@@ -25,3 +25,11 @@
## filter_polygons_by_area
:::supervision.detection.utils.filter_polygons_by_area
## move_boxes
:::supervision.detection.utils.move_boxes
## scale_boxes
:::supervision.detection.utils.scale_boxes
+8
View File
@@ -21,3 +21,11 @@
## draw_image
:::supervision.draw.utils.draw_image
## calculate_dynamic_font_scale
:::supervision.draw.utils.calculate_dynamic_text_scale
## calculate_dynamic_line_thickness
:::supervision.draw.utils.calculate_dynamic_line_thickness
+183 -1
View File
@@ -1 +1,183 @@
🚧 Page under construction.
Utilize Supervision to elevate your video analysis capabilities by effortlessly
[tracking](https://supervision.roboflow.com/trackers/) objects identified by various
object detection and segmentation models. This guide will walk you through the process
of running inference using the [Ultralytics](https://github.com/ultralytics/ultralytics)
YOLOv8 model, subsequently tracking these objects, and annotating the video.
To make it easier for you to follow our tutorial download the video we will use as an
example. You can do this using
[`supervision[assets]`](https://supervision.roboflow.com/assets/) extension.
```python
from supervision.assets import download_assets, VideoAssets
download_assets(VideoAssets.PEOPLE_WALKING)
```
<video controls>
<source src="https://media.roboflow.com/supervision/video-examples/people-walking.mp4" type="video/mp4">
</video>
## Run Inference
First, you'll need to obtain predictions from your object detection or segmentation
model. In this tutorial, we are using the YOLOv8 model as an example. However,
Supervision is versatile and compatible with various models. Check this
[link](https://supervision.roboflow.com/how_to/detect_and_annotate/#load-predictions-into-supervision)
for guidance on how to plug in other models.
We will define a `callback` function, which will process each frame of the video
by obtaining model predictions and then annotating the frame based on these predictions.
This `callback` function will be essential in the subsequent steps of the tutorial, as
it will be modified to include tracking, labeling, and trace annotations.
```{ .py }
import numpy as np
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
box_annotator = sv.BoundingBoxAnnotator()
def callback(frame: np.ndarray, _: int) -> np.ndarray:
results = model(frame)[0]
detections = sv.Detections.from_ultralytics(results)
return box_annotator.annotate(frame.copy(), detections=detections)
sv.process_video(
source_path="people-walking.mp4",
target_path="result.mp4",
callback=callback
)
```
<video controls>
<source src="https://media.roboflow.com/supervision/video-examples/how-to/track-objects/run-inference.mp4" type="video/mp4">
</video>
## Tracking
After running inference and obtaining predictions, the next step is to track the
detected objects throughout the video. Utilizing Supervision’s
[`sv.ByteTrack`](https://supervision.roboflow.com/trackers/#supervision.tracker.byte_tracker.core.ByteTrack)
functionality, each detected object is assigned a unique tracker ID,
enabling the continuous following of the object's motion path across different frames.
```{ .py hl_lines="6 12" }
import numpy as np
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
tracker = sv.ByteTrack()
box_annotator = sv.BoundingBoxAnnotator()
def callback(frame: np.ndarray, _: int) -> np.ndarray:
results = model(frame)[0]
detections = sv.Detections.from_ultralytics(results)
detections = tracker.update_with_detections(detections)
return box_annotator.annotate(frame.copy(), detections=detections)
sv.process_video(
source_path="people-walking.mp4",
target_path="result.mp4",
callback=callback
)
```
## Annotate Video with Tracking IDs
Annotating the video with tracking IDs helps in distinguishing and following each object
distinctly. With the
[`sv.LabelAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.LabelAnnotator)
in Supervision, we can overlay the tracker IDs and class labels on the detected objects,
offering a clear visual representation of each object's class and unique identifier.
```{ .py hl_lines="8 15-19 23-24" }
import numpy as np
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
tracker = sv.ByteTrack()
box_annotator = sv.BoundingBoxAnnotator()
label_annotator = sv.LabelAnnotator()
def callback(frame: np.ndarray, _: int) -> np.ndarray:
results = model(frame)[0]
detections = sv.Detections.from_ultralytics(results)
detections = tracker.update_with_detections(detections)
labels = [
f"#{tracker_id} {results.names[class_id]}"
for class_id, tracker_id
in zip(detections.class_id, detections.tracker_id)
]
annotated_frame = box_annotator.annotate(
frame.copy(), detections=detections)
return label_annotator.annotate(
annotated_frame, detections=detections, labels=labels)
sv.process_video(
source_path="people-walking.mp4",
target_path="result.mp4",
callback=callback
)
```
<video controls>
<source src="https://media.roboflow.com/supervision/video-examples/how-to/track-objects/annotate-video-with-tracking-ids.mp4" type="video/mp4">
</video>
## Annotate Video with Traces
Adding traces to the video involves overlaying the historical paths of the detected
objects. This feature, powered by the
[`sv.TraceAnnotator`](https://supervision.roboflow.com/annotators/#supervision.annotators.core.TraceAnnotator),
allows for visualizing the trajectories of objects, helping in understanding the
movement patterns and interactions between objects in the video.
```{ .py hl_lines="9 26-27" }
import numpy as np
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
tracker = sv.ByteTrack()
box_annotator = sv.BoundingBoxAnnotator()
label_annotator = sv.LabelAnnotator()
trace_annotator = sv.TraceAnnotator()
def callback(frame: np.ndarray, _: int) -> np.ndarray:
results = model(frame)[0]
detections = sv.Detections.from_ultralytics(results)
detections = tracker.update_with_detections(detections)
labels = [
f"#{tracker_id} {results.names[class_id]}"
for class_id, tracker_id
in zip(detections.class_id, detections.tracker_id)
]
annotated_frame = box_annotator.annotate(
frame.copy(), detections=detections)
annotated_frame = label_annotator.annotate(
annotated_frame, detections=detections, labels=labels)
return trace_annotator.annotate(
annotated_frame, detections=detections)
sv.process_video(
source_path="people-walking.mp4",
target_path="result.mp4",
callback=callback
)
```
<video controls>
<source src="https://media.roboflow.com/supervision/video-examples/how-to/track-objects/annotate-video-with-traces.mp4" type="video/mp4">
</video>
This structured walkthrough should give a detailed pathway to annotate videos
effectively using Supervision’s various functionalities, including object tracking and
trace annotations.
+10
View File
@@ -0,0 +1,10 @@
document.addEventListener("DOMContentLoaded", function () {
var script = document.createElement("script");
script.src = "https://widget.kapa.ai/kapa-widget.bundle.js";
script.setAttribute("data-website-id", "e83c5c60-2968-410b-a2da-08fb104f23df");
script.setAttribute("data-project-name", "Roboflow");
script.setAttribute("data-project-color", "#6405C9");
script.setAttribute("data-project-logo", "https://media.roboflow.com/chat.png");
script.async = true;
document.head.appendChild(script);
});
+13 -3
View File
@@ -1,7 +1,7 @@
site_name: Supervision
site_url: https://supervision.roboflow.com/
site_author: Roboflow
site_description: A set of easy-to-use utils that will come in handy in any Computer Vision project
site_description: A set of easy-to-use utilities that will come in handy in any computer vision project.
repo_name: roboflow/supervision
repo_url: https://github.com/roboflow/supervision
edit_uri: https://github.com/roboflow/supervision/tree/main/docs
@@ -55,12 +55,13 @@ nav:
- Image: utils/image.md
- Notebook: utils/notebook.md
- File: utils/file.md
- Assets: assets.md
- Changelog: changelog.md
theme:
name: 'material'
logo: https://media.roboflow.com/open-source/supervision/supervision-lenny.png
favicon: https://media.roboflow.com/open-source/supervision/supervision-lenny.png
logo: assets/supervision-lenny.png
favicon: assets/supervision-lenny.png
palette:
# Palette for light mode
- scheme: default
@@ -78,10 +79,15 @@ theme:
font:
text: Roboto
code: Roboto Mono
features:
- content.code.copy
plugins:
- mkdocstrings
- search
- social:
cards_layout_dir: docs/layouts
cards_layout: custom
markdown_extensions:
- admonition
@@ -93,3 +99,7 @@ markdown_extensions:
alternate_style: true
- toc:
permalink: true
extra_javascript:
- "https://widget.kapa.ai/kapa-widget.bundle.js"
- "javascript/init_kapa_widget.js"
Generated
+1439 -1164
View File
File diff suppressed because it is too large Load Diff
+20 -14
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "supervision"
version = "0.16.0"
version = "0.17.0"
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>"]
@@ -36,26 +36,28 @@ classifiers=[
[tool.poetry.dependencies]
python = ">=3.8,<3.12.0"
numpy = "^1.20.0"
matplotlib = "^3.7.1"
pyyaml = "^6.0"
pillow = ">=9.4,<11.0"
opencv-python = { version = "^4.8.0.74", optional = true }
opencv-python-headless = "^4.8.0.74"
scipy = "^1.9.0"
numpy = ">=1.21.2"
matplotlib = ">=3.5.0"
pyyaml = ">=5.3,<=6.0.1"
pillow = ">=9.4"
opencv-python = { version = ">=4.5.5.64,<=4.8.1.78", optional = true }
opencv-python-headless = ">=4.5.5.64,<=4.8.1.78"
scipy = ">=1.9.0,<=2.0.0"
requests = { version = ">=2.26.0,<=2.31.0", optional = true }
tqdm = { version = ">=4.62.3,<=4.66.1", optional = true }
[tool.poetry.extras]
desktop = ["opencv-python"]
assets = ["requests","tqdm"]
[tool.poetry.group.dev.dependencies]
twine = "^4.0.2"
pytest = "^7.2.2"
wheel = "^0.40.0"
notebook = "^6.5.3"
build = "^0.10.0"
ruff = "^0.0.280"
wheel = ">=0.40,<0.43"
notebook = ">=6.5.3,<8.0.0"
build = ">=0.10,<1.1"
ruff = ">=0.0.280,<0.1.8"
isort = "^5.12.0"
black = "^23.7.0"
mypy = "^1.4.1"
@@ -65,7 +67,7 @@ flake8 = { version = "*", python = ">=3.8.1,<3.12.0" }
[tool.poetry.group.docs.dependencies]
mkdocs-material = "^9.1.4"
mkdocstrings = {extras = ["python"], version = "^0.20.0"}
mkdocstrings = {extras = ["python"], version = ">=0.20,<0.25"}
[tool.flake8]
exclude = ".venv"
@@ -79,6 +81,7 @@ extend-ignore = """
"""
per-file-ignores = """
__init__.py: F401
supervision/assets/list.py: E501
"""
[tool.isort]
@@ -149,6 +152,7 @@ exclude = [
"yarn-error.log",
"yarn.lock",
"docs",
"supervision/assets/list.py"
]
# Same as Black.
@@ -167,6 +171,8 @@ convention = "google"
[tool.ruff.per-file-ignores]
"__init__.py" = ["E402","F401"]
"supervision/assets/list.py" = ["E501"]
[tool.ruff.pylint]
max-args = 20
+9 -1
View File
@@ -10,15 +10,18 @@ from supervision.annotators.core import (
BlurAnnotator,
BoundingBoxAnnotator,
BoxCornerAnnotator,
BoxMaskAnnotator,
CircleAnnotator,
ColorAnnotator,
DotAnnotator,
EllipseAnnotator,
HaloAnnotator,
HeatMapAnnotator,
LabelAnnotator,
MaskAnnotator,
PixelateAnnotator,
PolygonAnnotator,
TraceAnnotator,
TriangleAnnotator,
)
from supervision.annotators.utils import ColorLookup
from supervision.classification.core import Classifications
@@ -34,15 +37,20 @@ from supervision.detection.tools.inference_slicer import InferenceSlicer
from supervision.detection.tools.polygon_zone import PolygonZone, PolygonZoneAnnotator
from supervision.detection.utils import (
box_iou_batch,
calculate_masks_centroids,
filter_polygons_by_area,
mask_to_polygons,
mask_to_xyxy,
move_boxes,
non_max_suppression,
polygon_to_mask,
polygon_to_xyxy,
scale_boxes,
)
from supervision.draw.color import Color, ColorPalette
from supervision.draw.utils import (
calculate_dynamic_line_thickness,
calculate_dynamic_text_scale,
draw_filled_rectangle,
draw_image,
draw_line,
+324 -72
View File
@@ -7,7 +7,9 @@ import numpy as np
from supervision.annotators.base import BaseAnnotator
from supervision.annotators.utils import ColorLookup, Trace, resolve_color
from supervision.detection.core import Detections
from supervision.detection.utils import clip_boxes, mask_to_polygons
from supervision.draw.color import Color, ColorPalette
from supervision.draw.utils import draw_polygon
from supervision.geometry.core import Position
@@ -28,7 +30,7 @@ class BoundingBoxAnnotator(BaseAnnotator):
annotating detections.
thickness (int): Thickness of the bounding box lines.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.thickness: int = thickness
@@ -50,7 +52,7 @@ class BoundingBoxAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -92,6 +94,10 @@ class BoundingBoxAnnotator(BaseAnnotator):
class MaskAnnotator(BaseAnnotator):
"""
A class for drawing masks on an image using provided detections.
!!! warning
This annotator utilizes the `sv.Detections.mask`.
"""
def __init__(
@@ -106,7 +112,7 @@ class MaskAnnotator(BaseAnnotator):
annotating detections.
opacity (float): Opacity of the overlay mask. Must be between `0` and `1`.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.opacity = opacity
@@ -128,7 +134,7 @@ class MaskAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -150,6 +156,8 @@ class MaskAnnotator(BaseAnnotator):
if detections.mask is None:
return scene
colored_mask = np.array(scene, copy=True, dtype=np.uint8)
for detection_idx in np.flip(np.argsort(detections.area)):
color = resolve_color(
color=self.color,
@@ -160,16 +168,99 @@ class MaskAnnotator(BaseAnnotator):
else custom_color_lookup,
)
mask = detections.mask[detection_idx]
colored_mask = np.zeros_like(scene, dtype=np.uint8)
colored_mask[:] = color.as_bgr()
scene[mask] = cv2.addWeighted(
colored_mask, self.opacity, scene, 1 - self.opacity, 0
)[mask]
colored_mask[mask] = color.as_bgr()
scene = cv2.addWeighted(colored_mask, self.opacity, scene, 1 - self.opacity, 0)
return scene.astype(np.uint8)
class PolygonAnnotator(BaseAnnotator):
"""
A class for drawing polygons on an image using provided detections.
!!! warning
This annotator utilizes the `sv.Detections.mask`.
"""
def __init__(
self,
color: Union[Color, ColorPalette] = ColorPalette.default(),
thickness: int = 2,
color_lookup: ColorLookup = ColorLookup.CLASS,
):
"""
Args:
color (Union[Color, ColorPalette]): The color or color palette to use for
annotating detections.
thickness (int): Thickness of the polygon lines.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.thickness: int = thickness
self.color_lookup: ColorLookup = color_lookup
def annotate(
self,
scene: np.ndarray,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
"""
Annotates the given scene with polygons based on the provided detections.
Args:
scene (np.ndarray): The image where polygons will be drawn.
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.
Example:
```python
>>> import supervision as sv
>>> image = ...
>>> detections = sv.Detections(...)
>>> polygon_annotator = sv.PolygonAnnotator()
>>> annotated_frame = polygon_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
![polygon-annotator-example](https://media.roboflow.com/
supervision-annotator-examples/polygon-annotator-example-purple.png)
"""
if detections.mask is None:
return scene
for detection_idx in range(len(detections)):
mask = detections.mask[detection_idx]
color = resolve_color(
color=self.color,
detections=detections,
detection_idx=detection_idx,
color_lookup=self.color_lookup
if custom_color_lookup is None
else custom_color_lookup,
)
for polygon in mask_to_polygons(mask=mask):
scene = draw_polygon(
scene=scene,
polygon=polygon,
color=color,
thickness=self.thickness,
)
return scene
class BoxMaskAnnotator(BaseAnnotator):
class ColorAnnotator(BaseAnnotator):
"""
A class for drawing box masks on an image using provided detections.
"""
@@ -186,7 +277,7 @@ class BoxMaskAnnotator(BaseAnnotator):
annotating detections.
opacity (float): Opacity of the overlay mask. Must be between `0` and `1`.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.color_lookup: ColorLookup = color_lookup
@@ -208,7 +299,7 @@ class BoxMaskAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -217,8 +308,8 @@ class BoxMaskAnnotator(BaseAnnotator):
>>> image = ...
>>> detections = sv.Detections(...)
>>> box_mask_annotator = sv.BoxMaskAnnotator()
>>> annotated_frame = box_mask_annotator.annotate(
>>> color_annotator = sv.ColorAnnotator()
>>> annotated_frame = color_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
@@ -254,6 +345,10 @@ class BoxMaskAnnotator(BaseAnnotator):
class HaloAnnotator(BaseAnnotator):
"""
A class for drawing Halos on an image using provided detections.
!!! warning
This annotator utilizes the `sv.Detections.mask`.
"""
def __init__(
@@ -271,7 +366,7 @@ class HaloAnnotator(BaseAnnotator):
kernel_size (int): The size of the average pooling kernel used for creating
the halo.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.opacity = opacity
@@ -294,7 +389,7 @@ class HaloAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -364,7 +459,7 @@ class EllipseAnnotator(BaseAnnotator):
start_angle (int): Starting angle of the ellipse.
end_angle (int): Ending angle of the ellipse.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.thickness: int = thickness
@@ -388,7 +483,7 @@ class EllipseAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -452,7 +547,7 @@ class BoxCornerAnnotator(BaseAnnotator):
thickness (int): Thickness of the corner lines.
corner_length (int): Length of each corner line.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.thickness: int = thickness
@@ -475,7 +570,7 @@ class BoxCornerAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -536,7 +631,7 @@ class CircleAnnotator(BaseAnnotator):
annotating detections.
thickness (int): Thickness of the circle line.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
@@ -559,7 +654,7 @@ class CircleAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -622,7 +717,7 @@ class DotAnnotator(BaseAnnotator):
radius (int): Radius of the drawn dots.
position (Position): The anchor position for placing the dot.
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.radius: int = radius
@@ -645,7 +740,7 @@ class DotAnnotator(BaseAnnotator):
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -664,7 +759,7 @@ class DotAnnotator(BaseAnnotator):
![dot-annotator-example](https://media.roboflow.com/
supervision-annotator-examples/dot-annotator-example-purple.png)
"""
xy = detections.get_anchor_coordinates(anchor=self.position)
xy = detections.get_anchors_coordinates(anchor=self.position)
for detection_idx in range(len(detections)):
color = resolve_color(
color=self.color,
@@ -705,56 +800,53 @@ class LabelAnnotator:
text_position (Position): Position of the text relative to the detection.
Possible values are defined in the `Position` enum.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.text_color: Color = text_color
self.text_scale: float = text_scale
self.text_thickness: int = text_thickness
self.text_padding: int = text_padding
self.text_position: Position = text_position
self.text_anchor: Position = text_position
self.color_lookup: ColorLookup = color_lookup
@staticmethod
def resolve_text_background_xyxy(
detection_xyxy: Tuple[int, int, int, int],
center_coordinates: Tuple[int, int],
text_wh: Tuple[int, int],
text_padding: int,
position: Position,
) -> Tuple[int, int, int, int]:
padded_text_wh = (text_wh[0] + 2 * text_padding, text_wh[1] + 2 * text_padding)
x1, y1, x2, y2 = detection_xyxy
center_x = (x1 + x2) // 2
center_y = (y1 + y2) // 2
center_x, center_y = center_coordinates
text_w, text_h = text_wh
if position == Position.TOP_LEFT:
return x1, y1 - padded_text_wh[1], x1 + padded_text_wh[0], y1
return center_x, center_y - text_h, center_x + text_w, center_y
elif position == Position.TOP_RIGHT:
return x2 - padded_text_wh[0], y1 - padded_text_wh[1], x2, y1
return center_x - text_w, center_y - text_h, center_x, center_y
elif position == Position.TOP_CENTER:
return (
center_x - padded_text_wh[0] // 2,
y1 - padded_text_wh[1],
center_x + padded_text_wh[0] // 2,
y1,
center_x - text_w // 2,
center_y - text_h,
center_x + text_w // 2,
center_y,
)
elif position == Position.CENTER:
elif position == Position.CENTER or position == Position.CENTER_OF_MASS:
return (
center_x - padded_text_wh[0] // 2,
center_y - padded_text_wh[1] // 2,
center_x + padded_text_wh[0] // 2,
center_y + padded_text_wh[1] // 2,
center_x - text_w // 2,
center_y - text_h // 2,
center_x + text_w // 2,
center_y + text_h // 2,
)
elif position == Position.BOTTOM_LEFT:
return x1, y2, x1 + padded_text_wh[0], y2 + padded_text_wh[1]
return center_x, center_y, center_x + text_w, center_y + text_h
elif position == Position.BOTTOM_RIGHT:
return x2 - padded_text_wh[0], y2, x2, y2 + padded_text_wh[1]
return center_x - text_w, center_y, center_x, center_y + text_h
elif position == Position.BOTTOM_CENTER:
return (
center_x - padded_text_wh[0] // 2,
y2,
center_x + padded_text_wh[0] // 2,
y2 + padded_text_wh[1],
center_x - text_w // 2,
center_y,
center_x + text_w // 2,
center_y + text_h,
)
def annotate(
@@ -775,7 +867,7 @@ class LabelAnnotator:
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -795,8 +887,10 @@ class LabelAnnotator:
supervision-annotator-examples/label-annotator-example-purple.png)
"""
font = cv2.FONT_HERSHEY_SIMPLEX
for detection_idx in range(len(detections)):
detection_xyxy = detections.xyxy[detection_idx].astype(int)
anchors_coordinates = detections.get_anchors_coordinates(
anchor=self.text_anchor
).astype(int)
for detection_idx, center_coordinates in enumerate(anchors_coordinates):
color = resolve_color(
color=self.color,
detections=detections,
@@ -810,22 +904,22 @@ class LabelAnnotator:
if (labels is None or len(detections) != len(labels))
else labels[detection_idx]
)
text_wh = cv2.getTextSize(
text_w, text_h = cv2.getTextSize(
text=text,
fontFace=font,
fontScale=self.text_scale,
thickness=self.text_thickness,
)[0]
text_w_padded = text_w + 2 * self.text_padding
text_h_padded = text_h + 2 * self.text_padding
text_background_xyxy = self.resolve_text_background_xyxy(
detection_xyxy=detection_xyxy,
text_wh=text_wh,
text_padding=self.text_padding,
position=self.text_position,
center_coordinates=tuple(center_coordinates),
text_wh=(text_w_padded, text_h_padded),
position=self.text_anchor,
)
text_x = text_background_xyxy[0] + self.text_padding
text_y = text_background_xyxy[1] + self.text_padding + text_wh[1]
text_y = text_background_xyxy[1] + self.text_padding + text_h
cv2.rectangle(
img=scene,
@@ -872,7 +966,7 @@ class BlurAnnotator(BaseAnnotator):
detections (Detections): Object detections to annotate.
Returns:
np.ndarray: The annotated image.
The annotated image.
Example:
```python
@@ -882,7 +976,7 @@ class BlurAnnotator(BaseAnnotator):
>>> detections = sv.Detections(...)
>>> blur_annotator = sv.BlurAnnotator()
>>> annotated_frame = blur_annotator.annotate(
>>> annotated_frame = circle_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
@@ -891,10 +985,13 @@ class BlurAnnotator(BaseAnnotator):
![blur-annotator-example](https://media.roboflow.com/
supervision-annotator-examples/blur-annotator-example-purple.png)
"""
for detection_idx in range(len(detections)):
x1, y1, x2, y2 = detections.xyxy[detection_idx].astype(int)
roi = scene[y1:y2, x1:x2]
image_height, image_width = scene.shape[:2]
clipped_xyxy = clip_boxes(
xyxy=detections.xyxy, resolution_wh=(image_width, image_height)
).astype(int)
for x1, y1, x2, y2 in clipped_xyxy:
roi = scene[y1:y2, x1:x2]
roi = cv2.blur(roi, (self.kernel_size, self.kernel_size))
scene[y1:y2, x1:x2] = roi
@@ -907,7 +1004,7 @@ class TraceAnnotator:
!!! warning
This annotator utilizes the `tracker_id`. Read
This annotator utilizes the `sv.Detections.tracker_id`. Read
[here](https://supervision.roboflow.com/trackers/) to learn how to plug
tracking into your inference pipeline.
"""
@@ -930,11 +1027,10 @@ class TraceAnnotator:
points. Defaults to `30`.
thickness (int): The thickness of the trace lines. Defaults to `2`.
color_lookup (str): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACE`.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.position = position
self.trace = Trace(max_size=trace_length)
self.trace = Trace(max_size=trace_length, anchor=position)
self.thickness = thickness
self.color_lookup: ColorLookup = color_lookup
@@ -955,7 +1051,7 @@ class TraceAnnotator:
Allows to override the default color mapping strategy.
Returns:
np.ndarray: The image with the trace paths drawn on it.
The annotated image.
Example:
```python
@@ -1051,7 +1147,7 @@ class HeatMapAnnotator:
detections (Detections): Object detections to annotate.
Returns:
np.ndarray: Annotated image.
Annotated image.
Example:
```python
@@ -1082,7 +1178,7 @@ class HeatMapAnnotator:
if self.heat_mask is None:
self.heat_mask = np.zeros(scene.shape[:2])
mask = np.zeros(scene.shape[:2])
for xy in detections.get_anchor_coordinates(self.position):
for xy in detections.get_anchors_coordinates(self.position):
cv2.circle(mask, (int(xy[0]), int(xy[1])), self.radius, 1, -1)
self.heat_mask = mask + self.heat_mask
temp = self.heat_mask.copy()
@@ -1100,3 +1196,159 @@ class HeatMapAnnotator:
mask
]
return scene
class PixelateAnnotator(BaseAnnotator):
"""
A class for pixelating regions in an image using provided detections.
"""
def __init__(self, pixel_size: int = 20):
"""
Args:
pixel_size (int): The size of the pixelation.
"""
self.pixel_size: int = pixel_size
def annotate(
self,
scene: np.ndarray,
detections: Detections,
) -> np.ndarray:
"""
Annotates the given scene by pixelating regions based on the provided
detections.
Args:
scene (np.ndarray): The image where pixelating will be applied.
detections (Detections): Object detections to annotate.
Returns:
The annotated image.
Example:
```python
>>> import supervision as sv
>>> image = ...
>>> detections = sv.Detections(...)
>>> pixelate_annotator = sv.PixelateAnnotator()
>>> annotated_frame = pixelate_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
![pixelate-annotator-example](https://media.roboflow.com/
supervision-annotator-examples/pixelate-annotator-example-10.png)
"""
image_height, image_width = scene.shape[:2]
clipped_xyxy = clip_boxes(
xyxy=detections.xyxy, resolution_wh=(image_width, image_height)
).astype(int)
for x1, y1, x2, y2 in clipped_xyxy:
roi = scene[y1:y2, x1:x2]
scaled_up_roi = cv2.resize(
src=roi, dsize=None, fx=1 / self.pixel_size, fy=1 / self.pixel_size
)
scaled_down_roi = cv2.resize(
src=scaled_up_roi,
dsize=(roi.shape[1], roi.shape[0]),
interpolation=cv2.INTER_NEAREST,
)
scene[y1:y2, x1:x2] = scaled_down_roi
return scene
class TriangleAnnotator(BaseAnnotator):
"""
A class for drawing triangle markers on an image at specific coordinates based on
provided detections.
"""
def __init__(
self,
color: Union[Color, ColorPalette] = ColorPalette.default(),
base: int = 10,
height: int = 10,
position: Position = Position.TOP_CENTER,
color_lookup: ColorLookup = ColorLookup.CLASS,
):
"""
Args:
color (Union[Color, ColorPalette]): The color or color palette to use for
annotating detections.
base (int): The base width of the triangle.
height (int): The height of the triangle.
position (Position): The anchor position for placing the triangle.
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
Options are `INDEX`, `CLASS`, `TRACK`.
"""
self.color: Union[Color, ColorPalette] = color
self.base: int = base
self.height: int = height
self.position: Position = position
self.color_lookup: ColorLookup = color_lookup
def annotate(
self,
scene: np.ndarray,
detections: Detections,
custom_color_lookup: Optional[np.ndarray] = None,
) -> np.ndarray:
"""
Annotates the given scene with triangles based on the provided detections.
Args:
scene (np.ndarray): The image where triangles will be drawn.
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.
Example:
```python
>>> import supervision as sv
>>> image = ...
>>> detections = sv.Detections(...)
>>> triangle_annotator = sv.TriangleAnnotator()
>>> annotated_frame = triangle_annotator.annotate(
... scene=image.copy(),
... detections=detections
... )
```
![triangle-annotator-example](https://media.roboflow.com/
supervision-annotator-examples/triangle-annotator-example.png)
"""
xy = detections.get_anchors_coordinates(anchor=self.position)
for detection_idx in range(len(detections)):
color = resolve_color(
color=self.color,
detections=detections,
detection_idx=detection_idx,
color_lookup=self.color_lookup
if custom_color_lookup is None
else custom_color_lookup,
)
tip_x, tip_y = int(xy[detection_idx, 0]), int(xy[detection_idx, 1])
vertices = np.array(
[
[tip_x - self.base // 2, tip_y - self.height],
[tip_x + self.base // 2, tip_y - self.height],
[tip_x, tip_y],
],
np.int32,
)
cv2.fillPoly(scene, [vertices], color.as_bgr())
return scene
+1 -1
View File
@@ -102,7 +102,7 @@ class Trace:
frame_id = np.full(len(detections), self.current_frame_id, dtype=int)
self.frame_id = np.concatenate([self.frame_id, frame_id])
self.xy = np.concatenate(
[self.xy, detections.get_anchor_coordinates(self.anchor)]
[self.xy, detections.get_anchors_coordinates(self.anchor)]
)
self.tracker_id = np.concatenate([self.tracker_id, detections.tracker_id])
+2
View File
@@ -0,0 +1,2 @@
from supervision.assets.downloader import download_assets
from supervision.assets.list import VideoAssets
+94
View File
@@ -0,0 +1,94 @@
import os
from hashlib import md5
from pathlib import Path
from shutil import copyfileobj
from typing import Union
from supervision.assets.list import VIDEO_ASSETS, VideoAssets
try:
from requests import get
from tqdm.auto import tqdm
except ImportError:
raise ValueError(
"\n"
"Please install requests and tqdm to download assets \n"
"or install supervision with assets \n"
"pip install supervision[assets] \n"
"\n"
)
def is_md5_hash_matching(filename: str, original_md5_hash: str) -> bool:
"""
Check if the MD5 hash of a file matches the original hash.
Parameters:
filename (str): The path to the file to be checked as a string.
original_md5_hash (str): The original MD5 hash to compare against.
Returns:
bool: True if the hashes match, False otherwise.
"""
if not os.path.exists(filename):
return False
with open(filename, "rb") as file:
file_contents = file.read()
computed_md5_hash = md5(file_contents).hexdigest()
return computed_md5_hash == original_md5_hash
def download_assets(asset_name: Union[VideoAssets, str]) -> str:
"""
Download a specified asset if it doesn't already exist or is corrupted.
Parameters:
asset_name (Union[VideoAssets, str]): The name or type of the asset to be
downloaded.
Returns:
str: The filename of the downloaded asset.
Example:
```python
>>> from supervision.assets import download_assets, VideoAssets
>>> download_assets(VideoAssets.VEHICLES)
"vehicles.mp4"
```
"""
filename = asset_name.value if isinstance(asset_name, VideoAssets) else asset_name
if not Path(filename).exists() and filename in VIDEO_ASSETS:
print(f"Downloading {filename} assets \n")
response = get(VIDEO_ASSETS[filename][0], stream=True, allow_redirects=True)
response.raise_for_status()
file_size = int(response.headers.get("Content-Length", 0))
folder_path = Path(filename).expanduser().resolve()
folder_path.parent.mkdir(parents=True, exist_ok=True)
with tqdm.wrapattr(
response.raw, "read", total=file_size, desc="", colour="#a351fb"
) as raw_resp:
with folder_path.open("wb") as file:
copyfileobj(raw_resp, file)
elif Path(filename).exists():
if not is_md5_hash_matching(filename, VIDEO_ASSETS[filename][1]):
print("File corrupted. Re-downloading... \n")
os.remove(filename)
return download_assets(filename)
print(f"{filename} asset download complete. \n")
else:
valid_assets = ", ".join(asset.value for asset in VideoAssets)
raise ValueError(
f"Invalid asset. It should be one of the following: {valid_assets}."
)
return filename
+65
View File
@@ -0,0 +1,65 @@
from enum import Enum
from typing import Dict, Tuple
BASE_VIDEO_URL = "https://media.roboflow.com/supervision/video-examples/"
class VideoAssets(Enum):
"""
Each member of this enum represents a video asset. The value associated with each
member is the filename of the video.
| Enum Member | Video Filename | Video URL |
|------------------------|----------------------------|---------------------------------------------------------------------------------------|
| `VEHICLES` | `vehicles.mp4` | [Link](https://media.roboflow.com/supervision/video-examples/vehicles.mp4) |
| `MILK_BOTTLING_PLANT` | `milk-bottling-plant.mp4` | [Link](https://media.roboflow.com/supervision/video-examples/milk-bottling-plant.mp4) |
| `VEHICLES_2` | `vehicles-2.mp4` | [Link](https://media.roboflow.com/supervision/video-examples/vehicles-2.mp4) |
| `GROCERY_STORE` | `grocery-store.mp4` | [Link](https://media.roboflow.com/supervision/video-examples/grocery-store.mp4) |
| `SUBWAY` | `subway.mp4` | [Link](https://media.roboflow.com/supervision/video-examples/subway.mp4) |
| `MARKET_SQUARE` | `market-square.mp4` | [Link](https://media.roboflow.com/supervision/video-examples/market-square.mp4) |
| `PEOPLE_WALKING` | `people-walking.mp4` | [Link](https://media.roboflow.com/supervision/video-examples/people-walking.mp4) |
"""
VEHICLES = "vehicles.mp4"
MILK_BOTTLING_PLANT = "milk-bottling-plant.mp4"
VEHICLES_2 = "vehicles-2.mp4"
GROCERY_STORE = "grocery-store.mp4"
SUBWAY = "subway.mp4"
MARKET_SQUARE = "market-square.mp4"
PEOPLE_WALKING = "people-walking.mp4"
@classmethod
def list(cls):
return list(map(lambda c: c.value, cls))
VIDEO_ASSETS: Dict[str, Tuple[str, str]] = {
VideoAssets.VEHICLES.value: (
f"{BASE_VIDEO_URL}{VideoAssets.VEHICLES.value}",
"8155ff4e4de08cfa25f39de96483f918",
),
VideoAssets.VEHICLES_2.value: (
f"{BASE_VIDEO_URL}{VideoAssets.VEHICLES_2.value}",
"830af6fba21ffbf14867a7fea595937b",
),
VideoAssets.MILK_BOTTLING_PLANT.value: (
f"{BASE_VIDEO_URL}{VideoAssets.MILK_BOTTLING_PLANT.value}",
"9e8fb6e883f842a38b3d34267290bdc7",
),
VideoAssets.GROCERY_STORE.value: (
f"{BASE_VIDEO_URL}{VideoAssets.GROCERY_STORE.value}",
"11402e7b861c1980527d3d74cbe3b366",
),
VideoAssets.SUBWAY.value: (
f"{BASE_VIDEO_URL}{VideoAssets.SUBWAY.value}",
"453475750691fb23c56a0cffef089194",
),
VideoAssets.MARKET_SQUARE.value: (
f"{BASE_VIDEO_URL}{VideoAssets.MARKET_SQUARE.value}",
"859179bf4a21f80a8baabfdb2ed716dc",
),
VideoAssets.PEOPLE_WALKING.value: (
f"{BASE_VIDEO_URL}{VideoAssets.PEOPLE_WALKING.value}",
"0574c053c8686c3f1dc0aa3743e45cb9",
),
}
+90 -5
View File
@@ -39,15 +39,58 @@ class Classifications:
_validate_class_ids(self.class_id, n)
_validate_confidence(self.confidence, n)
def __len__(self) -> int:
"""
Returns the number of classifications.
"""
return len(self.class_id)
@classmethod
def from_clip(cls, clip_results) -> Classifications:
"""
Creates a Classifications instance from a
[clip](https://github.com/openai/clip) inference result.
Args:
clip_results (np.ndarray): The inference result from clip model.
Returns:
Classifications: A new Classifications object.
Example:
```python
>>> from PIL import Image
>>> import clip
>>> import supervision as sv
>>> model, preprocess = clip.load('ViT-B/32')
>>> image = cv2.imread(SOURCE_IMAGE_PATH)
>>> image = preprocess(image).unsqueeze(0)
>>> text = clip.tokenize(["a diagram", "a dog", "a cat"])
>>> output, _ = model(image, text)
>>> classifications = sv.Classifications.from_clip(output)
```
"""
confidence = clip_results.softmax(dim=-1).cpu().detach().numpy()[0]
if len(confidence) == 0:
return cls(class_id=np.array([]), confidence=np.array([]))
class_ids = np.arange(len(confidence))
return cls(class_id=class_ids, confidence=confidence)
@classmethod
def from_ultralytics(cls, ultralytics_results) -> Classifications:
"""
Creates a Classifications instance from a
(https://github.com/ultralytics/ultralytics) inference result.
[ultralytics](https://github.com/ultralytics/ultralytics) inference result.
Args:
ultralytics_results (ultralytics.engine.results.Results):
The output Results instance from ultralytics model
The inference result from ultralytics model.
Returns:
Classifications: A new Classifications object.
@@ -60,15 +103,57 @@ class Classifications:
>>> image = cv2.imread(SOURCE_IMAGE_PATH)
>>> model = YOLO('yolov8n-cls.pt')
>>> model = YOLO('yolov8s-cls.pt')
>>> result = model(image)[0]
>>> classifications = sv.Classifications.from_ultralytics(result)
>>> output = model(image)[0]
>>> classifications = sv.Classifications.from_ultralytics(output)
```
"""
confidence = ultralytics_results.probs.data.cpu().numpy()
return cls(class_id=np.arange(confidence.shape[0]), confidence=confidence)
@classmethod
def from_timm(cls, timm_results) -> Classifications:
"""
Creates a Classifications instance from a
[timm](https://huggingface.co/docs/hub/timm) inference result.
Args:
timm_results: The inference result from timm model.
Returns:
Classifications: A new Classifications object.
Example:
```python
>>> from PIL import Image
>>> import timm
>>> from timm.data import resolve_data_config, create_transform
>>> import supervision as sv
>>> model = timm.create_model(
... model_name='hf-hub:nateraw/resnet50-oxford-iiit-pet',
... pretrained=True
... ).eval()
>>> config = resolve_data_config({}, model=model)
>>> transform = create_transform(**config)
>>> image = Image.open(SOURCE_IMAGE_PATH).convert('RGB')
>>> x = transform(image).unsqueeze(0)
>>> output = model(x)
>>> classifications = sv.Classifications.from_timm(output)
```
"""
confidence = timm_results.cpu().detach().numpy()[0]
if len(confidence) == 0:
return cls(class_id=np.array([]), confidence=np.array([]))
class_id = np.arange(len(confidence))
return cls(class_id=class_id, confidence=confidence)
def get_top_k(self, k: int) -> Tuple[np.ndarray, np.ndarray]:
"""
Retrieve the top k class IDs and confidences,
+1 -1
View File
@@ -149,7 +149,7 @@ def load_yolo_annotations(
annotations[image_path] = Detections.empty()
continue
lines = read_txt_file(str(annotation_path))
lines = read_txt_file(file_path=annotation_path, skip_empty=True)
h, w, _ = image.shape
resolution_wh = (w, h)
+99 -4
View File
@@ -1,11 +1,12 @@
from __future__ import annotations
from dataclasses import astuple, dataclass
from typing import Any, Iterator, List, Optional, Tuple, Union
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
import numpy as np
from supervision.detection.utils import (
calculate_masks_centroids,
extract_ultralytics_masks,
non_max_suppression,
process_roboflow_result,
@@ -63,6 +64,7 @@ def _validate_tracker_id(tracker_id: Any, n: int) -> None:
class Detections:
"""
Data class containing information about the detections in a video frame.
Attributes:
xyxy (np.ndarray): An array of shape `(n, 4)` containing
the bounding boxes coordinates in format `[x1, y1, x2, y2]`
@@ -323,7 +325,7 @@ class Detections:
>>> inferencer = DetInferencer(model_name, checkpoint, device)
>>> mmdet_result = inferencer(SOURCE_IMAGE_PATH, out_dir='./output',
... return_datasample=True)["predictions"][0]
... return_datasamples=True)["predictions"][0]
>>> detections = sv.Detections.from_mmdet(mmdet_result)
```
"""
@@ -460,7 +462,7 @@ class Detections:
>>> from segment_anything import (
... sam_model_registry,
... SamAutomaticMaskGenerator
... )
... )
>>> sam_model_reg = sam_model_registry[MODEL_TYPE]
>>> sam = sam_model_reg(checkpoint=CHECKPOINT_PATH).to(device=DEVICE)
@@ -483,6 +485,93 @@ class Detections:
xyxy = xywh_to_xyxy(boxes_xywh=xywh)
return cls(xyxy=xyxy, mask=mask)
@classmethod
def from_azure_analyze_image(
cls, azure_result: dict, class_map: Optional[Dict[int, str]] = None
) -> Detections:
"""
Creates a Detections instance from [Azure Image Analysis 4.0](
https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/
concept-object-detection-40).
Args:
azure_result (dict): The result from Azure Image Analysis. It should
contain detected objects and their bounding box coordinates.
class_map (Optional[Dict[int, str]]): A mapping ofclass IDs (int) to class
names (str). If None, a new mapping is created dynamically.
Returns:
Detections: A new Detections object.
Example:
```python
>>> import requests
>>> import supervision as sv
>>> image = open(input, "rb").read()
>>> endpoint = "https://.cognitiveservices.azure.com/"
>>> subscription_key = "..."
>>> headers = {
... "Content-Type": "application/octet-stream",
... "Ocp-Apim-Subscription-Key": subscription_key
... }
>>> response = requests.post(endpoint,
... headers=self.headers,
... data=image
... ).json()
>>> detections = sv.Detections.from_azure_analyze_image(response)
```
"""
if "error" in azure_result:
raise ValueError(
f'Azure API returned an error {azure_result["error"]["message"]}'
)
xyxy, confidences, class_ids = [], [], []
is_dynamic_mapping = class_map is None
if is_dynamic_mapping:
class_map = {}
class_map = {value: key for key, value in class_map.items()}
for detection in azure_result["objectsResult"]["values"]:
bbox = detection["boundingBox"]
tags = detection["tags"]
x0 = bbox["x"]
y0 = bbox["y"]
x1 = x0 + bbox["w"]
y1 = y0 + bbox["h"]
for tag in tags:
confidence = tag["confidence"]
class_name = tag["name"]
class_id = class_map.get(class_name, None)
if is_dynamic_mapping and class_id is None:
class_id = len(class_map)
class_map[class_name] = class_id
if class_id is not None:
xyxy.append([x0, y0, x1, y1])
confidences.append(confidence)
class_ids.append(class_id)
if len(xyxy) == 0:
return Detections.empty()
return cls(
xyxy=np.array(xyxy),
class_id=np.array(class_ids),
confidence=np.array(confidences),
)
@classmethod
def from_paddledet(cls, paddledet_result) -> Detections:
"""
@@ -600,7 +689,7 @@ class Detections:
tracker_id=tracker_id,
)
def get_anchor_coordinates(self, anchor: Position) -> np.ndarray:
def get_anchors_coordinates(self, anchor: Position) -> np.ndarray:
"""
Calculates and returns the coordinates of a specific anchor point
within the bounding boxes defined by the `xyxy` attribute. The anchor
@@ -627,6 +716,12 @@ class Detections:
(self.xyxy[:, 1] + self.xyxy[:, 3]) / 2,
]
).transpose()
elif anchor == Position.CENTER_OF_MASS:
if self.mask is None:
raise ValueError(
"Cannot use `Position.CENTER_OF_MASS` without a detection mask."
)
return calculate_masks_centroids(masks=self.mask)
elif anchor == Position.CENTER_LEFT:
return np.array(
[
+2 -2
View File
@@ -56,11 +56,11 @@ class PolygonZone:
"""
clipped_xyxy = clip_boxes(
boxes_xyxy=detections.xyxy, frame_resolution_wh=self.frame_resolution_wh
xyxy=detections.xyxy, resolution_wh=self.frame_resolution_wh
)
clipped_detections = replace(detections, xyxy=clipped_xyxy)
clipped_anchors = np.ceil(
clipped_detections.get_anchor_coordinates(anchor=self.triggering_position)
clipped_detections.get_anchors_coordinates(anchor=self.triggering_position)
).astype(int)
is_in_zone = self.mask[clipped_anchors[:, 1], clipped_anchors[:, 0]]
self.current_count = int(np.sum(is_in_zone))
+84 -9
View File
@@ -110,17 +110,15 @@ def non_max_suppression(
return keep[sort_index.argsort()]
def clip_boxes(
boxes_xyxy: np.ndarray, frame_resolution_wh: Tuple[int, int]
) -> np.ndarray:
def clip_boxes(xyxy: np.ndarray, resolution_wh: Tuple[int, int]) -> np.ndarray:
"""
Clips bounding boxes coordinates to fit within the frame resolution.
Args:
boxes_xyxy (np.ndarray): A numpy array of shape `(N, 4)` where each
xyxy (np.ndarray): A numpy array of shape `(N, 4)` where each
row corresponds to a bounding box in
the format `(x_min, y_min, x_max, y_max)`.
frame_resolution_wh (Tuple[int, int]): A tuple of the form `(width, height)`
resolution_wh (Tuple[int, int]): A tuple of the form `(width, height)`
representing the resolution of the frame.
Returns:
@@ -128,8 +126,8 @@ def clip_boxes(
corresponds to a bounding box with coordinates clipped to fit
within the frame resolution.
"""
result = np.copy(boxes_xyxy)
width, height = frame_resolution_wh
result = np.copy(xyxy)
width, height = resolution_wh
result[:, [0, 2]] = result[:, [0, 2]].clip(0, width)
result[:, [1, 3]] = result[:, [1, 3]].clip(0, height)
return result
@@ -385,13 +383,90 @@ def process_roboflow_result(
def move_boxes(xyxy: np.ndarray, offset: np.ndarray) -> np.ndarray:
"""
Args:
Parameters:
xyxy (np.ndarray): An array of shape `(n, 4)` containing the bounding boxes
coordinates in format `[x1, y1, x2, y2]`
offset (np.array): An array of shape `(2,)` containing offset values in format
is `[dx, dy]`.
Returns:
(np.ndarray) repositioned bounding boxes
np.ndarray: Repositioned bounding boxes.
Example:
```python
>>> import numpy as np
>>> import supervision as sv
>>> boxes = np.array([[10, 10, 20, 20], [30, 30, 40, 40]])
>>> offset = np.array([5, 5])
>>> sv.move_boxes(boxes, offset)
... array([
... [15, 15, 25, 25],
... [35, 35, 45, 45]
... ])
```
"""
return xyxy + np.hstack([offset, offset])
def scale_boxes(xyxy: np.ndarray, factor: float) -> np.ndarray:
"""
Scale the dimensions of bounding boxes.
Parameters:
xyxy (np.ndarray): An array of shape `(n, 4)` containing the bounding boxes
coordinates in format `[x1, y1, x2, y2]`
factor (float): A float value representing the factor by which the box
dimensions are scaled. A factor greater than 1 enlarges the boxes, while a
factor less than 1 shrinks them.
Returns:
np.ndarray: Scaled bounding boxes.
Example:
```python
>>> import numpy as np
>>> import supervision as sv
>>> boxes = np.array([[10, 10, 20, 20], [30, 30, 40, 40]])
>>> factor = 1.5
>>> sv.scale_boxes(boxes, factor)
... array([
... [ 7.5, 7.5, 22.5, 22.5],
... [27.5, 27.5, 42.5, 42.5]
... ])
```
"""
centers = (xyxy[:, :2] + xyxy[:, 2:]) / 2
new_sizes = (xyxy[:, 2:] - xyxy[:, :2]) * factor
return np.concatenate((centers - new_sizes / 2, centers + new_sizes / 2), axis=1)
def calculate_masks_centroids(masks: np.ndarray) -> np.ndarray:
"""
Calculate the centroids of binary masks in a tensor.
Parameters:
masks (np.ndarray): A 3D NumPy array of shape (num_masks, height, width).
Each 2D array in the tensor represents a binary mask.
Returns:
A 2D NumPy array of shape (num_masks, 2), where each row contains the x and y
coordinates (in that order) of the centroid of the corresponding mask.
"""
num_masks, height, width = masks.shape
total_pixels = masks.sum(axis=(1, 2))
# offset for 1-based indexing
vertical_indices, horizontal_indices = np.indices((height, width)) + 0.5
# avoid division by zero for empty masks
total_pixels[total_pixels == 0] = 1
def sum_over_mask(indices: np.ndarray, axis: tuple) -> np.ndarray:
return np.tensordot(masks, indices, axes=axis)
aggregation_axis = ([1, 2], [0, 1])
centroid_x = sum_over_mask(horizontal_indices, aggregation_axis) / total_pixels
centroid_y = sum_over_mask(vertical_indices, aggregation_axis) / total_pixels
return np.column_stack((centroid_x, centroid_y)).astype(int)
+15
View File
@@ -71,6 +71,21 @@ class Color:
r, g, b = (int(color_hex[i : i + 2], 16) for i in range(0, 6, 2))
return cls(r, g, b)
def as_hex(self) -> str:
"""
Converts the Color instance to a hex string.
Returns:
str: The hexadecimal color string.
Example:
```
>>> Color(r=255, g=0, b=255).as_hex()
'#ff00ff'
```
"""
return f"#{self.r:02x}{self.g:02x}{self.b:02x}"
def as_rgb(self) -> Tuple[int, int, int]:
"""
Returns the color as an RGB tuple.
+39 -1
View File
@@ -1,5 +1,5 @@
import os
from typing import Optional, Union
from typing import Optional, Tuple, Union
import cv2
import numpy as np
@@ -231,3 +231,41 @@ def draw_image(
scene[rect.y : rect.y + rect.height, rect.x : rect.x + rect.width] = blended_roi
return scene
def calculate_dynamic_text_scale(resolution_wh: Tuple[int, int]) -> float:
"""
Calculate a dynamic font scale based on the resolution of an image.
Parameters:
resolution_wh (Tuple[int, int]): A tuple representing the width and height
of the image.
Returns:
float: The calculated font scale factor.
"""
return min(resolution_wh) * 1e-3
def calculate_dynamic_line_thickness(resolution_wh: Tuple[int, int]) -> int:
"""
Calculate a dynamic line thickness based on the resolution of an image.
Parameters:
resolution_wh (Tuple[int, int]): A tuple representing the width and height
of the image.
Returns:
int: The calculated line thickness in pixels.
"""
min_dimension = min(resolution_wh)
if min_dimension < 480:
return 2
if min_dimension < 720:
return 2
if min_dimension < 1080:
return 2
if min_dimension < 2160:
return 4
else:
return 4
+1
View File
@@ -19,6 +19,7 @@ class Position(Enum):
BOTTOM_LEFT = "BOTTOM_LEFT"
BOTTOM_CENTER = "BOTTOM_CENTER"
BOTTOM_RIGHT = "BOTTOM_RIGHT"
CENTER_OF_MASS = "CENTER_OF_MASS"
@classmethod
def list(cls):
+8 -3
View File
@@ -57,19 +57,24 @@ def list_files_with_extensions(
return files_with_extensions
def read_txt_file(file_path: str) -> List[str]:
def read_txt_file(file_path: str, skip_empty: bool = False) -> List[str]:
"""
Read a text file and return a list of strings without newline characters.
Optionally skip empty lines.
Args:
file_path (str): The path to the text file.
skip_empty (bool): If True, skip lines that are empty or contain only
whitespace. Default is False.
Returns:
List[str]: A list of strings representing the lines in the text file.
"""
with open(file_path, "r") as file:
lines = file.readlines()
lines = [line.rstrip("\n") for line in lines]
if skip_empty:
lines = [line.rstrip("\n") for line in file if line.strip()]
else:
lines = [line.rstrip("\n") for line in file]
return lines
+1 -1
View File
@@ -1,5 +1,5 @@
from contextlib import ExitStack as DoesNotRaise
from test.utils import mock_detections
from test.test_utils import mock_detections
from typing import Optional
import numpy as np
+1 -1
View File
@@ -1,6 +1,6 @@
import xml.etree.ElementTree as ET
from contextlib import ExitStack as DoesNotRaise
from test.utils import mock_detections
from test.test_utils import mock_detections
from typing import List, Optional
import numpy as np
+1 -1
View File
@@ -1,5 +1,5 @@
from contextlib import ExitStack as DoesNotRaise
from test.utils import mock_detections
from test.test_utils import mock_detections
from typing import List, Optional
import numpy as np
+1 -1
View File
@@ -1,5 +1,5 @@
from contextlib import ExitStack as DoesNotRaise
from test.utils import mock_detections
from test.test_utils import mock_detections
from typing import Dict, List, Optional, Tuple, TypeVar
import pytest
+2 -2
View File
@@ -1,5 +1,5 @@
from contextlib import ExitStack as DoesNotRaise
from test.utils import mock_detections
from test.test_utils import mock_detections
from typing import List, Optional, Union
import numpy as np
@@ -270,6 +270,6 @@ def test_get_anchor_coordinates(
expected_result: np.ndarray,
exception: Exception,
) -> None:
result = detections.get_anchor_coordinates(anchor)
result = detections.get_anchors_coordinates(anchor)
with exception:
assert np.array_equal(result, expected_result)
+146 -6
View File
@@ -5,11 +5,13 @@ import numpy as np
import pytest
from supervision.detection.utils import (
calculate_masks_centroids,
clip_boxes,
filter_polygons_by_area,
move_boxes,
non_max_suppression,
process_roboflow_result,
scale_boxes,
)
TEST_MASK = np.zeros((1, 1000, 1000), dtype=bool)
@@ -122,7 +124,7 @@ def test_non_max_suppression(
@pytest.mark.parametrize(
"boxes_xyxy, frame_resolution_wh, expected_result",
"xyxy, resolution_wh, expected_result",
[
(
np.empty(shape=(0, 4)),
@@ -157,11 +159,11 @@ def test_non_max_suppression(
],
)
def test_clip_boxes(
boxes_xyxy: np.ndarray,
frame_resolution_wh: Tuple[int, int],
xyxy: np.ndarray,
resolution_wh: Tuple[int, int],
expected_result: np.ndarray,
) -> None:
result = clip_boxes(boxes_xyxy=boxes_xyxy, frame_resolution_wh=frame_resolution_wh)
result = clip_boxes(xyxy=xyxy, resolution_wh=resolution_wh)
assert np.array_equal(result, expected_result)
@@ -498,5 +500,143 @@ def test_move_boxes(
expected_result: np.ndarray,
exception: Exception,
) -> None:
result = move_boxes(xyxy=xyxy, offset=offset)
assert np.array_equal(result, expected_result)
with exception:
result = move_boxes(xyxy=xyxy, offset=offset)
assert np.array_equal(result, expected_result)
@pytest.mark.parametrize(
"xyxy, factor, expected_result, exception",
[
(
np.empty(shape=(0, 4)),
2.0,
np.empty(shape=(0, 4)),
DoesNotRaise(),
), # empty xyxy array
(
np.array([[0, 0, 10, 10]]),
1.0,
np.array([[0, 0, 10, 10]]),
DoesNotRaise(),
), # single box with factor equal to 1.0
(
np.array([[0, 0, 10, 10]]),
2.0,
np.array([[-5, -5, 15, 15]]),
DoesNotRaise(),
), # single box with factor equal to 2.0
(
np.array([[0, 0, 10, 10]]),
0.5,
np.array([[2.5, 2.5, 7.5, 7.5]]),
DoesNotRaise(),
), # single box with factor equal to 0.5
(
np.array([[0, 0, 10, 10], [10, 10, 30, 30]]),
2.0,
np.array([[-5, -5, 15, 15], [0, 0, 40, 40]]),
DoesNotRaise(),
), # two boxes with factor equal to 2.0
],
)
def test_scale_boxes(
xyxy: np.ndarray,
factor: float,
expected_result: np.ndarray,
exception: Exception,
) -> None:
with exception:
result = scale_boxes(xyxy=xyxy, factor=factor)
assert np.array_equal(result, expected_result)
@pytest.mark.parametrize(
"masks, expected_result, exception",
[
(
np.array(
[
[
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
]
]
),
np.array([[0, 0]]),
DoesNotRaise(),
), # single mask with all zeros
(
np.array(
[
[
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
]
]
),
np.array([[2, 2]]),
DoesNotRaise(),
), # single mask with all ones
(
np.array(
[
[
[0, 1, 1, 0],
[1, 1, 1, 1],
[1, 1, 1, 1],
[0, 1, 1, 0],
]
]
),
np.array([[2, 2]]),
DoesNotRaise(),
), # single mask with symmetric ones
(
np.array(
[
[
[0, 0, 0, 0],
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 0, 0],
]
]
),
np.array([[3, 2]]),
DoesNotRaise(),
), # single mask with asymmetric ones
(
np.array(
[
[
[0, 1, 1, 0],
[1, 1, 1, 1],
[1, 1, 1, 1],
[0, 1, 1, 0],
],
[
[0, 0, 0, 0],
[0, 0, 1, 1],
[0, 0, 1, 1],
[0, 0, 0, 0],
],
]
),
np.array([[2, 2], [3, 2]]),
DoesNotRaise(),
), # two masks
],
)
def test_calculate_masks_centroids(
masks: np.ndarray,
expected_result: np.ndarray,
exception: Exception,
) -> None:
with exception:
result = calculate_masks_centroids(masks=masks)
assert np.array_equal(result, expected_result)
+19
View File
@@ -30,3 +30,22 @@ def test_color_from_hex(
with exception:
result = Color.from_hex(color_hex=color_hex)
assert result == expected_result
@pytest.mark.parametrize(
"color, expected_result, exception",
[
(Color.white(), "#ffffff", DoesNotRaise()),
(Color.black(), "#000000", DoesNotRaise()),
(Color.red(), "#ff0000", DoesNotRaise()),
(Color.green(), "#00ff00", DoesNotRaise()),
(Color.blue(), "#0000ff", DoesNotRaise()),
(Color(r=128, g=128, b=0), "#808000", DoesNotRaise()),
],
)
def test_color_as_hex(
color: Color, expected_result: Optional[str], exception: Exception
) -> None:
with exception:
result = color.as_hex()
assert result == expected_result
+1 -1
View File
@@ -1,5 +1,5 @@
from contextlib import ExitStack as DoesNotRaise
from test.utils import assert_almost_equal, mock_detections
from test.test_utils import assert_almost_equal, mock_detections
from typing import Optional, Union
import numpy as np
View File
+64
View File
@@ -0,0 +1,64 @@
import os
from contextlib import ExitStack as DoesNotRaise
from typing import List, Optional
import pytest
from supervision.utils.file import read_txt_file
FILE_1_CONTENT = """Line 1
Line 2
Line 3
"""
FILE_2_CONTENT = """
Line 2
Line 4
""" # noqa
FILE_3_CONTENT = """
Line 2
Line 4
"""
@pytest.fixture(scope="module", autouse=True)
def setup_and_teardown_files():
with open("file_1.txt", "w") as file:
file.write(FILE_1_CONTENT)
with open("file_2.txt", "w") as file:
file.write(FILE_2_CONTENT)
with open("file_3.txt", "w") as file:
file.write(FILE_3_CONTENT)
yield
os.remove("file_1.txt")
os.remove("file_2.txt")
os.remove("file_3.txt")
@pytest.mark.parametrize(
"file_name, skip_empty, expected_result, exception",
[
("file_1.txt", False, ["Line 1", "Line 2", "Line 3"], DoesNotRaise()),
("file_2.txt", True, ["Line 2", "Line 4"], DoesNotRaise()),
("file_2.txt", False, [" ", "Line 2", "", "Line 4", ""], DoesNotRaise()),
("file_3.txt", True, ["Line 2", "Line 4"], DoesNotRaise()),
("file_3.txt", False, ["", "Line 2", "", "Line 4", ""], DoesNotRaise()),
("file_4.txt", True, None, pytest.raises(FileNotFoundError)),
],
)
def test_read_txt_file(
file_name: str,
skip_empty: bool,
expected_result: Optional[List[str]],
exception: Exception,
):
with exception:
result = read_txt_file(file_name, skip_empty)
assert result == expected_result