refactor: 🧪 type hints to use the new union syntax for optional types
- Updated type hints across multiple files to replace `Optional[X]` with `X | None` for better readability and consistency. - Added `from __future__ import annotations` to files to enable postponed evaluation of type annotations. - Adjusted function signatures and variable types in various modules including `polygon_zone.py`, `smoother.py`, `transformers.py`, `vlm.py`, and others. - Ensured compatibility with Python 3.10+ type hinting features. Signed-off-by: Onuralp SEZER <thunderbirdtr@gmail.com>
This commit is contained in:
42 files changed
+320
-280
No files matched your search
@@ -58,6 +58,6 @@ repos:
|
||||
rev: v3.20.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: ["--py39-plus"]
|
||||
args: ["--py310-plus"]
|
||||
additional_dependencies:
|
||||
- tomli
|
||||
@@ -1,11 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from pytube import YouTube
|
||||
|
||||
|
||||
def main(url: str, output_path: Optional[str], file_name: Optional[str]) -> None:
|
||||
def main(url: str, output_path: str | None, file_name: str | None) -> None:
|
||||
yt = YouTube(url)
|
||||
stream = yt.streams.get_highest_resolution()
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -19,10 +21,10 @@ COLORS = sv.ColorPalette.DEFAULT
|
||||
WINDOW_NAME = "Draw Zones"
|
||||
POLYGONS = [[]]
|
||||
|
||||
current_mouse_position: Optional[tuple[int, int]] = None
|
||||
current_mouse_position: tuple[int, int] | None = None
|
||||
|
||||
|
||||
def resolve_source(source_path: str) -> Optional[np.ndarray]:
|
||||
def resolve_source(source_path: str) -> np.ndarray | None:
|
||||
if not os.path.exists(source_path):
|
||||
return None
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -78,7 +79,7 @@ class VideoProcessor:
|
||||
roboflow_api_key: str,
|
||||
model_id: str,
|
||||
source_video_path: str,
|
||||
target_video_path: Optional[str] = None,
|
||||
target_video_path: str | None = None,
|
||||
confidence_threshold: float = 0.3,
|
||||
iou_threshold: float = 0.7,
|
||||
) -> None:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -75,7 +76,7 @@ class VideoProcessor:
|
||||
self,
|
||||
source_weights_path: str,
|
||||
source_video_path: str,
|
||||
target_video_path: Optional[str] = None,
|
||||
target_video_path: str | None = None,
|
||||
confidence_threshold: float = 0.3,
|
||||
iou_threshold: float = 0.7,
|
||||
) -> None:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import lru_cache
|
||||
from math import sqrt
|
||||
from typing import Optional, Union
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -65,14 +66,14 @@ class _BaseLabelAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
text_color: Union[Color, ColorPalette] = Color.WHITE,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
text_color: Color | ColorPalette = Color.WHITE,
|
||||
text_padding: int = 10,
|
||||
text_position: Position = Position.TOP_LEFT,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
border_radius: int = 0,
|
||||
smart_position: bool = False,
|
||||
max_line_length: Optional[int] = None,
|
||||
max_line_length: int | None = None,
|
||||
):
|
||||
"""
|
||||
Initializes the _BaseLabelAnnotator.
|
||||
@@ -95,14 +96,14 @@ class _BaseLabelAnnotator(BaseAnnotator):
|
||||
line before wrapping the text. None means no wrapping.
|
||||
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.text_color: Union[Color, ColorPalette] = text_color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.text_color: Color | ColorPalette = text_color
|
||||
self.text_padding: int = text_padding
|
||||
self.text_anchor: Position = text_position
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
self.border_radius: int = border_radius
|
||||
self.smart_position = smart_position
|
||||
self.max_line_length: Optional[int] = max_line_length
|
||||
self.max_line_length: int | None = max_line_length
|
||||
|
||||
def _adjust_labels_in_frame(
|
||||
self,
|
||||
@@ -155,7 +156,7 @@ class BoxAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
thickness: int = 2,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
):
|
||||
@@ -167,7 +168,7 @@ class BoxAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.thickness: int = thickness
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
|
||||
@@ -176,7 +177,7 @@ class BoxAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with bounding boxes based on the provided detections.
|
||||
@@ -238,7 +239,7 @@ class OrientedBoxAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
thickness: int = 2,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
):
|
||||
@@ -250,7 +251,7 @@ class OrientedBoxAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.thickness: int = thickness
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
|
||||
@@ -259,7 +260,7 @@ class OrientedBoxAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with oriented bounding boxes based on the provided detections.
|
||||
@@ -327,7 +328,7 @@ class MaskAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
opacity: float = 0.5,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
):
|
||||
@@ -339,7 +340,7 @@ class MaskAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.opacity = opacity
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
|
||||
@@ -348,7 +349,7 @@ class MaskAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with masks based on the provided detections.
|
||||
@@ -417,7 +418,7 @@ class PolygonAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
thickness: int = 2,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
):
|
||||
@@ -429,7 +430,7 @@ class PolygonAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.thickness: int = thickness
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
|
||||
@@ -438,7 +439,7 @@ class PolygonAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with polygons based on the provided detections.
|
||||
@@ -504,7 +505,7 @@ class ColorAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
opacity: float = 0.5,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
):
|
||||
@@ -516,7 +517,7 @@ class ColorAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
self.opacity = opacity
|
||||
|
||||
@@ -525,7 +526,7 @@ class ColorAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with box masks based on the provided detections.
|
||||
@@ -596,7 +597,7 @@ class HaloAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
opacity: float = 0.8,
|
||||
kernel_size: int = 40,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
@@ -611,7 +612,7 @@ class HaloAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.opacity = opacity
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
self.kernel_size: int = kernel_size
|
||||
@@ -621,7 +622,7 @@ class HaloAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with halos based on the provided detections.
|
||||
@@ -694,7 +695,7 @@ class EllipseAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
thickness: int = 2,
|
||||
start_angle: int = -45,
|
||||
end_angle: int = 235,
|
||||
@@ -710,7 +711,7 @@ class EllipseAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.thickness: int = thickness
|
||||
self.start_angle: int = start_angle
|
||||
self.end_angle: int = end_angle
|
||||
@@ -721,7 +722,7 @@ class EllipseAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with ellipses based on the provided detections.
|
||||
@@ -789,7 +790,7 @@ class BoxCornerAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
thickness: int = 4,
|
||||
corner_length: int = 15,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
@@ -803,7 +804,7 @@ class BoxCornerAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.thickness: int = thickness
|
||||
self.corner_length: int = corner_length
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
@@ -813,7 +814,7 @@ class BoxCornerAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with box corners based on the provided detections.
|
||||
@@ -880,7 +881,7 @@ class CircleAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
thickness: int = 2,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
):
|
||||
@@ -893,7 +894,7 @@ class CircleAnnotator(BaseAnnotator):
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.thickness: int = thickness
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
|
||||
@@ -902,7 +903,7 @@ class CircleAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with circles based on the provided detections.
|
||||
@@ -969,12 +970,12 @@ class DotAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
radius: int = 4,
|
||||
position: Position = Position.CENTER,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
outline_thickness: int = 0,
|
||||
outline_color: Union[Color, ColorPalette] = Color.BLACK,
|
||||
outline_color: Color | ColorPalette = Color.BLACK,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
@@ -989,19 +990,19 @@ class DotAnnotator(BaseAnnotator):
|
||||
use for outline. It is activated by setting outline_thickness to a value
|
||||
greater than 0.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.radius: int = radius
|
||||
self.position: Position = position
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
self.outline_thickness = outline_thickness
|
||||
self.outline_color: Union[Color, ColorPalette] = outline_color
|
||||
self.outline_color: Color | ColorPalette = outline_color
|
||||
|
||||
@ensure_cv2_image_for_annotation
|
||||
def annotate(
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with dots based on the provided detections.
|
||||
@@ -1075,8 +1076,8 @@ class LabelAnnotator(_BaseLabelAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
text_color: Union[Color, ColorPalette] = Color.WHITE,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
text_color: Color | ColorPalette = Color.WHITE,
|
||||
text_scale: float = 0.5,
|
||||
text_thickness: int = 1,
|
||||
text_padding: int = 10,
|
||||
@@ -1084,7 +1085,7 @@ class LabelAnnotator(_BaseLabelAnnotator):
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
border_radius: int = 0,
|
||||
smart_position: bool = False,
|
||||
max_line_length: Optional[int] = None,
|
||||
max_line_length: int | None = None,
|
||||
):
|
||||
self.text_scale: float = text_scale
|
||||
self.text_thickness: int = text_thickness
|
||||
@@ -1104,8 +1105,8 @@ class LabelAnnotator(_BaseLabelAnnotator):
|
||||
self,
|
||||
scene: ImageType, # Ensure scene is initially a NumPy array here
|
||||
detections: Detections,
|
||||
labels: Optional[list[str]] = None,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
labels: list[str] | None = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> np.ndarray:
|
||||
assert isinstance(scene, np.ndarray)
|
||||
validate_labels(labels, detections)
|
||||
@@ -1189,7 +1190,7 @@ class LabelAnnotator(_BaseLabelAnnotator):
|
||||
labels: list[str],
|
||||
label_properties: np.ndarray,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray],
|
||||
custom_color_lookup: np.ndarray | None,
|
||||
) -> None:
|
||||
assert len(labels) == len(label_properties) == len(detections), (
|
||||
f"Number of label properties ({len(label_properties)}), "
|
||||
@@ -1316,16 +1317,16 @@ class RichLabelAnnotator(_BaseLabelAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
text_color: Union[Color, ColorPalette] = Color.WHITE,
|
||||
font_path: Optional[str] = None,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
text_color: Color | ColorPalette = Color.WHITE,
|
||||
font_path: str | None = None,
|
||||
font_size: int = 10,
|
||||
text_padding: int = 10,
|
||||
text_position: Position = Position.TOP_LEFT,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
border_radius: int = 0,
|
||||
smart_position: bool = False,
|
||||
max_line_length: Optional[int] = None,
|
||||
max_line_length: int | None = None,
|
||||
):
|
||||
self.font_path = font_path
|
||||
self.font_size = font_size
|
||||
@@ -1346,8 +1347,8 @@ class RichLabelAnnotator(_BaseLabelAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
labels: Optional[list[str]] = None,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
labels: list[str] | None = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
assert isinstance(scene, Image.Image)
|
||||
validate_labels(labels, detections)
|
||||
@@ -1427,7 +1428,7 @@ class RichLabelAnnotator(_BaseLabelAnnotator):
|
||||
labels: list[str],
|
||||
label_properties: np.ndarray,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray],
|
||||
custom_color_lookup: np.ndarray | None,
|
||||
) -> None:
|
||||
assert len(labels) == len(label_properties) == len(detections), (
|
||||
f"Number of label properties ({len(label_properties)}), "
|
||||
@@ -1485,7 +1486,7 @@ class RichLabelAnnotator(_BaseLabelAnnotator):
|
||||
y_position += line_height + self.text_padding
|
||||
|
||||
@staticmethod
|
||||
def _load_font(font_size: int, font_path: Optional[str]):
|
||||
def _load_font(font_size: int, font_path: str | None):
|
||||
def load_default_font(size):
|
||||
try:
|
||||
return ImageFont.load_default(size)
|
||||
@@ -1527,7 +1528,7 @@ class IconAnnotator(BaseAnnotator):
|
||||
|
||||
@ensure_cv2_image_for_annotation
|
||||
def annotate(
|
||||
self, scene: ImageType, detections: Detections, icon_path: Union[str, list[str]]
|
||||
self, scene: ImageType, detections: Detections, icon_path: str | list[str]
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with given icons.
|
||||
@@ -1677,7 +1678,7 @@ class TraceAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
position: Position = Position.CENTER,
|
||||
trace_length: int = 30,
|
||||
thickness: int = 2,
|
||||
@@ -1695,7 +1696,7 @@ class TraceAnnotator(BaseAnnotator):
|
||||
color_lookup (ColorLookup): Strategy for mapping colors to annotations.
|
||||
Options are `INDEX`, `CLASS`, `TRACK`.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.trace = Trace(max_size=trace_length, anchor=position)
|
||||
self.thickness = thickness
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
@@ -1705,7 +1706,7 @@ class TraceAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Draws trace paths on the frame based on the detection coordinates provided.
|
||||
@@ -1812,7 +1813,7 @@ class HeatMapAnnotator(BaseAnnotator):
|
||||
self.kernel_size = kernel_size
|
||||
self.top_hue = top_hue
|
||||
self.low_hue = low_hue
|
||||
self.heat_mask: Optional[npt.NDArray[np.float32]] = None
|
||||
self.heat_mask: npt.NDArray[np.float32] | None = None
|
||||
|
||||
@ensure_cv2_image_for_annotation
|
||||
def annotate(self, scene: ImageType, detections: Detections) -> ImageType:
|
||||
@@ -1963,13 +1964,13 @@ class TriangleAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
base: int = 10,
|
||||
height: int = 10,
|
||||
position: Position = Position.TOP_CENTER,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
outline_thickness: int = 0,
|
||||
outline_color: Union[Color, ColorPalette] = Color.BLACK,
|
||||
outline_color: Color | ColorPalette = Color.BLACK,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
@@ -1985,20 +1986,20 @@ class TriangleAnnotator(BaseAnnotator):
|
||||
use for outline. It is activated by setting outline_thickness to a value
|
||||
greater than 0.
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.base: int = base
|
||||
self.height: int = height
|
||||
self.position: Position = position
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
self.outline_thickness: int = outline_thickness
|
||||
self.outline_color: Union[Color, ColorPalette] = outline_color
|
||||
self.outline_color: Color | ColorPalette = outline_color
|
||||
|
||||
@ensure_cv2_image_for_annotation
|
||||
def annotate(
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with triangles based on the provided detections.
|
||||
@@ -2081,7 +2082,7 @@ class RoundBoxAnnotator(BaseAnnotator):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
thickness: int = 2,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
roundness: float = 0.6,
|
||||
@@ -2098,7 +2099,7 @@ class RoundBoxAnnotator(BaseAnnotator):
|
||||
By default roundness percent is calculated based on smaller side
|
||||
length (width or height).
|
||||
"""
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.thickness: int = thickness
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
if not 0 < roundness <= 1.0:
|
||||
@@ -2110,7 +2111,7 @@ class RoundBoxAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with bounding boxes with rounded edges
|
||||
@@ -2214,11 +2215,11 @@ class PercentageBarAnnotator(BaseAnnotator):
|
||||
self,
|
||||
height: int = 16,
|
||||
width: int = 80,
|
||||
color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
border_color: Color = Color.BLACK,
|
||||
position: Position = Position.TOP_CENTER,
|
||||
color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
border_thickness: Optional[int] = None,
|
||||
border_thickness: int | None = None,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
@@ -2234,7 +2235,7 @@ class PercentageBarAnnotator(BaseAnnotator):
|
||||
"""
|
||||
self.height: int = height
|
||||
self.width: int = width
|
||||
self.color: Union[Color, ColorPalette] = color
|
||||
self.color: Color | ColorPalette = color
|
||||
self.border_color: Color = border_color
|
||||
self.position: Position = position
|
||||
self.color_lookup: ColorLookup = color_lookup
|
||||
@@ -2247,8 +2248,8 @@ class PercentageBarAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_values: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
custom_values: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the given scene with percentage bars based on the provided
|
||||
@@ -2366,7 +2367,7 @@ class PercentageBarAnnotator(BaseAnnotator):
|
||||
|
||||
@staticmethod
|
||||
def validate_custom_values(
|
||||
custom_values: Optional[Union[np.ndarray, list[float]]], detections: Detections
|
||||
custom_values: np.ndarray | list[float] | None, detections: Detections
|
||||
) -> None:
|
||||
if custom_values is None:
|
||||
if detections.confidence is None:
|
||||
@@ -2400,7 +2401,7 @@ class CropAnnotator(BaseAnnotator):
|
||||
self,
|
||||
position: Position = Position.TOP_CENTER,
|
||||
scale_factor: float = 2.0,
|
||||
border_color: Union[Color, ColorPalette] = ColorPalette.DEFAULT,
|
||||
border_color: Color | ColorPalette = ColorPalette.DEFAULT,
|
||||
border_thickness: int = 2,
|
||||
border_color_lookup: ColorLookup = ColorLookup.CLASS,
|
||||
):
|
||||
@@ -2419,7 +2420,7 @@ class CropAnnotator(BaseAnnotator):
|
||||
"""
|
||||
self.position: Position = position
|
||||
self.scale_factor: float = scale_factor
|
||||
self.border_color: Union[Color, ColorPalette] = border_color
|
||||
self.border_color: Color | ColorPalette = border_color
|
||||
self.border_thickness: int = border_thickness
|
||||
self.border_color_lookup: ColorLookup = border_color_lookup
|
||||
|
||||
@@ -2428,7 +2429,7 @@ class CropAnnotator(BaseAnnotator):
|
||||
self,
|
||||
scene: ImageType,
|
||||
detections: Detections,
|
||||
custom_color_lookup: Optional[np.ndarray] = None,
|
||||
custom_color_lookup: np.ndarray | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Annotates the provided scene with scaled and cropped parts of the image based
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import textwrap
|
||||
from enum import Enum
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -35,7 +36,7 @@ class ColorLookup(Enum):
|
||||
def resolve_color_idx(
|
||||
detections: Detections,
|
||||
detection_idx: int,
|
||||
color_lookup: Union[ColorLookup, np.ndarray] = ColorLookup.CLASS,
|
||||
color_lookup: ColorLookup | np.ndarray = ColorLookup.CLASS,
|
||||
) -> int:
|
||||
if detection_idx >= len(detections):
|
||||
raise ValueError(
|
||||
@@ -124,17 +125,17 @@ def resolve_text_background_xyxy(
|
||||
)
|
||||
|
||||
|
||||
def get_color_by_index(color: Union[Color, ColorPalette], idx: int) -> Color:
|
||||
def get_color_by_index(color: Color | ColorPalette, idx: int) -> Color:
|
||||
if isinstance(color, ColorPalette):
|
||||
return color.by_idx(idx)
|
||||
return color
|
||||
|
||||
|
||||
def resolve_color(
|
||||
color: Union[Color, ColorPalette],
|
||||
color: Color | ColorPalette,
|
||||
detections: Detections,
|
||||
detection_idx: int,
|
||||
color_lookup: Union[ColorLookup, np.ndarray] = ColorLookup.CLASS,
|
||||
color_lookup: ColorLookup | np.ndarray = ColorLookup.CLASS,
|
||||
) -> Color:
|
||||
idx = resolve_color_idx(
|
||||
detections=detections,
|
||||
@@ -189,7 +190,7 @@ def wrap_text(text: str, max_line_length=None) -> list[str]:
|
||||
return all_lines if all_lines else [""]
|
||||
|
||||
|
||||
def validate_labels(labels: Optional[list[str]], detections: Detections):
|
||||
def validate_labels(labels: list[str] | None, detections: Detections):
|
||||
"""
|
||||
Validates that the number of provided labels matches the number of detections.
|
||||
|
||||
@@ -211,7 +212,7 @@ def validate_labels(labels: Optional[list[str]], detections: Detections):
|
||||
|
||||
|
||||
def get_labels_text(
|
||||
detections: Detections, custom_labels: Optional[list[str]]
|
||||
detections: Detections, custom_labels: list[str] | None
|
||||
) -> list[str]:
|
||||
"""
|
||||
Retrieves the text labels for the detections.
|
||||
@@ -309,7 +310,7 @@ def snap_boxes(xyxy: np.ndarray, resolution_wh: tuple[int, int]) -> np.ndarray:
|
||||
class Trace:
|
||||
def __init__(
|
||||
self,
|
||||
max_size: Optional[int] = None,
|
||||
max_size: int | None = None,
|
||||
start_frame_id: int = 0,
|
||||
anchor: Position = Position.CENTER,
|
||||
) -> None:
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from hashlib import new as hash_new
|
||||
from pathlib import Path
|
||||
from shutil import copyfileobj
|
||||
from typing import Union
|
||||
|
||||
from requests import get
|
||||
from tqdm.auto import tqdm
|
||||
@@ -32,7 +33,7 @@ def is_md5_hash_matching(filename: str, original_md5_hash: str) -> bool:
|
||||
return computed_md5_hash.hexdigest() == original_md5_hash
|
||||
|
||||
|
||||
def download_assets(asset_name: Union[VideoAssets, str]) -> str:
|
||||
def download_assets(asset_name: VideoAssets | str) -> str:
|
||||
"""
|
||||
Download a specified asset if it doesn't already exist or is corrupted.
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from xml.etree.ElementTree import Element, SubElement
|
||||
|
||||
import cv2
|
||||
@@ -15,7 +16,7 @@ from supervision.utils.file import list_files_with_extensions
|
||||
|
||||
|
||||
def object_to_pascal_voc(
|
||||
xyxy: np.ndarray, name: str, polygon: Optional[np.ndarray] = None
|
||||
xyxy: np.ndarray, name: str, polygon: np.ndarray | None = None
|
||||
) -> Element:
|
||||
root = Element("object")
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
@@ -205,7 +207,7 @@ def object_to_yolo(
|
||||
xyxy: np.ndarray,
|
||||
class_id: int,
|
||||
image_shape: tuple[int, int, int],
|
||||
polygon: Optional[np.ndarray] = None,
|
||||
polygon: np.ndarray | None = None,
|
||||
) -> str:
|
||||
h, w, _ = image_shape
|
||||
if polygon is None:
|
||||
@@ -260,7 +262,7 @@ def detections_to_yolo_annotations(
|
||||
|
||||
|
||||
def save_yolo_annotations(
|
||||
dataset: "DetectionDataset",
|
||||
dataset: DetectionDataset,
|
||||
annotations_directory_path: str,
|
||||
min_image_area_percentage: float = 0.0,
|
||||
max_image_area_percentage: float = 1.0,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import os
|
||||
import random
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Optional, TypeVar, Union
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -98,9 +100,7 @@ def map_detections_class_id(
|
||||
return detections_copy
|
||||
|
||||
|
||||
def save_dataset_images(
|
||||
dataset: "DetectionDataset", images_directory_path: str
|
||||
) -> None:
|
||||
def save_dataset_images(dataset: DetectionDataset, images_directory_path: str) -> None:
|
||||
Path(images_directory_path).mkdir(parents=True, exist_ok=True)
|
||||
for image_path in dataset.image_paths:
|
||||
final_path = os.path.join(images_directory_path, Path(image_path).name)
|
||||
@@ -114,7 +114,7 @@ def save_dataset_images(
|
||||
def train_test_split(
|
||||
data: list[T],
|
||||
train_ratio: float = 0.8,
|
||||
random_state: Optional[int] = None,
|
||||
random_state: int | None = None,
|
||||
shuffle: bool = True,
|
||||
) -> tuple[list[T], list[T]]:
|
||||
"""
|
||||
@@ -140,7 +140,7 @@ def train_test_split(
|
||||
|
||||
|
||||
def rle_to_mask(
|
||||
rle: Union[npt.NDArray[np.int_], list[int]], resolution_wh: tuple[int, int]
|
||||
rle: npt.NDArray[np.int_] | list[int], resolution_wh: tuple[int, int]
|
||||
) -> npt.NDArray[np.bool_]:
|
||||
"""
|
||||
Converts run-length encoding (RLE) to a binary mask.
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import warnings
|
||||
from collections import Counter, defaultdict, deque
|
||||
from collections.abc import Iterable
|
||||
from functools import lru_cache
|
||||
from typing import Any, Literal, Optional
|
||||
from typing import Any, Literal
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -161,7 +163,7 @@ class LineZone:
|
||||
self._compute_anchor_sides(detections)
|
||||
)
|
||||
|
||||
class_ids: list[Optional[int]] = (
|
||||
class_ids: list[int | None] = (
|
||||
list(detections.class_id)
|
||||
if detections.class_id is not None
|
||||
else [None] * len(detections)
|
||||
@@ -325,8 +327,8 @@ class LineZoneAnnotator:
|
||||
text_scale: float = 0.5,
|
||||
text_offset: float = 1.5,
|
||||
text_padding: int = 10,
|
||||
custom_in_text: Optional[str] = None,
|
||||
custom_out_text: Optional[str] = None,
|
||||
custom_in_text: str | None = None,
|
||||
custom_out_text: str | None = None,
|
||||
display_in_count: bool = True,
|
||||
display_out_count: bool = True,
|
||||
display_text_box: bool = True,
|
||||
@@ -758,7 +760,7 @@ class LineZoneAnnotatorMulticlass:
|
||||
self,
|
||||
frame: np.ndarray,
|
||||
line_zones: list[LineZone],
|
||||
line_zone_labels: Optional[list[str]] = None,
|
||||
line_zone_labels: list[str] | None = None,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Draws a table with the number of objects of each class that crossed each line.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import warnings
|
||||
from collections.abc import Callable
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from typing import Callable, Optional, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -18,7 +20,7 @@ from supervision.utils.internal import (
|
||||
def move_detections(
|
||||
detections: Detections,
|
||||
offset: np.ndarray,
|
||||
resolution_wh: Optional[tuple[int, int]] = None,
|
||||
resolution_wh: tuple[int, int] | None = None,
|
||||
) -> Detections:
|
||||
"""
|
||||
Args:
|
||||
@@ -89,9 +91,9 @@ class InferenceSlicer:
|
||||
self,
|
||||
callback: Callable[[np.ndarray], Detections],
|
||||
slice_wh: tuple[int, int] = (320, 320),
|
||||
overlap_ratio_wh: Optional[tuple[float, float]] = (0.2, 0.2),
|
||||
overlap_wh: Optional[tuple[int, int]] = None,
|
||||
overlap_filter: Union[OverlapFilter, str] = OverlapFilter.NON_MAX_SUPPRESSION,
|
||||
overlap_ratio_wh: tuple[float, float] | None = (0.2, 0.2),
|
||||
overlap_wh: tuple[int, int] | None = None,
|
||||
overlap_filter: OverlapFilter | str = OverlapFilter.NON_MAX_SUPPRESSION,
|
||||
iou_threshold: float = 0.5,
|
||||
match_metric: str = "IOU",
|
||||
thread_workers: int = 1,
|
||||
@@ -208,8 +210,8 @@ class InferenceSlicer:
|
||||
def _generate_offset(
|
||||
resolution_wh: tuple[int, int],
|
||||
slice_wh: tuple[int, int],
|
||||
overlap_ratio_wh: Optional[tuple[float, float]],
|
||||
overlap_wh: Optional[tuple[int, int]],
|
||||
overlap_ratio_wh: tuple[float, float] | None,
|
||||
overlap_wh: tuple[int, int] | None,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Generate offset coordinates for slicing an image based on the given resolution,
|
||||
@@ -268,8 +270,8 @@ class InferenceSlicer:
|
||||
|
||||
@staticmethod
|
||||
def _validate_overlap(
|
||||
overlap_ratio_wh: Optional[tuple[float, float]],
|
||||
overlap_wh: Optional[tuple[int, int]],
|
||||
overlap_ratio_wh: tuple[float, float] | None,
|
||||
overlap_wh: tuple[int, int] | None,
|
||||
) -> None:
|
||||
if overlap_ratio_wh is not None and overlap_wh is not None:
|
||||
raise ValueError(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable
|
||||
from dataclasses import replace
|
||||
from typing import Optional
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -154,7 +155,7 @@ class PolygonZoneAnnotator:
|
||||
self.display_in_zone_count = display_in_zone_count
|
||||
self.opacity = opacity
|
||||
|
||||
def annotate(self, scene: np.ndarray, label: Optional[str] = None) -> np.ndarray:
|
||||
def annotate(self, scene: np.ndarray, label: str | None = None) -> np.ndarray:
|
||||
"""
|
||||
Annotates the polygon zone within a frame with a count of detected objects.
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import warnings
|
||||
from collections import defaultdict, deque
|
||||
from copy import deepcopy
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -95,7 +96,7 @@ class DetectionsSmoother:
|
||||
|
||||
return self.get_smoothed_detections()
|
||||
|
||||
def get_track(self, track_id: int) -> Optional[Detections]:
|
||||
def get_track(self, track_id: int) -> Detections | None:
|
||||
track = self.tracks.get(track_id, None)
|
||||
if track is None:
|
||||
return None
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
@@ -9,7 +11,7 @@ from supervision.detection.utils import mask_to_xyxy
|
||||
|
||||
|
||||
def process_transformers_detection_result(
|
||||
detection_result: dict, id2label: Optional[dict[int, str]]
|
||||
detection_result: dict, id2label: dict[int, str] | None
|
||||
) -> dict:
|
||||
"""
|
||||
Process the result of Transformers object detection functions such as
|
||||
@@ -38,7 +40,7 @@ def process_transformers_detection_result(
|
||||
|
||||
|
||||
def process_transformers_v4_segmentation_result(
|
||||
segmentation_result: dict, id2label: Optional[dict[int, str]]
|
||||
segmentation_result: dict, id2label: dict[int, str] | None
|
||||
) -> dict:
|
||||
"""
|
||||
Process the result of Transformers segmentation functions such as
|
||||
@@ -77,7 +79,7 @@ def process_transformers_v4_segmentation_result(
|
||||
|
||||
|
||||
def process_transformers_v5_segmentation_result(
|
||||
segmentation_result: dict, id2label: Optional[dict[int, str]]
|
||||
segmentation_result: dict, id2label: dict[int, str] | None
|
||||
) -> dict:
|
||||
"""
|
||||
Process the result of Transformers segmentation functions such as
|
||||
@@ -107,7 +109,7 @@ def process_transformers_v5_segmentation_result(
|
||||
|
||||
|
||||
def process_transformers_v5_semantic_or_instance_segmentation_result(
|
||||
segmentation_result: dict, id2label: Optional[dict[int, str]]
|
||||
segmentation_result: dict, id2label: dict[int, str] | None
|
||||
) -> dict:
|
||||
"""
|
||||
Process the result of Transformers segmentation functions such as
|
||||
@@ -143,7 +145,7 @@ def process_transformers_v5_semantic_or_instance_segmentation_result(
|
||||
|
||||
|
||||
def process_transformers_v4_panoptic_segmentation_result(
|
||||
segmentation_result: dict, id2label: Optional[dict[int, str]]
|
||||
segmentation_result: dict, id2label: dict[int, str] | None
|
||||
) -> dict:
|
||||
"""
|
||||
Process the result of the Transformers function `post_process_panoptic` (v4).
|
||||
@@ -177,7 +179,7 @@ def process_transformers_v4_panoptic_segmentation_result(
|
||||
|
||||
|
||||
def process_transformers_v5_panoptic_segmentation_result(
|
||||
segmentation_array: np.ndarray, id2label: Optional[dict[int, str]]
|
||||
segmentation_array: np.ndarray, id2label: dict[int, str] | None
|
||||
) -> dict:
|
||||
"""
|
||||
Process the result of the Transformers function
|
||||
@@ -220,8 +222,8 @@ def png_string_to_segmentation_array(png_string: bytes) -> np.ndarray:
|
||||
|
||||
def append_class_names_to_data(
|
||||
class_ids: np.ndarray,
|
||||
id2label: Optional[dict[int, str]],
|
||||
data: Optional[dict[str, Any]] = None,
|
||||
id2label: dict[int, str] | None,
|
||||
data: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
Helper function to create or append to a data dictionary with class names if
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import io
|
||||
import json
|
||||
import re
|
||||
from enum import Enum
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
@@ -80,9 +82,7 @@ SUPPORTED_TASKS_FLORENCE_2 = [
|
||||
]
|
||||
|
||||
|
||||
def validate_vlm_parameters(
|
||||
vlm: Union[VLM, str], result: Any, kwargs: dict[str, Any]
|
||||
) -> VLM:
|
||||
def validate_vlm_parameters(vlm: VLM | str, result: Any, kwargs: dict[str, Any]) -> VLM:
|
||||
if isinstance(vlm, str):
|
||||
try:
|
||||
vlm = VLM(vlm.lower())
|
||||
@@ -110,8 +110,8 @@ def validate_vlm_parameters(
|
||||
|
||||
|
||||
def from_paligemma(
|
||||
result: str, resolution_wh: tuple[int, int], classes: Optional[list[str]] = None
|
||||
) -> tuple[np.ndarray, Optional[np.ndarray], np.ndarray]:
|
||||
result: str, resolution_wh: tuple[int, int], classes: list[str] | None = None
|
||||
) -> tuple[np.ndarray, np.ndarray | None, np.ndarray]:
|
||||
"""
|
||||
Parse bounding boxes from paligemma-formatted text, scale them to the specified
|
||||
resolution, and optionally filter by classes.
|
||||
@@ -161,8 +161,8 @@ def from_qwen_2_5_vl(
|
||||
result: str,
|
||||
input_wh: tuple[int, int],
|
||||
resolution_wh: tuple[int, int],
|
||||
classes: Optional[list[str]] = None,
|
||||
) -> tuple[np.ndarray, Optional[np.ndarray], np.ndarray]:
|
||||
classes: list[str] | None = None,
|
||||
) -> tuple[np.ndarray, np.ndarray | None, np.ndarray]:
|
||||
"""
|
||||
Parse and scale bounding boxes from Qwen-2.5-VL style JSON output.
|
||||
|
||||
@@ -239,9 +239,7 @@ def from_qwen_2_5_vl(
|
||||
|
||||
def from_florence_2(
|
||||
result: dict, resolution_wh: tuple[int, int]
|
||||
) -> tuple[
|
||||
np.ndarray, Optional[np.ndarray], Optional[np.ndarray], Optional[np.ndarray]
|
||||
]:
|
||||
) -> tuple[np.ndarray, np.ndarray | None, np.ndarray | None, np.ndarray | None]:
|
||||
"""
|
||||
Parse results from the Florence 2 multi-model model.
|
||||
https://huggingface.co/microsoft/Florence-2-large
|
||||
@@ -335,8 +333,8 @@ def from_florence_2(
|
||||
def from_google_gemini_2_0(
|
||||
result: str,
|
||||
resolution_wh: tuple[int, int],
|
||||
classes: Optional[list[str]] = None,
|
||||
) -> tuple[np.ndarray, Optional[np.ndarray], np.ndarray]:
|
||||
classes: list[str] | None = None,
|
||||
) -> tuple[np.ndarray, np.ndarray | None, np.ndarray]:
|
||||
"""
|
||||
Parse and scale bounding boxes from Google Gemini style
|
||||
[JSON output](https://ai.google.dev/gemini-api/docs/vision?lang=python).
|
||||
@@ -424,13 +422,13 @@ def from_google_gemini_2_0(
|
||||
def from_google_gemini_2_5(
|
||||
result: str,
|
||||
resolution_wh: tuple[int, int],
|
||||
classes: Optional[list[str]] = None,
|
||||
classes: list[str] | None = None,
|
||||
) -> tuple[
|
||||
np.ndarray,
|
||||
Optional[np.ndarray],
|
||||
np.ndarray | None,
|
||||
np.ndarray,
|
||||
Optional[np.ndarray],
|
||||
Optional[np.ndarray],
|
||||
np.ndarray | None,
|
||||
np.ndarray | None,
|
||||
]:
|
||||
"""
|
||||
Parse and scale bounding boxes and masks from Google Gemini 2.5 style
|
||||
@@ -490,8 +488,8 @@ def from_google_gemini_2_5(
|
||||
|
||||
boxes_list: list = []
|
||||
labels_list: list = []
|
||||
confidence_list: Optional[list] = []
|
||||
masks_list: Optional[list] = []
|
||||
confidence_list: list | None = []
|
||||
masks_list: list | None = []
|
||||
|
||||
for item in data:
|
||||
if "box_2d" not in item or "label" not in item:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Optional, Union
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -215,7 +216,7 @@ def draw_text(
|
||||
text_thickness: int = 1,
|
||||
text_padding: int = 10,
|
||||
text_font: int = cv2.FONT_HERSHEY_SIMPLEX,
|
||||
background_color: Optional[Color] = None,
|
||||
background_color: Color | None = None,
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Draw text with background on a scene.
|
||||
@@ -282,7 +283,7 @@ def draw_text(
|
||||
|
||||
|
||||
def draw_image(
|
||||
scene: np.ndarray, image: Union[str, np.ndarray], opacity: float, rect: Rect
|
||||
scene: np.ndarray, image: str | np.ndarray, opacity: float, rect: Rect
|
||||
) -> np.ndarray:
|
||||
"""
|
||||
Draws an image onto a given scene with specified opacity and dimensions.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from logging import warn
|
||||
from typing import Optional, Union
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -106,7 +107,7 @@ class EdgeAnnotator(BaseKeyPointAnnotator):
|
||||
self,
|
||||
color: Color = Color.ROBOFLOW,
|
||||
thickness: int = 2,
|
||||
edges: Optional[list[tuple[int, int]]] = None,
|
||||
edges: list[tuple[int, int]] | None = None,
|
||||
) -> None:
|
||||
"""
|
||||
Args:
|
||||
@@ -196,8 +197,8 @@ class VertexLabelAnnotator:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color: Union[Color, list[Color]] = Color.ROBOFLOW,
|
||||
text_color: Union[Color, list[Color]] = Color.WHITE,
|
||||
color: Color | list[Color] = Color.ROBOFLOW,
|
||||
text_color: Color | list[Color] = Color.WHITE,
|
||||
text_scale: float = 0.5,
|
||||
text_thickness: int = 1,
|
||||
text_padding: int = 10,
|
||||
@@ -220,8 +221,8 @@ class VertexLabelAnnotator:
|
||||
smart_position (bool): Spread out the labels to avoid overlap.
|
||||
"""
|
||||
self.border_radius: int = border_radius
|
||||
self.color: Union[Color, list[Color]] = color
|
||||
self.text_color: Union[Color, list[Color]] = text_color
|
||||
self.color: Color | list[Color] = color
|
||||
self.text_color: Color | list[Color] = text_color
|
||||
self.text_scale: float = text_scale
|
||||
self.text_thickness: int = text_thickness
|
||||
self.text_padding: int = text_padding
|
||||
@@ -231,7 +232,7 @@ class VertexLabelAnnotator:
|
||||
self,
|
||||
scene: ImageType,
|
||||
key_points: KeyPoints,
|
||||
labels: Optional[list[str]] = None,
|
||||
labels: list[str] | None = None,
|
||||
) -> ImageType:
|
||||
"""
|
||||
A class that draws labels of skeleton vertices on images. It uses specified key
|
||||
@@ -412,7 +413,7 @@ class VertexLabelAnnotator:
|
||||
|
||||
@staticmethod
|
||||
def preprocess_and_validate_labels(
|
||||
labels: Optional[list[str]], points_count: int, skeletons_count: int
|
||||
labels: list[str] | None, points_count: int, skeletons_count: int
|
||||
) -> np.ndarray:
|
||||
if labels and len(labels) != points_count:
|
||||
raise ValueError(
|
||||
@@ -426,7 +427,7 @@ class VertexLabelAnnotator:
|
||||
|
||||
@staticmethod
|
||||
def preprocess_and_validate_colors(
|
||||
colors: Optional[Union[Color, list[Color]]],
|
||||
colors: Color | list[Color] | None,
|
||||
points_count: int,
|
||||
skeletons_count: int,
|
||||
) -> np.ndarray:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable
|
||||
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import yaml
|
||||
@@ -18,7 +19,7 @@ class NumpyJsonEncoder(json.JSONEncoder):
|
||||
|
||||
|
||||
def list_files_with_extensions(
|
||||
directory: Union[str, Path], extensions: Optional[list[str]] = None
|
||||
directory: str | Path, extensions: list[str] | None = None
|
||||
) -> list[Path]:
|
||||
"""
|
||||
List files in a directory with specified extensions or
|
||||
@@ -57,7 +58,7 @@ def list_files_with_extensions(
|
||||
return files_with_extensions
|
||||
|
||||
|
||||
def read_txt_file(file_path: Union[str, Path], skip_empty: bool = False) -> list[str]:
|
||||
def read_txt_file(file_path: str | Path, skip_empty: bool = False) -> list[str]:
|
||||
"""
|
||||
Read a text file and return a list of strings without newline characters.
|
||||
Optionally skip empty lines.
|
||||
@@ -79,7 +80,7 @@ def read_txt_file(file_path: Union[str, Path], skip_empty: bool = False) -> list
|
||||
return lines
|
||||
|
||||
|
||||
def save_text_file(lines: list[str], file_path: Union[str, Path]) -> None:
|
||||
def save_text_file(lines: list[str], file_path: str | Path) -> None:
|
||||
"""
|
||||
Write a list of strings to a text file, each string on a new line.
|
||||
|
||||
@@ -92,7 +93,7 @@ def save_text_file(lines: list[str], file_path: Union[str, Path]) -> None:
|
||||
file.write(line + "\n")
|
||||
|
||||
|
||||
def read_json_file(file_path: Union[str, Path]) -> dict:
|
||||
def read_json_file(file_path: str | Path) -> dict:
|
||||
"""
|
||||
Read a json file and return a dict.
|
||||
|
||||
@@ -107,7 +108,7 @@ def read_json_file(file_path: Union[str, Path]) -> dict:
|
||||
return data
|
||||
|
||||
|
||||
def save_json_file(data: dict, file_path: Union[str, Path], indent: int = 3) -> None:
|
||||
def save_json_file(data: dict, file_path: str | Path, indent: int = 3) -> None:
|
||||
"""
|
||||
Write a dict to a json file.
|
||||
|
||||
@@ -120,7 +121,7 @@ def save_json_file(data: dict, file_path: Union[str, Path], indent: int = 3) ->
|
||||
json.dump(data, fp, cls=NumpyJsonEncoder, indent=indent)
|
||||
|
||||
|
||||
def read_yaml_file(file_path: Union[str, Path]) -> dict:
|
||||
def read_yaml_file(file_path: str | Path) -> dict:
|
||||
"""
|
||||
Read a yaml file and return a dict.
|
||||
|
||||
@@ -135,7 +136,7 @@ def read_yaml_file(file_path: Union[str, Path]) -> dict:
|
||||
return data
|
||||
|
||||
|
||||
def save_yaml_file(data: dict, file_path: Union[str, Path]) -> None:
|
||||
def save_yaml_file(data: dict, file_path: str | Path) -> None:
|
||||
"""
|
||||
Save a dict to a json file.
|
||||
|
||||
|
||||
+24
-23
@@ -1,9 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
import math
|
||||
import os
|
||||
import shutil
|
||||
from collections.abc import Callable
|
||||
from functools import partial
|
||||
from typing import Callable, Literal, Optional, Union
|
||||
from typing import Literal
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -28,7 +31,7 @@ MAX_COLUMNS_FOR_SINGLE_ROW_GRID = 3
|
||||
@ensure_cv2_image_for_processing
|
||||
def crop_image(
|
||||
image: ImageType,
|
||||
xyxy: Union[npt.NDArray[int], list[int], tuple[int, int, int, int]],
|
||||
xyxy: npt.NDArray[int] | list[int] | tuple[int, int, int, int],
|
||||
) -> ImageType:
|
||||
"""
|
||||
Crops the given image based on the given bounding box.
|
||||
@@ -220,7 +223,7 @@ def resize_image(
|
||||
def letterbox_image(
|
||||
image: ImageType,
|
||||
resolution_wh: tuple[int, int],
|
||||
color: Union[tuple[int, int, int], Color] = Color.BLACK,
|
||||
color: tuple[int, int, int] | Color = Color.BLACK,
|
||||
) -> ImageType:
|
||||
"""
|
||||
Resizes and pads an image to a specified resolution with a given color, maintaining
|
||||
@@ -412,7 +415,7 @@ class ImageSink:
|
||||
|
||||
return self
|
||||
|
||||
def save_image(self, image: np.ndarray, image_name: Optional[str] = None):
|
||||
def save_image(self, image: np.ndarray, image_name: str | None = None):
|
||||
"""
|
||||
Save a given image in the target directory.
|
||||
|
||||
@@ -436,23 +439,21 @@ class ImageSink:
|
||||
|
||||
def create_tiles(
|
||||
images: list[ImageType],
|
||||
grid_size: Optional[tuple[Optional[int], Optional[int]]] = None,
|
||||
single_tile_size: Optional[tuple[int, int]] = None,
|
||||
grid_size: tuple[int | None, int | None] | None = None,
|
||||
single_tile_size: tuple[int, int] | None = None,
|
||||
tile_scaling: Literal["min", "max", "avg"] = "avg",
|
||||
tile_padding_color: Union[tuple[int, int, int], Color] = Color.from_hex("#D9D9D9"),
|
||||
tile_padding_color: tuple[int, int, int] | Color = Color.from_hex("#D9D9D9"),
|
||||
tile_margin: int = 10,
|
||||
tile_margin_color: Union[tuple[int, int, int], Color] = Color.from_hex("#BFBEBD"),
|
||||
tile_margin_color: tuple[int, int, int] | Color = Color.from_hex("#BFBEBD"),
|
||||
return_type: Literal["auto", "cv2", "pillow"] = "auto",
|
||||
titles: Optional[list[Optional[str]]] = None,
|
||||
titles_anchors: Optional[Union[Point, list[Optional[Point]]]] = None,
|
||||
titles_color: Union[tuple[int, int, int], Color] = Color.from_hex("#262523"),
|
||||
titles_scale: Optional[float] = None,
|
||||
titles: list[str | None] | None = None,
|
||||
titles_anchors: Point | list[Point | None] | None = None,
|
||||
titles_color: tuple[int, int, int] | Color = Color.from_hex("#262523"),
|
||||
titles_scale: float | None = None,
|
||||
titles_thickness: int = 1,
|
||||
titles_padding: int = 10,
|
||||
titles_text_font: int = cv2.FONT_HERSHEY_SIMPLEX,
|
||||
titles_background_color: Union[tuple[int, int, int], Color] = Color.from_hex(
|
||||
"#D9D9D9"
|
||||
),
|
||||
titles_background_color: tuple[int, int, int] | Color = Color.from_hex("#D9D9D9"),
|
||||
default_title_placement: RelativePosition = "top",
|
||||
) -> ImageType:
|
||||
"""
|
||||
@@ -613,7 +614,7 @@ def _aggregate_images_shape(
|
||||
|
||||
|
||||
def _establish_grid_size(
|
||||
images: list[np.ndarray], grid_size: Optional[tuple[Optional[int], Optional[int]]]
|
||||
images: list[np.ndarray], grid_size: tuple[int | None, int | None] | None
|
||||
) -> tuple[int, int]:
|
||||
if grid_size is None or all(e is None for e in grid_size):
|
||||
return _negotiate_grid_size(images=images)
|
||||
@@ -642,10 +643,10 @@ def _generate_tiles(
|
||||
tile_padding_color: tuple[int, int, int],
|
||||
tile_margin: int,
|
||||
tile_margin_color: tuple[int, int, int],
|
||||
titles: Optional[list[Optional[str]]],
|
||||
titles_anchors: list[Optional[Point]],
|
||||
titles: list[str | None] | None,
|
||||
titles_anchors: list[Point | None],
|
||||
titles_color: tuple[int, int, int],
|
||||
titles_scale: Optional[float],
|
||||
titles_scale: float | None,
|
||||
titles_thickness: int,
|
||||
titles_padding: int,
|
||||
titles_text_font: int,
|
||||
@@ -686,10 +687,10 @@ def _generate_tiles(
|
||||
|
||||
def _draw_texts(
|
||||
images: list[np.ndarray],
|
||||
titles: Optional[list[Optional[str]]],
|
||||
titles_anchors: list[Optional[Point]],
|
||||
titles: list[str | None] | None,
|
||||
titles_anchors: list[Point | None],
|
||||
titles_color: tuple[int, int, int],
|
||||
titles_scale: Optional[float],
|
||||
titles_scale: float | None,
|
||||
titles_thickness: int,
|
||||
titles_padding: int,
|
||||
titles_text_font: int,
|
||||
@@ -730,7 +731,7 @@ def _draw_texts(
|
||||
|
||||
def _prepare_default_titles_anchors(
|
||||
images: list[np.ndarray],
|
||||
titles_anchors: list[Optional[Point]],
|
||||
titles_anchors: list[Point | None],
|
||||
default_title_placement: RelativePosition,
|
||||
) -> list[Point]:
|
||||
result = []
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import inspect
|
||||
import os
|
||||
import warnings
|
||||
from typing import Any, Callable, Generic, Optional, TypeVar
|
||||
from collections.abc import Callable
|
||||
from typing import Any, Generic, TypeVar
|
||||
|
||||
|
||||
class SupervisionWarnings(Warning):
|
||||
@@ -144,7 +147,7 @@ class classproperty(Generic[T]):
|
||||
"""
|
||||
self.fget = fget
|
||||
|
||||
def __get__(self, owner_self: Any, owner_cls: Optional[type] = None) -> T:
|
||||
def __get__(self, owner_self: Any, owner_cls: type | None = None) -> T:
|
||||
"""
|
||||
Override the __get__ method to return the result of the function call.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Optional
|
||||
from __future__ import annotations
|
||||
|
||||
import cv2
|
||||
import matplotlib.pyplot as plt
|
||||
@@ -9,7 +9,7 @@ from supervision.utils.conversion import pillow_to_cv2
|
||||
|
||||
|
||||
def plot_image(
|
||||
image: ImageType, size: tuple[int, int] = (12, 12), cmap: Optional[str] = "gray"
|
||||
image: ImageType, size: tuple[int, int] = (12, 12), cmap: str | None = "gray"
|
||||
) -> None:
|
||||
"""
|
||||
Plots image using matplotlib.
|
||||
@@ -48,9 +48,9 @@ def plot_image(
|
||||
def plot_images_grid(
|
||||
images: list[ImageType],
|
||||
grid_size: tuple[int, int],
|
||||
titles: Optional[list[str]] = None,
|
||||
titles: list[str] | None = None,
|
||||
size: tuple[int, int] = (12, 12),
|
||||
cmap: Optional[str] = "gray",
|
||||
cmap: str | None = "gray",
|
||||
) -> None:
|
||||
"""
|
||||
Plots images in a grid using matplotlib.
|
||||
|
||||
@@ -2,9 +2,8 @@ from __future__ import annotations
|
||||
|
||||
import time
|
||||
from collections import deque
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Callable, Generator
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -97,7 +98,7 @@ def test_resolve_color_idx(
|
||||
detections: Detections,
|
||||
detection_idx: int,
|
||||
color_lookup: ColorLookup,
|
||||
expected_result: Optional[int],
|
||||
expected_result: int | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -49,9 +50,9 @@ from supervision.classification.core import Classifications
|
||||
)
|
||||
def test_top_k(
|
||||
class_id: np.ndarray,
|
||||
confidence: Optional[np.ndarray],
|
||||
confidence: np.ndarray | None,
|
||||
k: int,
|
||||
expected_result: Optional[tuple[np.ndarray, np.ndarray]],
|
||||
expected_result: tuple[np.ndarray, np.ndarray] | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -21,7 +22,7 @@ def mock_coco_annotation(
|
||||
category_id: int = 0,
|
||||
bbox: tuple[float, float, float, float] = (0.0, 0.0, 0.0, 0.0),
|
||||
area: float = 0.0,
|
||||
segmentation: Optional[Union[list[list], dict]] = None,
|
||||
segmentation: list[list] | dict | None = None,
|
||||
iscrowd: bool = False,
|
||||
) -> dict:
|
||||
if not segmentation:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -60,7 +61,7 @@ def are_xml_elements_equal(elem1, elem2):
|
||||
def test_object_to_pascal_voc(
|
||||
xyxy: np.ndarray,
|
||||
name: str,
|
||||
polygon: Optional[np.ndarray],
|
||||
polygon: np.ndarray | None,
|
||||
expected_result,
|
||||
exception: Exception,
|
||||
):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -57,7 +58,7 @@ def _arrays_almost_equal(
|
||||
],
|
||||
)
|
||||
def test_with_mask(
|
||||
lines: list[str], expected_result: Optional[bool], exception: Exception
|
||||
lines: list[str], expected_result: bool | None, exception: Exception
|
||||
) -> None:
|
||||
with exception:
|
||||
result = _with_mask(lines=lines)
|
||||
@@ -174,7 +175,7 @@ def test_yolo_annotations_to_detections(
|
||||
lines: list[str],
|
||||
resolution_wh: tuple[int, int],
|
||||
with_masks: bool,
|
||||
expected_result: Optional[Detections],
|
||||
expected_result: Detections | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -202,7 +203,7 @@ def test_yolo_annotations_to_detections(
|
||||
],
|
||||
)
|
||||
def test_image_name_to_annotation_name(
|
||||
image_name: str, expected_result: Optional[str], exception: Exception
|
||||
image_name: str, expected_result: str | None, exception: Exception
|
||||
) -> None:
|
||||
with exception:
|
||||
result = _image_name_to_annotation_name(image_name=image_name)
|
||||
@@ -268,8 +269,8 @@ def test_object_to_yolo(
|
||||
xyxy: np.ndarray,
|
||||
class_id: int,
|
||||
image_shape: tuple[int, int, int],
|
||||
polygon: Optional[np.ndarray],
|
||||
expected_result: Optional[str],
|
||||
polygon: np.ndarray | None,
|
||||
expected_result: str | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -159,7 +160,7 @@ from test.test_utils import mock_detections
|
||||
)
|
||||
def test_dataset_merge(
|
||||
dataset_list: list[DetectionDataset],
|
||||
expected_result: Optional[DetectionDataset],
|
||||
expected_result: DetectionDataset | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional, TypeVar
|
||||
from typing import TypeVar
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
@@ -78,7 +80,7 @@ def test_train_test_split(
|
||||
train_ratio: float,
|
||||
random_state: int,
|
||||
shuffle: bool,
|
||||
expected_result: Optional[tuple[list[T], list[T]]],
|
||||
expected_result: tuple[list[T], list[T]] | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -165,7 +167,7 @@ def test_merge_class_maps(
|
||||
def test_build_class_index_mapping(
|
||||
source_classes: list[str],
|
||||
target_classes: list[str],
|
||||
expected_result: Optional[dict[int, int]],
|
||||
expected_result: dict[int, int] | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -225,7 +227,7 @@ def test_build_class_index_mapping(
|
||||
def test_map_detections_class_id(
|
||||
source_to_target_mapping: dict[int, int],
|
||||
detections: Detections,
|
||||
expected_result: Optional[Detections],
|
||||
expected_result: Detections | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -233,8 +234,8 @@ TEST_DET_DIFFERENT_METADATA = Detections(
|
||||
)
|
||||
def test_getitem(
|
||||
detections: Detections,
|
||||
index: Union[int, slice, list[int], np.ndarray],
|
||||
expected_result: Optional[Detections],
|
||||
index: int | slice | list[int] | np.ndarray,
|
||||
expected_result: Detections | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -506,7 +507,7 @@ def test_getitem(
|
||||
)
|
||||
def test_merge(
|
||||
detections_list: list[Detections],
|
||||
expected_result: Optional[Detections],
|
||||
expected_result: Detections | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -808,7 +809,7 @@ def test_equal(
|
||||
def test_merge_inner_detection_object_pair(
|
||||
detection_1: Detections,
|
||||
detection_2: Detections,
|
||||
expected_result: Optional[Detections],
|
||||
expected_result: Detections | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -65,7 +66,7 @@ from test.test_utils import mock_detections
|
||||
)
|
||||
def test_calculate_region_of_interest_limits(
|
||||
vector: Vector,
|
||||
expected_result: Optional[tuple[Vector, Vector]],
|
||||
expected_result: tuple[Vector, Vector] | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -741,7 +742,7 @@ def test_line_zone_one_detection_long_horizon(
|
||||
)
|
||||
def test_line_zone_long_horizon_disappearing_detections(
|
||||
vector: Vector,
|
||||
xyxy_sequence: list[list[Optional[list[float]]]],
|
||||
xyxy_sequence: list[list[list[float] | None]],
|
||||
anchors: list[Position],
|
||||
minimum_crossing_threshold: int,
|
||||
expected_crossed_in: list[list[bool]],
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -234,7 +235,7 @@ def test_group_overlapping_boxes(
|
||||
def test_box_non_max_suppression(
|
||||
predictions: np.ndarray,
|
||||
iou_threshold: float,
|
||||
expected_result: Optional[np.ndarray],
|
||||
expected_result: np.ndarray | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -440,7 +441,7 @@ def test_mask_non_max_suppression(
|
||||
predictions: np.ndarray,
|
||||
masks: np.ndarray,
|
||||
iou_threshold: float,
|
||||
expected_result: Optional[np.ndarray],
|
||||
expected_result: np.ndarray | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
@@ -153,8 +155,8 @@ def test_clip_boxes(
|
||||
)
|
||||
def test_filter_polygons_by_area(
|
||||
polygons: list[np.ndarray],
|
||||
min_area: Optional[float],
|
||||
max_area: Optional[float],
|
||||
min_area: float | None,
|
||||
max_area: float | None,
|
||||
expected_result: list[np.ndarray],
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
@@ -373,7 +375,7 @@ def test_filter_polygons_by_area(
|
||||
def test_process_roboflow_result(
|
||||
roboflow_result: dict,
|
||||
expected_result: tuple[
|
||||
np.ndarray, np.ndarray, np.ndarray, Optional[np.ndarray], np.ndarray
|
||||
np.ndarray, np.ndarray, np.ndarray, np.ndarray | None, np.ndarray
|
||||
],
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
@@ -1033,7 +1035,7 @@ def test_calculate_masks_centroids(
|
||||
)
|
||||
def test_merge_data(
|
||||
data_list: list[dict[str, Any]],
|
||||
expected_result: Optional[dict[str, Any]],
|
||||
expected_result: dict[str, Any] | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
@@ -1209,7 +1211,7 @@ def test_merge_data(
|
||||
def test_get_data_item(
|
||||
data: dict[str, Any],
|
||||
index: Any,
|
||||
expected_result: Optional[dict[str, Any]],
|
||||
expected_result: dict[str, Any] | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
|
||||
+11
-11
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from contextlib import nullcontext as does_not_raise
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -185,8 +186,8 @@ def test_from_paligemma(
|
||||
exception,
|
||||
result: str,
|
||||
resolution_wh: tuple[int, int],
|
||||
classes: Optional[list[str]],
|
||||
expected_results: tuple[np.ndarray, Optional[np.ndarray], np.ndarray],
|
||||
classes: list[str] | None,
|
||||
expected_results: tuple[np.ndarray, np.ndarray | None, np.ndarray],
|
||||
) -> None:
|
||||
with exception:
|
||||
result = from_paligemma(
|
||||
@@ -347,7 +348,7 @@ def test_from_qwen_2_5_vl(
|
||||
result: str,
|
||||
input_wh: tuple[int, int],
|
||||
resolution_wh: tuple[int, int],
|
||||
classes: Optional[list[str]],
|
||||
classes: list[str] | None,
|
||||
expected_results,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -489,8 +490,8 @@ def test_from_google_gemini(
|
||||
exception,
|
||||
result: str,
|
||||
resolution_wh: tuple[int, int],
|
||||
classes: Optional[list[str]],
|
||||
expected_results: tuple[np.ndarray, Optional[np.ndarray], np.ndarray],
|
||||
classes: list[str] | None,
|
||||
expected_results: tuple[np.ndarray, np.ndarray | None, np.ndarray],
|
||||
) -> None:
|
||||
with exception:
|
||||
xyxy, class_id, class_name = from_google_gemini_2_0(
|
||||
@@ -865,7 +866,7 @@ def test_florence_2(
|
||||
florence_result: dict,
|
||||
resolution_wh: tuple[int, int],
|
||||
expected_results: tuple[
|
||||
np.ndarray, Optional[np.ndarray], Optional[np.ndarray], Optional[np.ndarray]
|
||||
np.ndarray, np.ndarray | None, np.ndarray | None, np.ndarray | None
|
||||
],
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
@@ -1081,10 +1082,9 @@ def test_from_google_gemini_2_5(
|
||||
exception,
|
||||
result: str,
|
||||
resolution_wh: tuple[int, int],
|
||||
classes: Optional[list[str]],
|
||||
expected_results: Optional[
|
||||
tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]
|
||||
],
|
||||
classes: list[str] | None,
|
||||
expected_results: None
|
||||
| (tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]),
|
||||
):
|
||||
with exception:
|
||||
(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -47,9 +48,9 @@ def mock_callback():
|
||||
def test_inference_slicer_overlap(
|
||||
mock_callback,
|
||||
slice_wh: tuple[int, int],
|
||||
overlap_ratio_wh: Optional[tuple[float, float]],
|
||||
overlap_wh: Optional[tuple[int, int]],
|
||||
expected_overlap: Optional[tuple[int, int]],
|
||||
overlap_ratio_wh: tuple[float, float] | None,
|
||||
overlap_wh: tuple[int, int] | None,
|
||||
expected_overlap: tuple[int, int] | None,
|
||||
exception: Exception,
|
||||
) -> None:
|
||||
with exception:
|
||||
@@ -169,7 +170,7 @@ def test_inference_slicer_overlap(
|
||||
def test_generate_offset(
|
||||
resolution_wh: tuple[int, int],
|
||||
slice_wh: tuple[int, int],
|
||||
overlap_wh: Optional[tuple[int, int]],
|
||||
overlap_wh: tuple[int, int] | None,
|
||||
expected_offsets: np.ndarray,
|
||||
) -> None:
|
||||
offsets = InferenceSlicer._generate_offset(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -25,7 +26,7 @@ from supervision.draw.color import Color
|
||||
],
|
||||
)
|
||||
def test_color_from_hex(
|
||||
color_hex, expected_result: Optional[Color], exception: Exception
|
||||
color_hex, expected_result: Color | None, exception: Exception
|
||||
) -> None:
|
||||
with exception:
|
||||
result = Color.from_hex(color_hex=color_hex)
|
||||
@@ -44,7 +45,7 @@ def test_color_from_hex(
|
||||
],
|
||||
)
|
||||
def test_color_as_hex(
|
||||
color: Color, expected_result: Optional[str], exception: Exception
|
||||
color: Color, expected_result: str | None, exception: Exception
|
||||
) -> None:
|
||||
with exception:
|
||||
result = color.as_hex()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
@@ -103,9 +104,7 @@ def update_ideal_conf_matrix(conf_matrix: np.ndarray, class_ids: np.ndarray):
|
||||
return conf_matrix
|
||||
|
||||
|
||||
def worsen_ideal_conf_matrix(
|
||||
conf_matrix: np.ndarray, class_ids: Union[np.ndarray, list]
|
||||
):
|
||||
def worsen_ideal_conf_matrix(conf_matrix: np.ndarray, class_ids: np.ndarray | list):
|
||||
for class_id in class_ids:
|
||||
class_id = int(class_id)
|
||||
conf_matrix[class_id, class_id] -= 1
|
||||
@@ -177,7 +176,7 @@ BAD_CONF_MATRIX = worsen_ideal_conf_matrix(
|
||||
def test_detections_to_tensor(
|
||||
detections: Detections,
|
||||
with_confidence: bool,
|
||||
expected_result: Optional[np.ndarray],
|
||||
expected_result: np.ndarray | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
@@ -343,7 +342,7 @@ def test_from_tensors(
|
||||
classes,
|
||||
conf_threshold,
|
||||
iou_threshold,
|
||||
expected_result: Optional[np.ndarray],
|
||||
expected_result: np.ndarray | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
@@ -380,7 +379,7 @@ def test_evaluate_detection_batch(
|
||||
num_classes,
|
||||
conf_threshold,
|
||||
iou_threshold,
|
||||
expected_result: Optional[np.ndarray],
|
||||
expected_result: np.ndarray | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
@@ -408,7 +407,7 @@ def test_evaluate_detection_batch(
|
||||
)
|
||||
def test_drop_extra_matches(
|
||||
matches,
|
||||
expected_result: Optional[np.ndarray],
|
||||
expected_result: np.ndarray | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
|
||||
+11
-9
@@ -1,4 +1,6 @@
|
||||
from typing import Any, Optional
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
@@ -9,11 +11,11 @@ from supervision.keypoint.core import KeyPoints
|
||||
|
||||
def mock_detections(
|
||||
xyxy: npt.NDArray[np.float32],
|
||||
mask: Optional[list[np.ndarray]] = None,
|
||||
confidence: Optional[list[float]] = None,
|
||||
class_id: Optional[list[int]] = None,
|
||||
tracker_id: Optional[list[int]] = None,
|
||||
data: Optional[dict[str, list[Any]]] = None,
|
||||
mask: list[np.ndarray] | None = None,
|
||||
confidence: list[float] | None = None,
|
||||
class_id: list[int] | None = None,
|
||||
tracker_id: list[int] | None = None,
|
||||
data: dict[str, list[Any]] | None = None,
|
||||
) -> Detections:
|
||||
def convert_data(data: dict[str, list[Any]]):
|
||||
return {k: np.array(v) for k, v in data.items()}
|
||||
@@ -34,9 +36,9 @@ def mock_detections(
|
||||
|
||||
def mock_keypoints(
|
||||
xy: npt.NDArray[np.float32],
|
||||
confidence: Optional[list[float]] = None,
|
||||
class_id: Optional[list[int]] = None,
|
||||
data: Optional[dict[str, list[Any]]] = None,
|
||||
confidence: list[float] | None = None,
|
||||
class_id: list[int] | None = None,
|
||||
data: dict[str, list[Any]] | None = None,
|
||||
) -> KeyPoints:
|
||||
def convert_data(data: dict[str, list[Any]]):
|
||||
return {k: np.array(v) for k, v in data.items()}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from contextlib import ExitStack as DoesNotRaise
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -56,7 +57,7 @@ def setup_and_teardown_files():
|
||||
def test_read_txt_file(
|
||||
file_name: str,
|
||||
skip_empty: bool,
|
||||
expected_result: Optional[list[str]],
|
||||
expected_result: list[str] | None,
|
||||
exception: Exception,
|
||||
):
|
||||
with exception:
|
||||
|
||||
Reference in new issue
Block a user