From 1f0c278c4eff1d1ddc9cd2ed15a20be0bd71bf84 Mon Sep 17 00:00:00 2001 From: Onuralp SEZER Date: Thu, 19 Sep 2024 10:35:30 +0300 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=E2=9C=A8=20ruff=20rules=20enab?= =?UTF-8?q?led=20and=20fixed=20and=20code=20refactor=20made?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Onuralp SEZER --- demo.ipynb | 2 +- examples/traffic_analysis/inference_example.py | 4 ++-- examples/traffic_analysis/ultralytics_example.py | 4 ++-- pyproject.toml | 2 +- supervision/detection/core.py | 8 ++++---- supervision/detection/line_zone.py | 2 +- supervision/detection/lmm.py | 2 +- supervision/detection/overlap_filter.py | 2 +- supervision/detection/tools/csv_sink.py | 6 +++--- supervision/detection/tools/json_sink.py | 6 +++--- supervision/detection/tools/smoother.py | 2 +- supervision/keypoint/core.py | 2 +- supervision/keypoint/skeletons.py | 13 +++++++------ supervision/metrics/detection.py | 4 ++-- test/dataset/formats/test_coco.py | 4 ++-- 15 files changed, 32 insertions(+), 31 deletions(-) diff --git a/demo.ipynb b/demo.ipynb index b5aa7c5e8..3b8cf2dc1 100644 --- a/demo.ipynb +++ b/demo.ipynb @@ -1357,7 +1357,7 @@ } ], "source": [ - "IMAGE_NAME = list(ds.images.keys())[0]\n", + "IMAGE_NAME = next(iter(ds.images.keys()))\n", "\n", "image = ds.images[IMAGE_NAME]\n", "annotations = ds.annotations[IMAGE_NAME]\n", diff --git a/examples/traffic_analysis/inference_example.py b/examples/traffic_analysis/inference_example.py index d844bc923..d98abcc51 100644 --- a/examples/traffic_analysis/inference_example.py +++ b/examples/traffic_analysis/inference_example.py @@ -1,6 +1,6 @@ import argparse import os -from typing import Dict, Iterable, List, Set +from typing import Dict, Iterable, List, Optional, Set import cv2 import numpy as np @@ -77,7 +77,7 @@ def __init__( roboflow_api_key: str, model_id: str, source_video_path: str, - target_video_path: str = None, + target_video_path: Optional[str] = None, confidence_threshold: float = 0.3, iou_threshold: float = 0.7, ) -> None: diff --git a/examples/traffic_analysis/ultralytics_example.py b/examples/traffic_analysis/ultralytics_example.py index d8ba6e831..269967f50 100644 --- a/examples/traffic_analysis/ultralytics_example.py +++ b/examples/traffic_analysis/ultralytics_example.py @@ -1,5 +1,5 @@ import argparse -from typing import Dict, Iterable, List, Set +from typing import Dict, Iterable, List, Optional, Set import cv2 import numpy as np @@ -74,7 +74,7 @@ def __init__( self, source_weights_path: str, source_video_path: str, - target_video_path: str = None, + target_video_path: Optional[str] = None, confidence_threshold: float = 0.3, iou_threshold: float = 0.7, ) -> None: diff --git a/pyproject.toml b/pyproject.toml index 75880a269..383fec6e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -166,7 +166,7 @@ indent-width = 4 [tool.ruff.lint] # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. -select = ["E", "F", "I", "A", "Q", "W"] +select = ["E", "F", "I", "A", "Q", "W","RUF"] ignore = [] # Allow autofix for all enabled rules (when `--fix`) is provided. fixable = [ diff --git a/supervision/detection/core.py b/supervision/detection/core.py index 06995f90f..9cd3147fb 100644 --- a/supervision/detection/core.py +++ b/supervision/detection/core.py @@ -249,7 +249,7 @@ def from_ultralytics(cls, ultralytics_results) -> Detections: results = model(image)[0] detections = sv.Detections.from_ultralytics(results) ``` - """ # noqa: E501 // docs + """ if hasattr(ultralytics_results, "obb") and ultralytics_results.obb is not None: class_id = ultralytics_results.obb.cls.cpu().numpy().astype(int) @@ -356,7 +356,7 @@ def from_tensorflow( result = model(img) detections = sv.Detections.from_tensorflow(result) ``` - """ # noqa: E501 // docs + """ boxes = tensorflow_results["detection_boxes"][0].numpy() boxes[:, [0, 2]] *= resolution_wh[0] @@ -431,7 +431,7 @@ def from_mmdetection(cls, mmdet_results) -> Detections: result = inference_detector(model, image) detections = sv.Detections.from_mmdetection(result) ``` - """ # noqa: E501 // docs + """ return cls( xyxy=mmdet_results.pred_instances.bboxes.cpu().numpy(), @@ -490,7 +490,7 @@ def from_transformers( id2label=model.config.id2label ) ``` - """ # noqa: E501 // docs + """ if ( transformers_results.__class__.__name__ == "Tensor" diff --git a/supervision/detection/line_zone.py b/supervision/detection/line_zone.py index 4255a0adb..aa7f2d4e3 100644 --- a/supervision/detection/line_zone.py +++ b/supervision/detection/line_zone.py @@ -55,7 +55,7 @@ class LineZone: line_zone.in_count, line_zone.out_count # 7, 2 ``` - """ # noqa: E501 // docs + """ def __init__( self, diff --git a/supervision/detection/lmm.py b/supervision/detection/lmm.py index 61b06ee1f..7879902f3 100644 --- a/supervision/detection/lmm.py +++ b/supervision/detection/lmm.py @@ -113,7 +113,7 @@ def from_florence_2( oriented bounding boxes. """ assert len(result) == 1, f"Expected result with a single element. Got: {result}" - task = list(result.keys())[0] + task = next(iter(result.keys())) if task not in SUPPORTED_TASKS_FLORENCE_2: raise ValueError( f"{task} not supported. Supported tasks are: {SUPPORTED_TASKS_FLORENCE_2}" diff --git a/supervision/detection/overlap_filter.py b/supervision/detection/overlap_filter.py index 461e413ca..dcfbb6428 100644 --- a/supervision/detection/overlap_filter.py +++ b/supervision/detection/overlap_filter.py @@ -183,7 +183,7 @@ def group_overlapping_boxes( ious = ious.flatten() above_threshold = ious >= iou_threshold - merge_group = [idx] + np.flip(order[above_threshold]).tolist() + merge_group = [idx, *np.flip(order[above_threshold]).tolist()] merge_groups.append(merge_group) order = order[~above_threshold] return merge_groups diff --git a/supervision/detection/tools/csv_sink.py b/supervision/detection/tools/csv_sink.py index 1e1f2940c..ea7e58bb8 100644 --- a/supervision/detection/tools/csv_sink.py +++ b/supervision/detection/tools/csv_sink.py @@ -48,7 +48,7 @@ class CSVSink: detections = sv.Detections.from_ultralytics(result) sink.append(detections, custom_data={'':''}) ``` - """ # noqa: E501 // docs + """ def __init__(self, file_name: str = "output.csv") -> None: """ @@ -104,7 +104,7 @@ def close(self) -> None: @staticmethod def parse_detection_data( - detections: Detections, custom_data: Dict[str, Any] = None + detections: Detections, custom_data: Optional[Dict[str, Any]] = None ) -> List[Dict[str, Any]]: parsed_rows = [] for i in range(len(detections.xyxy)): @@ -137,7 +137,7 @@ def parse_detection_data( return parsed_rows def append( - self, detections: Detections, custom_data: Dict[str, Any] = None + self, detections: Detections, custom_data: Optional[Dict[str, Any]] = None ) -> None: """ Append detection data to the CSV file. diff --git a/supervision/detection/tools/json_sink.py b/supervision/detection/tools/json_sink.py index 9e73554b4..b8927c5f3 100644 --- a/supervision/detection/tools/json_sink.py +++ b/supervision/detection/tools/json_sink.py @@ -38,7 +38,7 @@ class JSONSink: detections = sv.Detections.from_ultralytics(result) sink.append(detections, custom_data={'':''}) ``` - """ # noqa: E501 // docs + """ def __init__(self, file_name: str = "output.json") -> None: """ @@ -92,7 +92,7 @@ def write_and_close(self) -> None: @staticmethod def parse_detection_data( - detections: Detections, custom_data: Dict[str, Any] = None + detections: Detections, custom_data: Optional[Dict[str, Any]] = None ) -> List[Dict[str, Any]]: parsed_rows = [] for i in range(len(detections.xyxy)): @@ -126,7 +126,7 @@ def parse_detection_data( return parsed_rows def append( - self, detections: Detections, custom_data: Dict[str, Any] = None + self, detections: Detections, custom_data: Optional[Dict[str, Any]] = None ) -> None: """ Append detection data to the JSON file. diff --git a/supervision/detection/tools/smoother.py b/supervision/detection/tools/smoother.py index 9d0d907bf..933d4fa4b 100644 --- a/supervision/detection/tools/smoother.py +++ b/supervision/detection/tools/smoother.py @@ -53,7 +53,7 @@ class DetectionsSmoother: annotated_frame = box_annotator.annotate(frame.copy(), detections) sink.write_frame(annotated_frame) ``` - """ # noqa: E501 // docs + """ def __init__(self, length: int = 5) -> None: """ diff --git a/supervision/keypoint/core.py b/supervision/keypoint/core.py index 39b2f08c4..922c6cab3 100644 --- a/supervision/keypoint/core.py +++ b/supervision/keypoint/core.py @@ -429,7 +429,7 @@ def from_yolo_nas(cls, yolo_nas_results) -> KeyPoints: results = model.predict(image, conf=0.1) key_points = sv.KeyPoints.from_yolo_nas(results) ``` - """ # noqa: E501 // docs + """ if len(yolo_nas_results.prediction.poses) == 0: return cls.empty() diff --git a/supervision/keypoint/skeletons.py b/supervision/keypoint/skeletons.py index e4c27150f..e1bd613a5 100644 --- a/supervision/keypoint/skeletons.py +++ b/supervision/keypoint/skeletons.py @@ -1,11 +1,11 @@ from enum import Enum -from typing import Dict, List, Tuple +from typing import ClassVar, Dict, List, Tuple Edges = List[Tuple[int, int]] class Skeleton(Enum): - COCO = [ + COCO: ClassVar[List[Tuple[int, int]]] = [ (1, 2), (1, 3), (2, 3), @@ -25,7 +25,7 @@ class Skeleton(Enum): (17, 15), ] - GHUM = [ + GHUM: ClassVar[List[Tuple[int, int]]] = [ (1, 2), (1, 5), (2, 3), @@ -63,7 +63,7 @@ class Skeleton(Enum): (31, 33), ] - FACEMESH_TESSELATION_NO_IRIS = [ + FACEMESH_TESSELATION_NO_IRIS: ClassVar[List[Tuple[int, int]]] = [ (128, 35), (35, 140), (140, 128), @@ -2622,7 +2622,7 @@ class Skeleton(Enum): (256, 340), ] - FACEMESH_TESSELATION = [ + FACEMESH_TESSELATION: ClassVar[List[Tuple[int, int]]] = [ (474, 474), (475, 476), (476, 477), @@ -2633,7 +2633,8 @@ class Skeleton(Enum): (471, 472), (472, 473), (473, 470), - ] + FACEMESH_TESSELATION_NO_IRIS + *FACEMESH_TESSELATION_NO_IRIS, + ] SKELETONS_BY_EDGE_COUNT: Dict[int, Edges] = {} diff --git a/supervision/metrics/detection.py b/supervision/metrics/detection.py index e0820fa1d..ee6d2b61f 100644 --- a/supervision/metrics/detection.py +++ b/supervision/metrics/detection.py @@ -440,8 +440,8 @@ def plot( class_names = classes if classes is not None else self.classes use_labels_for_ticks = class_names is not None and (0 < len(class_names) < 99) if use_labels_for_ticks: - x_tick_labels = class_names + ["FN"] - y_tick_labels = class_names + ["FP"] + x_tick_labels = [*class_names, "FN"] + y_tick_labels = [*class_names, "FP"] num_ticks = len(x_tick_labels) else: x_tick_labels = None diff --git a/test/dataset/formats/test_coco.py b/test/dataset/formats/test_coco.py index 7e269dae4..b023a2605 100644 --- a/test/dataset/formats/test_coco.py +++ b/test/dataset/formats/test_coco.py @@ -1,5 +1,5 @@ from contextlib import ExitStack as DoesNotRaise -from typing import Dict, List, Tuple, Union +from typing import Dict, List, Optional, Tuple, Union import numpy as np import pytest @@ -21,7 +21,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: Union[List[list], Dict] = None, + segmentation: Optional[Union[List[list], Dict]] = None, iscrowd: bool = False, ) -> dict: if not segmentation: From a34f0e95973560d9b2fcd2b318fd6ca652cf0e6a Mon Sep 17 00:00:00 2001 From: Onuralp SEZER Date: Thu, 19 Sep 2024 20:30:43 +0300 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20update=20E?= =?UTF-8?q?dges=20type=20from=20List=20to=20Tuple=20for=20better=20perform?= =?UTF-8?q?ance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Onuralp SEZER --- supervision/keypoint/skeletons.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/supervision/keypoint/skeletons.py b/supervision/keypoint/skeletons.py index e1bd613a5..a5ac7b3a3 100644 --- a/supervision/keypoint/skeletons.py +++ b/supervision/keypoint/skeletons.py @@ -1,11 +1,11 @@ from enum import Enum -from typing import ClassVar, Dict, List, Tuple +from typing import Dict, Tuple -Edges = List[Tuple[int, int]] +Edges = Tuple[Tuple[int, int], ...] class Skeleton(Enum): - COCO: ClassVar[List[Tuple[int, int]]] = [ + COCO: Edges = ( (1, 2), (1, 3), (2, 3), @@ -23,9 +23,9 @@ class Skeleton(Enum): (15, 13), (16, 14), (17, 15), - ] + ) - GHUM: ClassVar[List[Tuple[int, int]]] = [ + GHUM: Edges = ( (1, 2), (1, 5), (2, 3), @@ -61,9 +61,9 @@ class Skeleton(Enum): (29, 33), (30, 32), (31, 33), - ] + ) - FACEMESH_TESSELATION_NO_IRIS: ClassVar[List[Tuple[int, int]]] = [ + FACEMESH_TESSELATION_NO_IRIS: Edges = ( (128, 35), (35, 140), (140, 128), @@ -2620,9 +2620,9 @@ class Skeleton(Enum): (340, 449), (449, 256), (256, 340), - ] + ) - FACEMESH_TESSELATION: ClassVar[List[Tuple[int, int]]] = [ + FACEMESH_TESSELATION: Edges = ( (474, 474), (475, 476), (476, 477), @@ -2634,7 +2634,7 @@ class Skeleton(Enum): (472, 473), (473, 470), *FACEMESH_TESSELATION_NO_IRIS, - ] + ) SKELETONS_BY_EDGE_COUNT: Dict[int, Edges] = {}