Merge branch 'develop' into feature/support_for_qwen_2_5_vl

This commit is contained in:
Onuralp SEZER 2025-02-18 17:07:35 +03:00
commit 2e38e8998f
No known key found for this signature in database
GPG Key ID: CF0835DFDF14CA38
18 changed files with 5735 additions and 5123 deletions

View File

@ -1,45 +0,0 @@
name: 🔧 Poetry Checks and Test Workflow
on:
push:
paths:
- "poetry.lock"
- "pyproject.toml"
pull_request:
paths:
- "poetry.lock"
- "pyproject.toml"
workflow_dispatch:
jobs:
poetry-tests:
name: Poetry install and check
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
runs-on: ${{ matrix.os }}
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: ${{ matrix.python-version }}
- name: 📜 Setup Poetry
uses: abatilo/actions-poetry@3765cf608f2d4a72178a9fc5b918668e542b89b1 # v4.0.0
- name: 🔍 Check the correctness of the project config
run: poetry check
- name: 🚀 Do Install the package Test
run: poetry install --with dev --extras metrics
- name: 🧪 Run the Import test
run: poetry run python -c "import supervision; from supervision import assets; from supervision import metrics; print(supervision.__version__)"
- name: 🧪 Run the Test
run: poetry run pytest

View File

@ -33,17 +33,25 @@ jobs:
with:
fetch-depth: 0
- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
- name: 🐍 Install uv and set Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
with:
python-version: ${{ matrix.python-version }}
- name: 📜 Setup Poetry
uses: abatilo/actions-poetry@3765cf608f2d4a72178a9fc5b918668e542b89b1 # v4.0.0
- name: 🔑 Create GitHub App token (mkdocs)
id: mkdocs_token
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1
with:
app-id: ${{ secrets.MKDOCS_APP_ID }}
private-key: ${{ secrets.MKDOCS_PEM }}
owner: roboflow
repositories: mkdocs-material-insiders
- name: 📦 Install dependencies
- name: 🏗️ Install dependencies
run: |
poetry install --with=docs
uv pip install -r pyproject.toml --extra docs
# Install mkdocs-material-insiders using the GitHub App token
uv pip install "git+https://roboflow:${{ steps.mkdocs_token.outputs.token }}@github.com/roboflow/mkdocs-material-insiders.git@9.5.49-insiders-4.53.14#egg=mkdocs-material[imaging]"
- name: ⚙️ Configure git for github-actions
run: |
@ -53,10 +61,10 @@ jobs:
- name: 🚀 Deploy Development Docs
if: (github.event_name == 'push' && github.ref == 'refs/heads/develop') || github.event_name == 'workflow_dispatch'
run: |
MKDOCS_GIT_COMMITTERS_APIKEY=${{ secrets.GITHUB_TOKEN }} poetry run mike deploy --push develop
MKDOCS_GIT_COMMITTERS_APIKEY=${{ secrets.GITHUB_TOKEN }} uv run mike deploy --push develop
- name: 🚀 Deploy Release Docs
if: github.event_name == 'release' && github.event.action == 'published'
run: |
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
MKDOCS_GIT_COMMITTERS_APIKEY=${{ secrets.GITHUB_TOKEN }} poetry run mike deploy --push --update-aliases $latest_tag latest
MKDOCS_GIT_COMMITTERS_APIKEY=${{ secrets.GITHUB_TOKEN }} uv run mike deploy --push --update-aliases $latest_tag latest

View File

@ -1,4 +1,4 @@
name: Publish Supervision Pre-Releases to PyPI and TestPyPI
name: Publish Supervision Pre-Releases to PyPI
on:
push:
@ -11,10 +11,12 @@ on:
permissions: {} # Explicitly remove all permissions by default
jobs:
build-and-publish-pre-release:
name: Publish Pre-releasePackage
publish-pre-release:
name: Publish Pre-release Package
runs-on: ubuntu-latest
environment: test
environment:
name: test
url: https://pypi.org/project/supervision/
timeout-minutes: 10
permissions:
id-token: write # Required for PyPI publishing
@ -26,27 +28,18 @@ jobs:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
with:
python-version: ${{ matrix.python-version }}
- name: 📜 Setup Poetry
uses: abatilo/actions-poetry@3765cf608f2d4a72178a9fc5b918668e542b89b1 # v4.0.0
- name: 🏗️ Build source and wheel distributions
run: |
poetry install --with=build
poetry build
poetry run twine check --strict dist/*
uv pip install -r pyproject.toml --extra build
uv build
uv run twine check --strict dist/*
- name: 🚀 Publish to PyPi
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
attestations: true
- name: 🚀 Publish to Test-PyPi
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
repository-url: https://test.pypi.org/legacy/
attestations: true

43
.github/workflows/publish-release.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Publish Supervision Releases to PyPI
on:
push:
tags:
- "[0-9]+.[0-9]+[0-9]+.[0-9]"
workflow_dispatch:
permissions: {} # Explicitly remove all permissions by default
jobs:
publish-release:
name: Publish Release Package
runs-on: ubuntu-latest
environment:
name: release
url: https://pypi.org/project/supervision/
timeout-minutes: 10
permissions:
id-token: write # Required for PyPI publishing
contents: read # Required for checkout
strategy:
matrix:
python-version: ["3.10"]
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
with:
python-version: ${{ matrix.python-version }}
- name: 🏗️ Build source and wheel distributions
run: |
uv pip install -r pyproject.toml --extra build
uv build
uv run twine check --strict dist/*
- name: 🚀 Publish to PyPi
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3
with:
attestations: true

View File

@ -1,18 +1,17 @@
name: Publish Supervision Releases to PyPI and TestPyPI
name: Publish Supervision Releases to TestPyPI
on:
push:
tags:
- "[0-9]+.[0-9]+[0-9]+.[0-9]"
workflow_dispatch:
permissions: {} # Explicitly remove all permissions by default
jobs:
build-and-publish-pre-release:
publish-testpypi:
name: Publish Release Package
runs-on: ubuntu-latest
environment: release
environment:
name: release
url: https://pypi.org/project/supervision/
timeout-minutes: 10
permissions:
id-token: write # Required for PyPI publishing
@ -24,24 +23,16 @@ jobs:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
with:
python-version: ${{ matrix.python-version }}
- name: 📜 Setup Poetry
uses: abatilo/actions-poetry@3765cf608f2d4a72178a9fc5b918668e542b89b1 # v4.0.0
- name: 🏗️ Build source and wheel distributions
run: |
poetry install --with=build
poetry build
poetry run twine check --strict dist/*
- name: 🚀 Publish to PyPi
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
attestations: true
uv pip install -r pyproject.toml --extra build
uv build
uv run twine check --strict dist/*
- name: 🚀 Publish to Test-PyPi
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4

View File

@ -23,18 +23,15 @@ jobs:
with:
fetch-depth: 0
- name: 🐍 Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
- name: 🐍 Install uv and set Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
with:
python-version: ${{ matrix.python-version }}
- name: 📜 Setup Poetry
uses: abatilo/actions-poetry@3765cf608f2d4a72178a9fc5b918668e542b89b1 # v4.0.0
- name: 🏗️ Install dependencies
run: |
poetry install --with=docs
uv pip install -r pyproject.toml --extra docs
- name: 🧪 Test Docs Build
run: |
poetry run mkdocs build --verbose
run: uv run mkdocs build --verbose

33
.github/workflows/uv-test.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: 🔧 Pytest/Test Workflow
on:
pull_request:
branches: [main, develop]
jobs:
run-tests:
name: Import Test and Pytest Run
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
runs-on: ${{ matrix.os }}
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
with:
python-version: ${{ matrix.python-version }}
- name: 🚀 Install Packages
run: uv pip install -r pyproject.toml --extra dev --extra docs --extra metrics
- name: 🧪 Run the Import test
run: uv run python -c "import supervision; from supervision import assets; from supervision import metrics; print(supervision.__version__)"
- name: 🧪 Run the Test
run: uv run pytest

View File

@ -155,31 +155,20 @@ Before starting your work on the project, set up your development environment:
source .venv/bin/activate
```
3. Install Poetry:
3. Install `uv`:
Using pip:
```bash
pip install -U pip setuptools
pip install poetry
```
Or using pipx (recommended for global installation):
```bash
pipx install poetry
```
Follow the instructions on the [uv installation page](https://docs.astral.sh/uv/getting-started/installation/).
4. Install project dependencies:
```bash
poetry install
uv pip install -r pyproject.toml --extra dev --extra docs --extra metrics
```
5. Run pytest to verify the setup:
```bash
poetry run pytest
uv run pytest
```
## 🎨 Code Style and Quality
@ -192,7 +181,7 @@ Furthermore, we have integrated a pre-commit GitHub Action into our workflow. Th
To run the pre-commit tool, follow these steps:
1. Install pre-commit by running the following command: `poetry install --with dev`. It will not only install pre-commit but also install all the deps and dev-deps of project
1. Install pre-commit by running the following command: `uv pip install -r pyproject.toml --extra dev`. It will not only install pre-commit but also install all the deps and dev-deps of project
2. Once pre-commit is installed, navigate to the project's root directory.
@ -214,7 +203,7 @@ So far, **there is no type checking with mypy**. See [issue](https://github.com/
The `supervision` documentation is stored in a folder called `docs`. The project documentation is built using `mkdocs`.
To run the documentation, install the project requirements with `poetry install --with dev`. Then, run `mkdocs serve` to start the documentation server.
To run the documentation, install the project requirements with `uv pip install -r pyproject.toml --extra dev --extra docs`. Then, run `mkdocs serve` to start the documentation server.
You can learn more about mkdocs on the [mkdocs website](https://www.mkdocs.org/).

View File

@ -89,6 +89,12 @@ status: new
:::supervision.detection.utils.xywh_to_xyxy
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.xyxy_to_xywh">xyxy_to_xywh</a></h2>
</div>
:::supervision.detection.utils.xyxy_to_xywh
<div class="md-typeset">
<h2><a href="#supervision.detection.utils.xcycwh_to_xyxy">xcycwh_to_xyxy</a></h2>
</div>

View File

@ -113,18 +113,19 @@ You can install `supervision` in a
pip install -e "."
```
=== "poetry"
=== "uv"
```bash
# clone repository and navigate to root directory
git clone --depth 1 -b develop https://github.com/roboflow/supervision.git
cd supervision
# setup python environment and activate it
poetry env use python3.10
poetry shell
uv venv
source .venv/bin/activate
# installation
poetry install
uv pip install -r pyproject.toml -e . --all-extras
```
## 🚀 Quickstart

4955
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -38,15 +38,8 @@ classifiers = [
'Operating System :: MacOS',
]
dependencies = [
# "numpy>=1.21.2,<1.26.0; python_version < '3.12'",
# "numpy>=1.26.0,<2.1.0; python_version >= '3.12' and python_version < '3.13'",
# "numpy>=2.1.0; python_version >= '3.13'",
"numpy>=1.21.2,<1.26.0; python_version < '3.10'",
"numpy>=1.26.0,<2.1.0; python_version >= '3.10' and python_version < '3.13'",
"numpy>=2.1.0; python_version >= '3.13'",
"scipy (==1.10.0); python_version < '3.9'",
"scipy (>=1.10.0,<1.14.1) ; python_version >= '3.9' and python_version < '3.13'",
"scipy (>=1.14.1); python_version >= '3.13'",
"numpy>=1.21.2",
"scipy>=1.10.0",
"matplotlib>=3.6.0",
"pyyaml>=5.3",
"defusedxml>=0.7.1",
@ -63,49 +56,40 @@ Documentation = "https://supervision.roboflow.com/latest/"
[project.optional-dependencies]
metrics = [
"pandas>=2.0.0; python_version < '3.13'",
"pandas>=2.2.3; python_version >= '3.13'"
"pandas>=2.0.0",
]
dev = [
"pytest>=7.2.2,<9.0.0",
"tox>=4.11.4",
"notebook>=6.5.3,<8.0.0",
"ipywidgets>=8.1.1",
"jupytext>=1.16.1",
"nbconvert>=7.14.2",
"docutils!=0.21"
]
docs = [
"mkdocs-material[imaging]>=9.5.5",
"mkdocstrings>=0.25.2,<0.27.0",
"mkdocstrings-python>=1.10.9",
"mike>=2.0.0",
"mkdocs-jupyter>=0.24.3",
"mkdocs-git-committers-plugin-2>=2.4.1; python_version >= '3.8' and python_version < '4'",
"mkdocs-git-revision-date-localized-plugin>=1.2.4"
]
build = [
"twine>=5.1.1,<7.0.0",
"wheel>=0.40,<0.46",
"build>=0.10,<1.3"
]
[tool.poetry]
# Keep version here since it's dynamic
packages = [{ include = "supervision" }, { include = "supervision/py.typed" }]
[tool.poetry.group.dev.dependencies]
pytest = ">=7.2.2,<9.0.0"
tox = ">=4.11.4"
notebook = ">=6.5.3,<8.0.0"
ipywidgets = ">=8.1.1"
jupytext = ">=1.16.1"
nbconvert = ">=7.14.2"
docutils = "!=0.21"
[tool.poetry.group.docs.dependencies]
mkdocs-material = { extras = ["imaging"], version = "^9.5.5" }
mkdocstrings = ">=0.25.2,<0.27.0"
mkdocstrings-python = ">=1.10.9"
mike = ">=2.0.0"
# For Documentation Development use Python 3.10 or above
# Use Latest mkdocs-jupyter min 0.24.6 for Jupyter Notebook Theme support
mkdocs-jupyter = ">=0.24.3"
mkdocs-git-committers-plugin-2 = { version = ">=2.4.1", python = ">=3.8,<4" }
mkdocs-git-revision-date-localized-plugin = ">=1.2.4"
[tool.poetry.group.build.dependencies]
twine = ">=5.1.1,<7.0.0"
wheel = ">=0.40,<0.46"
build = ">=0.10,<1.3"
[tool.bandit]
target = ["test", "supervision"]
tests = ["B201", "B301", "B318", "B314", "B303", "B413", "B412", "B410"]
tests = ["B201", "B301", "B318", "B314", "B303", "B413", "B412"]
[tool.autoflake]
check = true
imports = ["cv2", "supervision"]
[tool.ruff]
target-version = "py38"
@ -229,7 +213,7 @@ skip-magic-trailing-comma = false
line-ending = "auto"
[tool.codespell]
skip = "*.ipynb,poetry.lock"
skip = "*.ipynb"
count = true
quiet-level = 3
ignore-words-list = "STrack,sTrack,strack"
@ -238,8 +222,12 @@ ignore-words-list = "STrack,sTrack,strack"
include-package-data = false
[tool.setuptools.packages.find]
include = ["supervision*"]
exclude = ["docs*", "test*", "examples*"]
[tool.setuptools.package-data]
supervision = ["py.typed"]
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"

View File

@ -76,6 +76,7 @@ from supervision.detection.utils import (
xcycwh_to_xyxy,
xywh_to_xyxy,
xyxy_to_polygons,
xyxy_to_xywh,
)
from supervision.detection.vlm import LMM, VLM
from supervision.draw.color import Color, ColorPalette
@ -224,4 +225,5 @@ __all__ = [
"xcycwh_to_xyxy",
"xywh_to_xyxy",
"xyxy_to_polygons",
"xyxy_to_xywh",
]

View File

@ -321,6 +321,43 @@ def xywh_to_xyxy(xywh: np.ndarray) -> np.ndarray:
return xyxy
def xyxy_to_xywh(xyxy: np.ndarray) -> np.ndarray:
"""
Converts bounding box coordinates from `(x_min, y_min, x_max, y_max)`
format to `(x, y, width, height)` format.
Args:
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)`.
Returns:
np.ndarray: A numpy array of shape `(N, 4)` where each row corresponds
to a bounding box in the format `(x, y, width, height)`.
Examples:
```python
import numpy as np
import supervision as sv
xyxy = np.array([
[10, 20, 40, 60],
[15, 25, 50, 70]
])
sv.xyxy_to_xywh(xyxy=xyxy)
# array([
# [10, 20, 30, 40],
# [15, 25, 35, 45]
# ])
```
"""
xywh = xyxy.copy()
xywh[:, 2] = xyxy[:, 2] - xyxy[:, 0]
xywh[:, 3] = xyxy[:, 3] - xyxy[:, 1]
return xywh
def xcycwh_to_xyxy(xcycwh: np.ndarray) -> np.ndarray:
"""
Converts bounding box coordinates from `(center_x, center_y, width, height)`

View File

@ -61,6 +61,7 @@ class KeyPoints:
method, which accepts [MediaPipe](https://github.com/google-ai-edge/mediapipe)
pose result.
```python
import cv2
import mediapipe as mp
@ -314,6 +315,7 @@ class KeyPoints:
key_points = sv.KeyPoints.from_mediapipe(
face_landmarker_result, (image_width, image_height))
```
""" # noqa: E501 // docs
if hasattr(mediapipe_results, "pose_landmarks"):
results = mediapipe_results.pose_landmarks
@ -473,7 +475,7 @@ class KeyPoints:
A `sv.KeyPoints` object containing the keypoint coordinates, class IDs,
and class names, and confidences of each keypoint.
Example:
Examples:
```python
import cv2
import supervision as sv
@ -510,6 +512,91 @@ class KeyPoints:
else:
return cls.empty()
@classmethod
def from_transformers(cls, transfomers_results: Any) -> KeyPoints:
"""
Create a `sv.KeyPoints` object from the
[Transformers](https://github.com/huggingface/transformers) inference result.
Args:
transfomers_results (Any): The output of a
Transformers model containing instances with prediction data.
Returns:
A `sv.KeyPoints` object containing the keypoint coordinates, class IDs,
and class names, and confidences of each keypoint.
Examples:
```python
from PIL import Image
import requests
import supervision as sv
import torch
from transformers import (
AutoProcessor,
RTDetrForObjectDetection,
VitPoseForPoseEstimation,
)
device = "cuda" if torch.cuda.is_available() else "cpu"
image = Image.open(<SOURCE_IMAGE_PATH>)
DETECTION_MODEL_ID = "PekingU/rtdetr_r50vd_coco_o365"
detection_processor = AutoProcessor.from_pretrained(DETECTION_MODEL_ID, use_fast=True)
detection_model = RTDetrForObjectDetection.from_pretrained(DETECTION_MODEL_ID, device_map=DEVICE)
inputs = detection_processor(images=frame, return_tensors="pt").to(DEVICE)
with torch.no_grad():
outputs = detection_model(**inputs)
target_size = torch.tensor([(frame.height, frame.width)])
results = detection_processor.post_process_object_detection(
outputs, target_sizes=target_size, threshold=0.3)
detections = sv.Detections.from_transformers(results[0])
boxes = sv.xyxy_to_xywh(detections[detections.class_id == 0].xyxy)
POSE_ESTIMATION_MODEL_ID = "usyd-community/vitpose-base-simple"
pose_estimation_processor = AutoProcessor.from_pretrained(POSE_ESTIMATION_MODEL_ID)
pose_estimation_model = VitPoseForPoseEstimation.from_pretrained(
POSE_ESTIMATION_MODEL_ID, device_map=DEVICE)
inputs = pose_estimation_processor(frame, boxes=[boxes], return_tensors="pt").to(DEVICE)
with torch.no_grad():
outputs = pose_estimation_model(**inputs)
results = pose_estimation_processor.post_process_pose_estimation(outputs, boxes=[boxes])
key_point = sv.KeyPoints.from_transformers(results[0])
```
""" # noqa: E501 // docs
if "keypoints" in transfomers_results[0]:
if transfomers_results[0]["keypoints"].cpu().numpy().size == 0:
return cls.empty()
result_data = [
(
result["keypoints"].cpu().numpy(),
result["scores"].cpu().numpy(),
)
for result in transfomers_results
]
xy, scores = zip(*result_data)
return cls(
xy=np.stack(xy).astype(np.float32),
confidence=np.stack(scores).astype(np.float32),
class_id=np.arange(len(xy)).astype(int),
)
else:
return cls.empty()
def __getitem__(
self, index: Union[int, slice, List[int], np.ndarray, str]
) -> Union[KeyPoints, List, np.ndarray, None]:
@ -639,7 +726,7 @@ class KeyPoints:
Returns:
detections (Detections): The converted detections object.
Example:
Examples:
```python
keypoints = sv.KeyPoints.from_inference(...)
detections = keypoints.as_detections()

View File

@ -5,5 +5,6 @@ def ensure_pandas_installed():
raise ImportError(
"`metrics` extra is required to run the function."
" Run `pip install 'supervision[metrics]'` or"
" `poetry add supervision -E metrics`"
" `poetry add supervision -E metrics` or"
" `uv pip install 'supervision[metrics]'`"
)

View File

@ -21,6 +21,7 @@ from supervision.detection.utils import (
scale_boxes,
xcycwh_to_xyxy,
xywh_to_xyxy,
xyxy_to_xywh,
)
TEST_MASK = np.zeros((1, 1000, 1000), dtype=bool)
@ -1381,6 +1382,29 @@ def test_xywh_to_xyxy(xywh: np.ndarray, expected_result: np.ndarray) -> None:
np.testing.assert_array_equal(result, expected_result)
@pytest.mark.parametrize(
"xyxy, expected_result",
[
(np.array([[10, 20, 40, 60]]), np.array([[10, 20, 30, 40]])), # standard case
(np.array([[0, 0, 0, 0]]), np.array([[0, 0, 0, 0]])), # zero size bounding box
(
np.array([[50, 50, 150, 150]]),
np.array([[50, 50, 100, 100]]),
), # large bounding box
(
np.array([[-10, -20, 20, 20]]),
np.array([[-10, -20, 30, 40]]),
), # negative coordinates
(np.array([[50, 50, 50, 80]]), np.array([[50, 50, 0, 30]])), # zero width
(np.array([[50, 50, 70, 50]]), np.array([[50, 50, 20, 0]])), # zero height
(np.array([]).reshape(0, 4), np.array([]).reshape(0, 4)), # empty array
],
)
def test_xyxy_to_xywh(xyxy: np.ndarray, expected_result: np.ndarray) -> None:
result = xyxy_to_xywh(xyxy)
np.testing.assert_array_equal(result, expected_result)
@pytest.mark.parametrize(
"xcycwh, expected_result",
[

5412
uv.lock Normal file

File diff suppressed because it is too large Load Diff