Compare commits

...
55 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
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
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
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
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
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
12 changed files with 425 additions and 45 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ idna==3.4
iniconfig==2.0.0
kiwisolver==1.4.5
matplotlib==3.5.0
numpy==1.24.4
numpy==1.21.2
opencv-python==4.5.5.64
packaging==23.2
Pillow==10.1.0
+1 -1
View File
@@ -34,7 +34,7 @@ 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/).
+30 -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
@@ -318,9 +339,9 @@
:::supervision.annotators.core.BoxCornerAnnotator
## BoxMaskAnnotator
## ColorAnnotator
:::supervision.annotators.core.BoxMaskAnnotator
:::supervision.annotators.core.ColorAnnotator
## CircleAnnotator
@@ -330,6 +351,10 @@
:::supervision.annotators.core.DotAnnotator
## TriangleAnnotator
:::supervision.annotators.core.TriangleAnnotator
## EllipseAnnotator
:::supervision.annotators.core.EllipseAnnotator
+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
Generated
+42 -22
View File
@@ -1630,6 +1630,16 @@ files = [
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
{file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
{file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
@@ -2775,6 +2785,7 @@ files = [
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
@@ -2782,8 +2793,15 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
@@ -2800,6 +2818,7 @@ files = [
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
@@ -2807,6 +2826,7 @@ files = [
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
@@ -3265,28 +3285,28 @@ files = [
[[package]]
name = "ruff"
version = "0.1.6"
version = "0.1.7"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.1.6-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:88b8cdf6abf98130991cbc9f6438f35f6e8d41a02622cc5ee130a02a0ed28703"},
{file = "ruff-0.1.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5c549ed437680b6105a1299d2cd30e4964211606eeb48a0ff7a93ef70b902248"},
{file = "ruff-0.1.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cf5f701062e294f2167e66d11b092bba7af6a057668ed618a9253e1e90cfd76"},
{file = "ruff-0.1.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:05991ee20d4ac4bb78385360c684e4b417edd971030ab12a4fbd075ff535050e"},
{file = "ruff-0.1.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87455a0c1f739b3c069e2f4c43b66479a54dea0276dd5d4d67b091265f6fd1dc"},
{file = "ruff-0.1.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:683aa5bdda5a48cb8266fcde8eea2a6af4e5700a392c56ea5fb5f0d4bfdc0240"},
{file = "ruff-0.1.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:137852105586dcbf80c1717facb6781555c4e99f520c9c827bd414fac67ddfb6"},
{file = "ruff-0.1.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd98138a98d48a1c36c394fd6b84cd943ac92a08278aa8ac8c0fdefcf7138f35"},
{file = "ruff-0.1.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0cd909d25f227ac5c36d4e7e681577275fb74ba3b11d288aff7ec47e3ae745"},
{file = "ruff-0.1.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8fd1c62a47aa88a02707b5dd20c5ff20d035d634aa74826b42a1da77861b5ff"},
{file = "ruff-0.1.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fd89b45d374935829134a082617954120d7a1470a9f0ec0e7f3ead983edc48cc"},
{file = "ruff-0.1.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:491262006e92f825b145cd1e52948073c56560243b55fb3b4ecb142f6f0e9543"},
{file = "ruff-0.1.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ea284789861b8b5ca9d5443591a92a397ac183d4351882ab52f6296b4fdd5462"},
{file = "ruff-0.1.6-py3-none-win32.whl", hash = "sha256:1610e14750826dfc207ccbcdd7331b6bd285607d4181df9c1c6ae26646d6848a"},
{file = "ruff-0.1.6-py3-none-win_amd64.whl", hash = "sha256:4558b3e178145491e9bc3b2ee3c4b42f19d19384eaa5c59d10acf6e8f8b57e33"},
{file = "ruff-0.1.6-py3-none-win_arm64.whl", hash = "sha256:03910e81df0d8db0e30050725a5802441c2022ea3ae4fe0609b76081731accbc"},
{file = "ruff-0.1.6.tar.gz", hash = "sha256:1b09f29b16c6ead5ea6b097ef2764b42372aebe363722f1605ecbcd2b9207184"},
{file = "ruff-0.1.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7f80496854fdc65b6659c271d2c26e90d4d401e6a4a31908e7e334fab4645aac"},
{file = "ruff-0.1.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1ea109bdb23c2a4413f397ebd8ac32cb498bee234d4191ae1a310af760e5d287"},
{file = "ruff-0.1.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0c2de9dd9daf5e07624c24add25c3a490dbf74b0e9bca4145c632457b3b42a"},
{file = "ruff-0.1.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:69a4bed13bc1d5dabf3902522b5a2aadfebe28226c6269694283c3b0cecb45fd"},
{file = "ruff-0.1.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de02ca331f2143195a712983a57137c5ec0f10acc4aa81f7c1f86519e52b92a1"},
{file = "ruff-0.1.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45b38c3f8788a65e6a2cab02e0f7adfa88872696839d9882c13b7e2f35d64c5f"},
{file = "ruff-0.1.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c64cb67b2025b1ac6d58e5ffca8f7b3f7fd921f35e78198411237e4f0db8e73"},
{file = "ruff-0.1.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dcc6bb2f4df59cb5b4b40ff14be7d57012179d69c6565c1da0d1f013d29951b"},
{file = "ruff-0.1.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2bb4bb6bbe921f6b4f5b6fdd8d8468c940731cb9406f274ae8c5ed7a78c478"},
{file = "ruff-0.1.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:276a89bcb149b3d8c1b11d91aa81898fe698900ed553a08129b38d9d6570e717"},
{file = "ruff-0.1.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:90c958fe950735041f1c80d21b42184f1072cc3975d05e736e8d66fc377119ea"},
{file = "ruff-0.1.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6b05e3b123f93bb4146a761b7a7d57af8cb7384ccb2502d29d736eaade0db519"},
{file = "ruff-0.1.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:290ecab680dce94affebefe0bbca2322a6277e83d4f29234627e0f8f6b4fa9ce"},
{file = "ruff-0.1.7-py3-none-win32.whl", hash = "sha256:416dfd0bd45d1a2baa3b1b07b1b9758e7d993c256d3e51dc6e03a5e7901c7d80"},
{file = "ruff-0.1.7-py3-none-win_amd64.whl", hash = "sha256:4af95fd1d3b001fc41325064336db36e3d27d2004cdb6d21fd617d45a172dd96"},
{file = "ruff-0.1.7-py3-none-win_arm64.whl", hash = "sha256:0683b7bfbb95e6df3c7c04fe9d78f631f8e8ba4868dfc932d43d690698057e2e"},
{file = "ruff-0.1.7.tar.gz", hash = "sha256:dffd699d07abf54833e5f6cc50b85a6ff043715da8788c4a79bcd4ab4734d306"},
]
[[package]]
@@ -3741,13 +3761,13 @@ test = ["websockets"]
[[package]]
name = "wheel"
version = "0.41.3"
version = "0.42.0"
description = "A built-package format for Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "wheel-0.41.3-py3-none-any.whl", hash = "sha256:488609bc63a29322326e05560731bf7bfea8e48ad646e1f5e40d366607de0942"},
{file = "wheel-0.41.3.tar.gz", hash = "sha256:4d4987ce51a49370ea65c0bfd2234e8ce80a12780820d9dc462597a6e60d0841"},
{file = "wheel-0.42.0-py3-none-any.whl", hash = "sha256:177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d"},
{file = "wheel-0.42.0.tar.gz", hash = "sha256:c45be39f7882c9d34243236f2d63cbd58039e360f85d0913425fbd7ceea617a8"},
]
[package.extras]
@@ -3775,4 +3795,4 @@ desktop = ["opencv-python"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.8,<3.12.0"
content-hash = "abbd8c3b0bbed2349aa2ba8f4a822ab44d1092ea8b60118dc83fe11737e4ca12"
content-hash = "62ad5b29a089dde783bbbe3f0df6ed314c602f7ae329bb2623f52b61d5d83e37"
+6 -6
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "supervision"
version = "0.17.0rc7"
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,10 +36,10 @@ classifiers=[
[tool.poetry.dependencies]
python = ">=3.8,<3.12.0"
numpy = ">=1.24.0,>=1.26.1"
matplotlib = ">=3.5.0,>=3.8.1"
numpy = ">=1.21.2"
matplotlib = ">=3.5.0"
pyyaml = ">=5.3,<=6.0.1"
pillow = ">=9.4,<=10.1.0"
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"
@@ -54,10 +54,10 @@ assets = ["requests","tqdm"]
[tool.poetry.group.dev.dependencies]
twine = "^4.0.2"
pytest = "^7.2.2"
wheel = ">=0.40,<0.42"
wheel = ">=0.40,<0.43"
notebook = ">=6.5.3,<8.0.0"
build = ">=0.10,<1.1"
ruff = ">=0.0.280,<0.1.7"
ruff = ">=0.0.280,<0.1.8"
isort = "^5.12.0"
black = "^23.7.0"
mypy = "^1.4.1"
+4 -1
View File
@@ -10,8 +10,8 @@ from supervision.annotators.core import (
BlurAnnotator,
BoundingBoxAnnotator,
BoxCornerAnnotator,
BoxMaskAnnotator,
CircleAnnotator,
ColorAnnotator,
DotAnnotator,
EllipseAnnotator,
HaloAnnotator,
@@ -21,6 +21,7 @@ from supervision.annotators.core import (
PixelateAnnotator,
PolygonAnnotator,
TraceAnnotator,
TriangleAnnotator,
)
from supervision.annotators.utils import ColorLookup
from supervision.classification.core import Classifications
@@ -40,9 +41,11 @@ from supervision.detection.utils import (
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 (
+94 -5
View File
@@ -260,7 +260,7 @@ class PolygonAnnotator(BaseAnnotator):
return scene
class BoxMaskAnnotator(BaseAnnotator):
class ColorAnnotator(BaseAnnotator):
"""
A class for drawing box masks on an image using provided detections.
"""
@@ -308,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
... )
@@ -1030,8 +1030,7 @@ class TraceAnnotator:
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
@@ -1263,3 +1262,93 @@ class PixelateAnnotator(BaseAnnotator):
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
+90 -2
View File
@@ -1,7 +1,7 @@
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
@@ -64,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]`
@@ -461,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)
@@ -484,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:
"""
+49 -2
View File
@@ -383,18 +383,65 @@ 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.
+47
View File
@@ -11,6 +11,7 @@ from supervision.detection.utils import (
move_boxes,
non_max_suppression,
process_roboflow_result,
scale_boxes,
)
TEST_MASK = np.zeros((1, 1000, 1000), dtype=bool)
@@ -504,6 +505,52 @@ def test_move_boxes(
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",
[