Compare commits

...
74 Commits
Author SHA1 Message Date
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
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
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
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
Onuralp SEZER b3dec1a734 Merge branch 'develop' into min-ver-settings 2023-11-15 21:39:37 +03:00
James Gallagher 82ed322fba add timm data loader 2023-11-03 18:25:09 +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
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
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
20 changed files with 1398 additions and 1053 deletions
+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.24.4
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
View File
@@ -22,4 +22,5 @@ jobs:
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
+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"
+1 -1
View File
@@ -5,7 +5,7 @@ on:
branches: [main, develop]
jobs:
build:
build-dev-test:
runs-on: ubuntu-latest
strategy:
matrix:
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
name: 👋 Welcome
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1.2.0
- 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."
+1 -1
View File
@@ -71,7 +71,7 @@ repos:
- id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.5
rev: v0.1.6
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
+49 -135
View File
@@ -41,66 +41,55 @@ Read more about desktop, headless, and local installation in our [guide](https:/
## 🔥 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
@@ -113,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)
@@ -154,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(...)
@@ -176,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
+25
View File
@@ -229,6 +229,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
@@ -337,6 +358,10 @@
:::supervision.annotators.core.BlurAnnotator
## PixelateAnnotator
:::supervision.annotators.core.PixelateAnnotator
## TraceAnnotator
:::supervision.annotators.core.TraceAnnotator
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+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
+8 -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
@@ -60,8 +60,8 @@ nav:
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
@@ -79,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
Generated
+990 -883
View File
File diff suppressed because it is too large Load Diff
+11 -11
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "supervision"
version = "0.17.0rc3"
version = "0.17.0rc7"
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,15 +36,15 @@ 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"
requests = { version = "^2.31.0", optional = true }
tqdm = { version = "^4.66.1", optional = true }
numpy = ">=1.24.0,>=1.26.1"
matplotlib = ">=3.5.0,>=3.8.1"
pyyaml = ">=5.3,<=6.0.1"
pillow = ">=9.4,<=10.1.0"
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]
@@ -57,7 +57,7 @@ pytest = "^7.2.2"
wheel = ">=0.40,<0.42"
notebook = ">=6.5.3,<8.0.0"
build = ">=0.10,<1.1"
ruff = ">=0.0.280,<0.1.6"
ruff = ">=0.0.280,<0.1.7"
isort = "^5.12.0"
black = "^23.7.0"
mypy = "^1.4.1"
+3
View File
@@ -18,6 +18,7 @@ from supervision.annotators.core import (
HeatMapAnnotator,
LabelAnnotator,
MaskAnnotator,
PixelateAnnotator,
PolygonAnnotator,
TraceAnnotator,
)
@@ -45,6 +46,8 @@ from supervision.detection.utils import (
)
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,
+77 -11
View File
@@ -30,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
@@ -112,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
@@ -195,7 +195,7 @@ class PolygonAnnotator(BaseAnnotator):
annotating detections.
thickness (int): Thickness of the polygon 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
@@ -277,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
@@ -366,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
@@ -459,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
@@ -547,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
@@ -631,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
@@ -717,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
@@ -800,7 +800,7 @@ 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
@@ -1027,7 +1027,7 @@ 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
@@ -1197,3 +1197,69 @@ 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
+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
@@ -324,7 +324,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)
```
"""
+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
+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