From 5df9730b3fe32674e834cba82ea58971d97926d1 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Thu, 4 Jan 2024 20:08:01 +0100 Subject: [PATCH 01/18] =?UTF-8?q?=F0=9F=9A=97=F0=9F=92=A8=F0=9F=92=A8?= =?UTF-8?q?=F0=9F=92=A8=20speed=20estimation=20example=20initial=20commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/README.md | 1 + examples/speed_estimation/.gitignore | 2 + examples/speed_estimation/README.md | 73 +++++++++++++++++++ examples/speed_estimation/requirements.txt | 5 ++ .../speed_estimation/ultralytics_example.py | 56 ++++++++++++++ examples/traffic_analysis/.gitignore | 1 + 6 files changed, 138 insertions(+) create mode 100644 examples/speed_estimation/.gitignore create mode 100644 examples/speed_estimation/README.md create mode 100644 examples/speed_estimation/requirements.txt create mode 100644 examples/speed_estimation/ultralytics_example.py diff --git a/examples/README.md b/examples/README.md index f3f04c71..936a7402 100644 --- a/examples/README.md +++ b/examples/README.md @@ -7,6 +7,7 @@ interfaces with diverse applications. - [tracking](./tracking) by [@SkalskiP](https://github.com/SkalskiP) - [count people in zone](./count_people_in_zone) by [@SkalskiP](https://github.com/SkalskiP) - [traffic analysis](./traffic_analysis) by [@SkalskiP](https://github.com/SkalskiP) +- [speed estimation](./speed_estimation) by [@SkalskiP](https://github.com/SkalskiP) - [heatmap and track](./heatmap_and_track/) by [@HinePo](https://github.com/HinePo) ## contributing diff --git a/examples/speed_estimation/.gitignore b/examples/speed_estimation/.gitignore new file mode 100644 index 00000000..9435cafc --- /dev/null +++ b/examples/speed_estimation/.gitignore @@ -0,0 +1,2 @@ +data/ +venv/ \ No newline at end of file diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md new file mode 100644 index 00000000..d0beea4a --- /dev/null +++ b/examples/speed_estimation/README.md @@ -0,0 +1,73 @@ +# speed estimation + +## 👋 hello + +TODO + +## 💻 install + +- clone repository and navigate to example directory + + ```bash + git clone https://github.com/roboflow/supervision.git + cd supervision/examples/speed_estimation + ``` + +- setup python environment and activate it [optional] + + ```bash + python3 -m venv venv + source venv/bin/activate + ``` + +- install required dependencies + + ```bash + pip install -r requirements.txt + ``` + +## 🛠️ script arguments + +- `--source_weights_path`: Required. Specifies the path to the YOLO model's weights + file, which is essential for the object detection process. This file contains the + data that the model uses to identify objects in the video. +- `--source_video_path`: Required. The path to the source video file that will be + analyzed. This is the input video on which traffic flow analysis will be performed. +- `--target_video_path` (optional): The path to save the output video with + annotations. If not specified, the processed video will be displayed in real-time + without being saved. +- `--confidence_threshold` (optional): Sets the confidence threshold for the YOLO + model to filter detections. Default is `0.3`. This determines how confident the + model should be to recognize an object in the video. +- `--iou_threshold` (optional): Specifies the IOU (Intersection Over Union) threshold + for the model. Default is 0.7. This value is used to manage object detection + accuracy, particularly in distinguishing between different objects. + +## 📌 line configuration + +TODO + +## ⚙️ run + +```bash + python ultralytics_example.py \ + --source_weights_path yolov8x.pt \ + --lines_configuration_path data/vehicles-config.json \ + --source_video_path data/vehicles.mp4 \ + --confidence_threshold 0.3 \ + --iou_threshold 0.5 +``` + +## © license + +This demo integrates two main components, each with its own licensing: + +- ultralytics: The object detection model used in this demo, YOLOv8, is distributed + under the [AGPL-3.0 license](https://github.com/ultralytics/ultralytics/blob/main/LICENSE). + You can find more details about this license here. + +- supervision: The analytics code that powers the zone-based analysis in this demo is + based on the Supervision library, which is licensed under the + [MIT license](https://github.com/roboflow/supervision/blob/develop/LICENSE.md). This + makes the Supervision part of the code fully open source and freely usable in your + projects. \ No newline at end of file diff --git a/examples/speed_estimation/requirements.txt b/examples/speed_estimation/requirements.txt new file mode 100644 index 00000000..537df5eb --- /dev/null +++ b/examples/speed_estimation/requirements.txt @@ -0,0 +1,5 @@ +gdown +inference +supervision[asserts] +tqdm +ultralytics \ No newline at end of file diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py new file mode 100644 index 00000000..4b29cf03 --- /dev/null +++ b/examples/speed_estimation/ultralytics_example.py @@ -0,0 +1,56 @@ +import cv2 +import argparse +import supervision as sv + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Vehicle Speed Estimation using Supervision Package" + ) + + parser.add_argument( + "--lines_configuration_path", + required=True, + help="Path to the lines configuration JSON file", + type=str, + ) + parser.add_argument( + "--source_weights_path", + required=True, + help="Path to the source weights file", + type=str, + ) + parser.add_argument( + "--source_video_path", + required=True, + help="Path to the source video file", + type=str, + ) + parser.add_argument( + "--target_video_path", + default=None, + help="Path to the target video file (output)", + type=str, + ) + parser.add_argument( + "--confidence_threshold", + default=0.3, + help="Confidence threshold for the model", + type=float, + ) + parser.add_argument( + "--iou_threshold", + default=0.7, + help="IOU threshold for the model", + type=float + ) + + args = parser.parse_args() + + video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) + frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) + + for frame in frame_generator: + cv2.imshow("frame", frame) + if cv2.waitKey(1) & 0xFF == ord("q"): + break + cv2.destroyAllWindows() diff --git a/examples/traffic_analysis/.gitignore b/examples/traffic_analysis/.gitignore index 8fce6030..9435cafc 100644 --- a/examples/traffic_analysis/.gitignore +++ b/examples/traffic_analysis/.gitignore @@ -1 +1,2 @@ data/ +venv/ \ No newline at end of file From 2e9b2a1bcb610cb3b38ca6a22d55368791ede439 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Thu, 4 Jan 2024 20:54:37 +0100 Subject: [PATCH 02/18] detection, tracking and annotation added --- .../speed_estimation/ultralytics_example.py | 90 ++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index 4b29cf03..f65653ba 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -1,7 +1,40 @@ -import cv2 import argparse +import json +from dataclasses import dataclass +from typing import List + +import cv2 +from ultralytics import YOLO + import supervision as sv + +COLOR = sv.Color.red() + + +@dataclass +class Line: + start: sv.Point + end: sv.Point + + +@dataclass +class Config: + lines: List[Line] + distance: float + + @classmethod + def load(cls, file_path: str): + with open(file_path, 'r') as file: + data = json.load(file) + lines = [ + Line(sv.Point(**line['start']), sv.Point(**line['end'])) + for line + in data['lines'] + ] + return cls(lines, data['distance']) + + if __name__ == "__main__": parser = argparse.ArgumentParser( description="Vehicle Speed Estimation using Supervision Package" @@ -46,11 +79,64 @@ if __name__ == "__main__": args = parser.parse_args() + config = Config.load(args.lines_configuration_path) video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) + + model = YOLO(args.source_weights_path) + byte_track = sv.ByteTrack(frame_rate=video_info.fps) + + thickness = sv.calculate_dynamic_line_thickness( + resolution_wh=video_info.resolution_wh) + text_scale = sv.calculate_dynamic_text_scale( + resolution_wh=video_info.resolution_wh) + + bounding_box_annotator = sv.BoundingBoxAnnotator( + thickness=thickness, color=COLOR) + label_annotator = sv.LabelAnnotator( + text_scale=text_scale, text_thickness=thickness, color=COLOR, + text_position=sv.Position.BOTTOM_CENTER) + trace_annotator = sv.TraceAnnotator( + thickness=thickness, color=COLOR, trace_length=video_info.fps, + position=sv.Position.BOTTOM_CENTER) + frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) for frame in frame_generator: - cv2.imshow("frame", frame) + result = model(frame)[0] + detections = sv.Detections.from_ultralytics(result) + detections = byte_track.update_with_detections(detections) + + labels = [ + f"#{tracker_id}" + for _, _, _, _, tracker_id + in detections + ] + + annotated_frame = frame.copy() + annotated_frame = sv.draw_line( + scene=annotated_frame, + start=config.lines[0].start, + end=config.lines[0].end, + color=sv.Color.white(), + thickness=2) + annotated_frame = sv.draw_line( + scene=annotated_frame, + start=config.lines[1].start, + end=config.lines[1].end, + color=sv.Color.white(), + thickness=2) + annotated_frame = bounding_box_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = trace_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = label_annotator.annotate( + scene=annotated_frame, + detections=detections, + labels=labels) + + cv2.imshow("frame", annotated_frame) if cv2.waitKey(1) & 0xFF == ord("q"): break cv2.destroyAllWindows() From 7e8d44ac35804cba17f50f13f94f6eda67c2a3ae Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Thu, 4 Jan 2024 22:35:59 +0100 Subject: [PATCH 03/18] dropping idea of using lines to calculate speed --- .../speed_estimation/ultralytics_example.py | 66 +++++-------------- 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index f65653ba..2f130be6 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -1,51 +1,26 @@ import argparse -import json -from dataclasses import dataclass -from typing import List import cv2 +import numpy as np from ultralytics import YOLO import supervision as sv - COLOR = sv.Color.red() +ZONE = np.array([ + [1252, 787], + [2298, 803], + [5039, 2159], + [-550, 2159] +]) - -@dataclass -class Line: - start: sv.Point - end: sv.Point - - -@dataclass -class Config: - lines: List[Line] - distance: float - - @classmethod - def load(cls, file_path: str): - with open(file_path, 'r') as file: - data = json.load(file) - lines = [ - Line(sv.Point(**line['start']), sv.Point(**line['end'])) - for line - in data['lines'] - ] - return cls(lines, data['distance']) +polygon_zone = sv.PolygonZone(polygon=ZONE, frame_resolution_wh=(3840, 2160)) if __name__ == "__main__": parser = argparse.ArgumentParser( description="Vehicle Speed Estimation using Supervision Package" ) - - parser.add_argument( - "--lines_configuration_path", - required=True, - help="Path to the lines configuration JSON file", - type=str, - ) parser.add_argument( "--source_weights_path", required=True, @@ -79,11 +54,11 @@ if __name__ == "__main__": args = parser.parse_args() - config = Config.load(args.lines_configuration_path) video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) model = YOLO(args.source_weights_path) - byte_track = sv.ByteTrack(frame_rate=video_info.fps) + byte_track = sv.ByteTrack( + frame_rate=video_info.fps, track_thresh=args.confidence_threshold) thickness = sv.calculate_dynamic_line_thickness( resolution_wh=video_info.resolution_wh) @@ -96,7 +71,7 @@ if __name__ == "__main__": text_scale=text_scale, text_thickness=thickness, color=COLOR, text_position=sv.Position.BOTTOM_CENTER) trace_annotator = sv.TraceAnnotator( - thickness=thickness, color=COLOR, trace_length=video_info.fps, + thickness=thickness, color=COLOR, trace_length=video_info.fps * 2, position=sv.Position.BOTTOM_CENTER) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) @@ -104,7 +79,9 @@ if __name__ == "__main__": for frame in frame_generator: result = model(frame)[0] detections = sv.Detections.from_ultralytics(result) - detections = byte_track.update_with_detections(detections) + detections = detections[detections.confidence > args.confidence_threshold] + detections = detections[polygon_zone.trigger(detections)] + detections = byte_track.update_with_detections(detections=detections) labels = [ f"#{tracker_id}" @@ -113,18 +90,11 @@ if __name__ == "__main__": ] annotated_frame = frame.copy() - annotated_frame = sv.draw_line( + annotated_frame = sv.draw_polygon( scene=annotated_frame, - start=config.lines[0].start, - end=config.lines[0].end, - color=sv.Color.white(), - thickness=2) - annotated_frame = sv.draw_line( - scene=annotated_frame, - start=config.lines[1].start, - end=config.lines[1].end, - color=sv.Color.white(), - thickness=2) + polygon=ZONE, + color=COLOR, + thickness=thickness) annotated_frame = bounding_box_annotator.annotate( scene=annotated_frame, detections=detections) From d83547ec8027dee9d461a27c2c99c3bf079f53de Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Thu, 4 Jan 2024 23:38:47 +0100 Subject: [PATCH 04/18] initial working version --- .../speed_estimation/ultralytics_example.py | 109 ++++++++++++------ 1 file changed, 75 insertions(+), 34 deletions(-) diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index 2f130be6..ac5a9103 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -1,4 +1,5 @@ import argparse +from collections import defaultdict, deque import cv2 import numpy as np @@ -7,14 +8,40 @@ from ultralytics import YOLO import supervision as sv COLOR = sv.Color.red() -ZONE = np.array([ + +SOURCE = np.array([ [1252, 787], [2298, 803], [5039, 2159], [-550, 2159] ]) -polygon_zone = sv.PolygonZone(polygon=ZONE, frame_resolution_wh=(3840, 2160)) +TARGET_WIDTH = 25 +TARGET_HEIGHT = 250 + +TARGET = np.array([ + [0, 0], + [TARGET_WIDTH - 1, 0], + [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], + [0, TARGET_HEIGHT - 1] +]) + + +class ViewTransformer: + + def __init__(self, m: np.ndarray) -> None: + self.m = m + + @classmethod + def initialize(cls, source: np.ndarray, target: np.ndarray) -> 'ViewTransformer': + source = source.astype(np.float32) + target = target.astype(np.float32) + return cls(m=cv2.getPerspectiveTransform(source, target)) + + def transform_points(self, points: np.ndarray) -> np.ndarray: + reshaped_points = points.reshape(-1, 1, 2).astype(np.float32) + transformed_points = cv2.perspectiveTransform(reshaped_points, self.m) + return transformed_points.reshape(-1, 2) if __name__ == "__main__": @@ -71,42 +98,56 @@ if __name__ == "__main__": text_scale=text_scale, text_thickness=thickness, color=COLOR, text_position=sv.Position.BOTTOM_CENTER) trace_annotator = sv.TraceAnnotator( - thickness=thickness, color=COLOR, trace_length=video_info.fps * 2, + thickness=thickness, color=COLOR, trace_length=video_info.fps, position=sv.Position.BOTTOM_CENTER) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) - for frame in frame_generator: - result = model(frame)[0] - detections = sv.Detections.from_ultralytics(result) - detections = detections[detections.confidence > args.confidence_threshold] - detections = detections[polygon_zone.trigger(detections)] - detections = byte_track.update_with_detections(detections=detections) + polygon_zone = sv.PolygonZone( + polygon=SOURCE, frame_resolution_wh=video_info.resolution_wh) + view_transformer = ViewTransformer.initialize(source=SOURCE, target=TARGET) - labels = [ - f"#{tracker_id}" - for _, _, _, _, tracker_id - in detections - ] + position = defaultdict(lambda: deque(maxlen=video_info.fps)) - annotated_frame = frame.copy() - annotated_frame = sv.draw_polygon( - scene=annotated_frame, - polygon=ZONE, - color=COLOR, - thickness=thickness) - annotated_frame = bounding_box_annotator.annotate( - scene=annotated_frame, - detections=detections) - annotated_frame = trace_annotator.annotate( - scene=annotated_frame, - detections=detections) - annotated_frame = label_annotator.annotate( - scene=annotated_frame, - detections=detections, - labels=labels) + with sv.VideoSink('data/result.mp4', video_info) as sink: + for frame in frame_generator: + result = model(frame)[0] + detections = sv.Detections.from_ultralytics(result) + detections = detections[detections.confidence > args.confidence_threshold] + detections = detections[polygon_zone.trigger(detections)] + detections = byte_track.update_with_detections(detections=detections) - cv2.imshow("frame", annotated_frame) - if cv2.waitKey(1) & 0xFF == ord("q"): - break - cv2.destroyAllWindows() + points = detections.get_anchors_coordinates(anchor=sv.Position.BOTTOM_CENTER) + points = view_transformer.transform_points(points=points).astype(int) + + labels = [] + for tracker_id, [_, y] in zip(detections.tracker_id, points): + position[tracker_id].append(y) + if len(position[tracker_id]) < video_info.fps / 2: + labels.append(f"#{tracker_id}") + else: + speed = abs(position[tracker_id][-1] - position[tracker_id][0]) * video_info.fps / len(position[tracker_id]) * 3.6 + labels.append(f"#{tracker_id} {int(speed)} km/h") + + annotated_frame = frame.copy() + annotated_frame = sv.draw_polygon( + scene=annotated_frame, + polygon=SOURCE, + color=COLOR, + thickness=thickness) + annotated_frame = bounding_box_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = trace_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = label_annotator.annotate( + scene=annotated_frame, + detections=detections, + labels=labels) + + sink.write_frame(annotated_frame) + cv2.imshow("frame", annotated_frame) + if cv2.waitKey(1) & 0xFF == ord("q"): + break + cv2.destroyAllWindows() From 3e6c1799ef81bb492ca5ad6fd3604dd61793b25c Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Fri, 5 Jan 2024 16:51:27 +0100 Subject: [PATCH 05/18] current version --- .../speed_estimation/ultralytics_example.py | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index ac5a9103..aefab334 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -4,6 +4,7 @@ from collections import defaultdict, deque import cv2 import numpy as np from ultralytics import YOLO +from tqdm import tqdm import supervision as sv @@ -43,6 +44,9 @@ class ViewTransformer: transformed_points = cv2.perspectiveTransform(reshaped_points, self.m) return transformed_points.reshape(-1, 2) + def transform_image(self, image: np.ndarray, width: int, height: int) -> np.ndarray: + return cv2.warpPerspective(image, self.m, (width, height)) + if __name__ == "__main__": parser = argparse.ArgumentParser( @@ -92,14 +96,14 @@ if __name__ == "__main__": text_scale = sv.calculate_dynamic_text_scale( resolution_wh=video_info.resolution_wh) - bounding_box_annotator = sv.BoundingBoxAnnotator( - thickness=thickness, color=COLOR) + box_corner_annotator = sv.BoxCornerAnnotator( + thickness=thickness, color_lookup=sv.ColorLookup.TRACK) label_annotator = sv.LabelAnnotator( - text_scale=text_scale, text_thickness=thickness, color=COLOR, - text_position=sv.Position.BOTTOM_CENTER) + text_scale=text_scale, text_thickness=thickness, + text_position=sv.Position.BOTTOM_CENTER, color_lookup=sv.ColorLookup.TRACK) trace_annotator = sv.TraceAnnotator( - thickness=thickness, color=COLOR, trace_length=video_info.fps, - position=sv.Position.BOTTOM_CENTER) + thickness=thickness, trace_length=video_info.fps * 2, + position=sv.Position.BOTTOM_CENTER, color_lookup=sv.ColorLookup.TRACK) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) @@ -109,11 +113,12 @@ if __name__ == "__main__": position = defaultdict(lambda: deque(maxlen=video_info.fps)) - with sv.VideoSink('data/result.mp4', video_info) as sink: + with sv.VideoSink(args.target_video_path, video_info) as sink: for frame in frame_generator: - result = model(frame)[0] + result = model(frame, imgsz=1280)[0] detections = sv.Detections.from_ultralytics(result) detections = detections[detections.confidence > args.confidence_threshold] + detections = detections[detections.class_id != 0] detections = detections[polygon_zone.trigger(detections)] detections = byte_track.update_with_detections(detections=detections) @@ -126,16 +131,17 @@ if __name__ == "__main__": if len(position[tracker_id]) < video_info.fps / 2: labels.append(f"#{tracker_id}") else: - speed = abs(position[tracker_id][-1] - position[tracker_id][0]) * video_info.fps / len(position[tracker_id]) * 3.6 + distance = abs(position[tracker_id][-1] - position[tracker_id][0]) + speed = distance * video_info.fps / len(position[tracker_id]) * 3.6 labels.append(f"#{tracker_id} {int(speed)} km/h") annotated_frame = frame.copy() - annotated_frame = sv.draw_polygon( - scene=annotated_frame, - polygon=SOURCE, - color=COLOR, - thickness=thickness) - annotated_frame = bounding_box_annotator.annotate( + # annotated_frame = sv.draw_polygon( + # scene=annotated_frame, + # polygon=SOURCE, + # color=COLOR, + # thickness=thickness) + annotated_frame = box_corner_annotator.annotate( scene=annotated_frame, detections=detections) annotated_frame = trace_annotator.annotate( From 5ce65a2fd5d80bd7fd77e5af608816569bf99e74 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 08:11:40 +0100 Subject: [PATCH 06/18] current version --- .../speed_estimation/ultralytics_example.py | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index aefab334..ab47f3ec 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -4,7 +4,6 @@ from collections import defaultdict, deque import cv2 import numpy as np from ultralytics import YOLO -from tqdm import tqdm import supervision as sv @@ -30,23 +29,16 @@ TARGET = np.array([ class ViewTransformer: - def __init__(self, m: np.ndarray) -> None: - self.m = m - - @classmethod - def initialize(cls, source: np.ndarray, target: np.ndarray) -> 'ViewTransformer': + def __init__(self, source: np.ndarray, target: np.ndarray) -> None: source = source.astype(np.float32) target = target.astype(np.float32) - return cls(m=cv2.getPerspectiveTransform(source, target)) + self.m = cv2.getPerspectiveTransform(source, target) def transform_points(self, points: np.ndarray) -> np.ndarray: reshaped_points = points.reshape(-1, 1, 2).astype(np.float32) transformed_points = cv2.perspectiveTransform(reshaped_points, self.m) return transformed_points.reshape(-1, 2) - def transform_image(self, image: np.ndarray, width: int, height: int) -> np.ndarray: - return cv2.warpPerspective(image, self.m, (width, height)) - if __name__ == "__main__": parser = argparse.ArgumentParser( @@ -96,20 +88,20 @@ if __name__ == "__main__": text_scale = sv.calculate_dynamic_text_scale( resolution_wh=video_info.resolution_wh) - box_corner_annotator = sv.BoxCornerAnnotator( - thickness=thickness, color_lookup=sv.ColorLookup.TRACK) + box_corner_annotator = sv.BoundingBoxAnnotator( + thickness=thickness) label_annotator = sv.LabelAnnotator( text_scale=text_scale, text_thickness=thickness, - text_position=sv.Position.BOTTOM_CENTER, color_lookup=sv.ColorLookup.TRACK) + text_position=sv.Position.BOTTOM_CENTER) trace_annotator = sv.TraceAnnotator( thickness=thickness, trace_length=video_info.fps * 2, - position=sv.Position.BOTTOM_CENTER, color_lookup=sv.ColorLookup.TRACK) + position=sv.Position.BOTTOM_CENTER) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) polygon_zone = sv.PolygonZone( polygon=SOURCE, frame_resolution_wh=video_info.resolution_wh) - view_transformer = ViewTransformer.initialize(source=SOURCE, target=TARGET) + view_transformer = ViewTransformer(source=SOURCE, target=TARGET) position = defaultdict(lambda: deque(maxlen=video_info.fps)) @@ -118,7 +110,6 @@ if __name__ == "__main__": result = model(frame, imgsz=1280)[0] detections = sv.Detections.from_ultralytics(result) detections = detections[detections.confidence > args.confidence_threshold] - detections = detections[detections.class_id != 0] detections = detections[polygon_zone.trigger(detections)] detections = byte_track.update_with_detections(detections=detections) @@ -136,15 +127,10 @@ if __name__ == "__main__": labels.append(f"#{tracker_id} {int(speed)} km/h") annotated_frame = frame.copy() - # annotated_frame = sv.draw_polygon( - # scene=annotated_frame, - # polygon=SOURCE, - # color=COLOR, - # thickness=thickness) - annotated_frame = box_corner_annotator.annotate( + annotated_frame = trace_annotator.annotate( scene=annotated_frame, detections=detections) - annotated_frame = trace_annotator.annotate( + annotated_frame = box_corner_annotator.annotate( scene=annotated_frame, detections=detections) annotated_frame = label_annotator.annotate( From 0a7e116d7f7f3842d5b3a387797a32181c70a44d Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 08:34:55 +0100 Subject: [PATCH 07/18] added `script.sh` and updated `README.md` --- examples/speed_estimation/README.md | 10 ++++++---- examples/speed_estimation/setup.sh | 14 ++++++++++++++ examples/speed_estimation/ultralytics_example.py | 1 - 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 examples/speed_estimation/setup.sh diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index d0beea4a..1be961f6 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -26,6 +26,12 @@ TODO pip install -r requirements.txt ``` +- download `vehicles.mp4` file + + ```bash + ./setup.sh + ``` + ## 🛠️ script arguments - `--source_weights_path`: Required. Specifies the path to the YOLO model's weights @@ -43,10 +49,6 @@ TODO for the model. Default is 0.7. This value is used to manage object detection accuracy, particularly in distinguishing between different objects. -## 📌 line configuration - -TODO - ## ⚙️ run ```bash diff --git a/examples/speed_estimation/setup.sh b/examples/speed_estimation/setup.sh new file mode 100644 index 00000000..6e9e82bb --- /dev/null +++ b/examples/speed_estimation/setup.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Get the directory where the script is located +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Check if 'data' directory does not exist and then create it +if [[ ! -e $DIR/data ]]; then + mkdir "$DIR/data" +else + echo "'data' directory already exists." +fi + +# Download the vehicles.mp4 file from Google Drive +gdown -O "$DIR/data/vehicles.mp4" "https://drive.google.com/uc?id=1pz68D1Gsx80MoPg-_q-IbEdESEmyVLm-" diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index ab47f3ec..8ee6e405 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -7,7 +7,6 @@ from ultralytics import YOLO import supervision as sv -COLOR = sv.Color.red() SOURCE = np.array([ [1252, 787], From 949e3265593025e5be40228ce3f7cbf1117bd5c6 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 08:55:28 +0100 Subject: [PATCH 08/18] updated `README.md` and `ultralytics_example.py` --- examples/speed_estimation/README.md | 4 +++- .../speed_estimation/ultralytics_example.py | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index 1be961f6..f7e5b0df 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -2,7 +2,9 @@ ## 👋 hello -TODO +This example performs speed estimation analysis using various object-detection models +and ByteTrack - a simple yet effective online multi-object tracking method. It uses the +supervision package for multiple tasks such as tracking, annotations, etc. ## 💻 install diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index 8ee6e405..16e419bb 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -102,7 +102,7 @@ if __name__ == "__main__": polygon=SOURCE, frame_resolution_wh=video_info.resolution_wh) view_transformer = ViewTransformer(source=SOURCE, target=TARGET) - position = defaultdict(lambda: deque(maxlen=video_info.fps)) + coordinates = defaultdict(lambda: deque(maxlen=video_info.fps)) with sv.VideoSink(args.target_video_path, video_info) as sink: for frame in frame_generator: @@ -110,19 +110,25 @@ if __name__ == "__main__": detections = sv.Detections.from_ultralytics(result) detections = detections[detections.confidence > args.confidence_threshold] detections = detections[polygon_zone.trigger(detections)] + detections = detections.with_nms(threshold=args.iou_threshold) detections = byte_track.update_with_detections(detections=detections) points = detections.get_anchors_coordinates(anchor=sv.Position.BOTTOM_CENTER) points = view_transformer.transform_points(points=points).astype(int) - labels = [] for tracker_id, [_, y] in zip(detections.tracker_id, points): - position[tracker_id].append(y) - if len(position[tracker_id]) < video_info.fps / 2: + coordinates[tracker_id].append(y) + + labels = [] + for tracker_id in detections.tracker_id: + if len(coordinates[tracker_id]) < video_info.fps / 2: labels.append(f"#{tracker_id}") else: - distance = abs(position[tracker_id][-1] - position[tracker_id][0]) - speed = distance * video_info.fps / len(position[tracker_id]) * 3.6 + coordinate_start = coordinates[tracker_id][-1] + coordinate_end = coordinates[tracker_id][0] + distance = abs(coordinate_start - coordinate_end) + time = len(coordinates[tracker_id]) / video_info.fps + speed = distance / time * 3.6 labels.append(f"#{tracker_id} {int(speed)} km/h") annotated_frame = frame.copy() From 351ef464d95b9769d1af7719a5fc801eda00ac8d Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 12:04:29 +0100 Subject: [PATCH 09/18] initial version of `yolo_nas_example.py` script --- examples/speed_estimation/.gitignore | 2 +- examples/speed_estimation/README.md | 4 +- examples/speed_estimation/requirements.txt | 9 ++-- .../speed_estimation/ultralytics_example.py | 28 +++++++----- examples/speed_estimation/yolo_nas_example.py | 45 +++++++++++++++++++ 5 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 examples/speed_estimation/yolo_nas_example.py diff --git a/examples/speed_estimation/.gitignore b/examples/speed_estimation/.gitignore index 9435cafc..27cca3bd 100644 --- a/examples/speed_estimation/.gitignore +++ b/examples/speed_estimation/.gitignore @@ -1,2 +1,2 @@ data/ -venv/ \ No newline at end of file +venv*/ \ No newline at end of file diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index f7e5b0df..7833e18b 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -41,7 +41,7 @@ supervision package for multiple tasks such as tracking, annotations, etc. data that the model uses to identify objects in the video. - `--source_video_path`: Required. The path to the source video file that will be analyzed. This is the input video on which traffic flow analysis will be performed. -- `--target_video_path` (optional): The path to save the output video with +- `--target_video_path`: The path to save the output video with annotations. If not specified, the processed video will be displayed in real-time without being saved. - `--confidence_threshold` (optional): Sets the confidence threshold for the YOLO @@ -56,8 +56,8 @@ supervision package for multiple tasks such as tracking, annotations, etc. ```bash python ultralytics_example.py \ --source_weights_path yolov8x.pt \ - --lines_configuration_path data/vehicles-config.json \ --source_video_path data/vehicles.mp4 \ + --target_video_path data/vehicles-result.mp4 \ --confidence_threshold 0.3 \ --iou_threshold 0.5 ``` diff --git a/examples/speed_estimation/requirements.txt b/examples/speed_estimation/requirements.txt index 537df5eb..7365d559 100644 --- a/examples/speed_estimation/requirements.txt +++ b/examples/speed_estimation/requirements.txt @@ -1,5 +1,6 @@ gdown -inference -supervision[asserts] -tqdm -ultralytics \ No newline at end of file +supervision + +ultralytics +super-gradients +inference \ No newline at end of file diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index 16e419bb..9b5d84a0 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -7,7 +7,6 @@ from ultralytics import YOLO import supervision as sv - SOURCE = np.array([ [1252, 787], [2298, 803], @@ -39,7 +38,7 @@ class ViewTransformer: return transformed_points.reshape(-1, 2) -if __name__ == "__main__": +def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Vehicle Speed Estimation using Supervision Package" ) @@ -57,7 +56,7 @@ if __name__ == "__main__": ) parser.add_argument( "--target_video_path", - default=None, + required=True, help="Path to the target video file (output)", type=str, ) @@ -74,39 +73,46 @@ if __name__ == "__main__": type=float ) - args = parser.parse_args() + return parser.parse_args() + + +if __name__ == "__main__": + args = parse_arguments() video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) - model = YOLO(args.source_weights_path) + byte_track = sv.ByteTrack( - frame_rate=video_info.fps, track_thresh=args.confidence_threshold) + frame_rate=video_info.fps, + track_thresh=args.confidence_threshold) thickness = sv.calculate_dynamic_line_thickness( resolution_wh=video_info.resolution_wh) text_scale = sv.calculate_dynamic_text_scale( resolution_wh=video_info.resolution_wh) - box_corner_annotator = sv.BoundingBoxAnnotator( thickness=thickness) label_annotator = sv.LabelAnnotator( - text_scale=text_scale, text_thickness=thickness, + text_scale=text_scale, + text_thickness=thickness, text_position=sv.Position.BOTTOM_CENTER) trace_annotator = sv.TraceAnnotator( - thickness=thickness, trace_length=video_info.fps * 2, + thickness=thickness, + trace_length=video_info.fps * 2, position=sv.Position.BOTTOM_CENTER) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) polygon_zone = sv.PolygonZone( - polygon=SOURCE, frame_resolution_wh=video_info.resolution_wh) + polygon=SOURCE, + frame_resolution_wh=video_info.resolution_wh) view_transformer = ViewTransformer(source=SOURCE, target=TARGET) coordinates = defaultdict(lambda: deque(maxlen=video_info.fps)) with sv.VideoSink(args.target_video_path, video_info) as sink: for frame in frame_generator: - result = model(frame, imgsz=1280)[0] + result = model(frame)[0] detections = sv.Detections.from_ultralytics(result) detections = detections[detections.confidence > args.confidence_threshold] detections = detections[polygon_zone.trigger(detections)] diff --git a/examples/speed_estimation/yolo_nas_example.py b/examples/speed_estimation/yolo_nas_example.py new file mode 100644 index 00000000..79eabe15 --- /dev/null +++ b/examples/speed_estimation/yolo_nas_example.py @@ -0,0 +1,45 @@ +import argparse + +from super_gradients.training import models +from super_gradients.common.object_names import Models + +import supervision as sv + + +def parse_arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Vehicle Speed Estimation using Supervision Package" + ) + parser.add_argument( + "--source_video_path", + required=True, + help="Path to the source video file", + type=str, + ) + parser.add_argument( + "--target_video_path", + required=True, + help="Path to the target video file (output)", + type=str, + ) + parser.add_argument( + "--confidence_threshold", + default=0.3, + help="Confidence threshold for the model", + type=float, + ) + parser.add_argument( + "--iou_threshold", + default=0.7, + help="IOU threshold for the model", + type=float + ) + + return parser.parse_args() + + +if __name__ == "__main__": + args = parse_arguments() + + video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) + model = models.get(Models.YOLO_NAS_L, pretrained_weights="coco") \ No newline at end of file From e009402934f57931e5bbbfa22f541f664a458122 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 12:26:43 +0100 Subject: [PATCH 10/18] `yolo_nas_example.py` script is ready --- examples/speed_estimation/README.md | 27 +++-- .../speed_estimation/ultralytics_example.py | 14 +-- examples/speed_estimation/yolo_nas_example.py | 111 +++++++++++++++++- 3 files changed, 132 insertions(+), 20 deletions(-) diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index 7833e18b..4dea9e88 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -53,14 +53,25 @@ supervision package for multiple tasks such as tracking, annotations, etc. ## ⚙️ run -```bash - python ultralytics_example.py \ - --source_weights_path yolov8x.pt \ - --source_video_path data/vehicles.mp4 \ - --target_video_path data/vehicles-result.mp4 \ - --confidence_threshold 0.3 \ - --iou_threshold 0.5 -``` +- yolo-nas + + ```bash + python yolo_nas_example.py \ + --source_video_path data/vehicles.mp4 \ + --target_video_path data/vehicles-result.mp4 \ + --confidence_threshold 0.3 \ + --iou_threshold 0.5 + ``` + +- ultralytics + + ```bash + python ultralytics_example.py \ + --source_video_path data/vehicles.mp4 \ + --target_video_path data/vehicles-result.mp4 \ + --confidence_threshold 0.3 \ + --iou_threshold 0.5 + ``` ## © license diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index 9b5d84a0..b397a527 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -40,13 +40,7 @@ class ViewTransformer: def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser( - description="Vehicle Speed Estimation using Supervision Package" - ) - parser.add_argument( - "--source_weights_path", - required=True, - help="Path to the source weights file", - type=str, + description="Vehicle Speed Estimation using Ultralytics and Supervision" ) parser.add_argument( "--source_video_path", @@ -80,7 +74,7 @@ if __name__ == "__main__": args = parse_arguments() video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) - model = YOLO(args.source_weights_path) + model = YOLO('yolov8x.pt') byte_track = sv.ByteTrack( frame_rate=video_info.fps, @@ -90,7 +84,7 @@ if __name__ == "__main__": resolution_wh=video_info.resolution_wh) text_scale = sv.calculate_dynamic_text_scale( resolution_wh=video_info.resolution_wh) - box_corner_annotator = sv.BoundingBoxAnnotator( + bounding_box_annotator = sv.BoundingBoxAnnotator( thickness=thickness) label_annotator = sv.LabelAnnotator( text_scale=text_scale, @@ -141,7 +135,7 @@ if __name__ == "__main__": annotated_frame = trace_annotator.annotate( scene=annotated_frame, detections=detections) - annotated_frame = box_corner_annotator.annotate( + annotated_frame = bounding_box_annotator.annotate( scene=annotated_frame, detections=detections) annotated_frame = label_annotator.annotate( diff --git a/examples/speed_estimation/yolo_nas_example.py b/examples/speed_estimation/yolo_nas_example.py index 79eabe15..9862dfbf 100644 --- a/examples/speed_estimation/yolo_nas_example.py +++ b/examples/speed_estimation/yolo_nas_example.py @@ -1,14 +1,48 @@ import argparse +from collections import defaultdict, deque from super_gradients.training import models from super_gradients.common.object_names import Models +import cv2 +import numpy as np + import supervision as sv +SOURCE = np.array([ + [1252, 787], + [2298, 803], + [5039, 2159], + [-550, 2159] +]) + +TARGET_WIDTH = 25 +TARGET_HEIGHT = 250 + +TARGET = np.array([ + [0, 0], + [TARGET_WIDTH - 1, 0], + [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], + [0, TARGET_HEIGHT - 1] +]) + + +class ViewTransformer: + + def __init__(self, source: np.ndarray, target: np.ndarray) -> None: + source = source.astype(np.float32) + target = target.astype(np.float32) + self.m = cv2.getPerspectiveTransform(source, target) + + def transform_points(self, points: np.ndarray) -> np.ndarray: + reshaped_points = points.reshape(-1, 1, 2).astype(np.float32) + transformed_points = cv2.perspectiveTransform(reshaped_points, self.m) + return transformed_points.reshape(-1, 2) + def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser( - description="Vehicle Speed Estimation using Supervision Package" + description="Vehicle Speed Estimation using YOLO-NAS and Supervision" ) parser.add_argument( "--source_video_path", @@ -42,4 +76,77 @@ if __name__ == "__main__": args = parse_arguments() video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) - model = models.get(Models.YOLO_NAS_L, pretrained_weights="coco") \ No newline at end of file + model = models.get(Models.YOLO_NAS_L, pretrained_weights="coco") + + byte_track = sv.ByteTrack( + frame_rate=video_info.fps, + track_thresh=args.confidence_threshold) + + thickness = sv.calculate_dynamic_line_thickness( + resolution_wh=video_info.resolution_wh) + text_scale = sv.calculate_dynamic_text_scale( + resolution_wh=video_info.resolution_wh) + bounding_box_annotator = sv.BoundingBoxAnnotator( + thickness=thickness) + label_annotator = sv.LabelAnnotator( + text_scale=text_scale, + text_thickness=thickness, + text_position=sv.Position.BOTTOM_CENTER) + trace_annotator = sv.TraceAnnotator( + thickness=thickness, + trace_length=video_info.fps * 2, + position=sv.Position.BOTTOM_CENTER) + + frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) + + polygon_zone = sv.PolygonZone( + polygon=SOURCE, + frame_resolution_wh=video_info.resolution_wh) + view_transformer = ViewTransformer(source=SOURCE, target=TARGET) + + coordinates = defaultdict(lambda: deque(maxlen=video_info.fps)) + + with sv.VideoSink(args.target_video_path, video_info) as sink: + for frame in frame_generator: + result = model.predict(frame)[0] + detections = sv.Detections.from_yolo_nas(result) + detections = detections[polygon_zone.trigger(detections)] + detections = detections.with_nms(threshold=args.iou_threshold) + detections = byte_track.update_with_detections(detections=detections) + + points = detections.get_anchors_coordinates( + anchor=sv.Position.BOTTOM_CENTER) + points = view_transformer.transform_points(points=points).astype(int) + + for tracker_id, [_, y] in zip(detections.tracker_id, points): + coordinates[tracker_id].append(y) + + labels = [] + for tracker_id in detections.tracker_id: + if len(coordinates[tracker_id]) < video_info.fps / 2: + labels.append(f"#{tracker_id}") + else: + coordinate_start = coordinates[tracker_id][-1] + coordinate_end = coordinates[tracker_id][0] + distance = abs(coordinate_start - coordinate_end) + time = len(coordinates[tracker_id]) / video_info.fps + speed = distance / time * 3.6 + labels.append(f"#{tracker_id} {int(speed)} km/h") + + annotated_frame = frame.copy() + annotated_frame = trace_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = bounding_box_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = label_annotator.annotate( + scene=annotated_frame, + detections=detections, + labels=labels) + + sink.write_frame(annotated_frame) + cv2.imshow("frame", annotated_frame) + if cv2.waitKey(1) & 0xFF == ord("q"): + break + cv2.destroyAllWindows() \ No newline at end of file From 69894c82afd248a015768a54d44f0f7358755547 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 13:01:08 +0100 Subject: [PATCH 11/18] initial version of `inference_example.py` script --- examples/speed_estimation/README.md | 18 ++ .../speed_estimation/inference_example.py | 172 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 examples/speed_estimation/inference_example.py diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index 4dea9e88..a982f9f8 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -36,6 +36,13 @@ supervision package for multiple tasks such as tracking, annotations, etc. ## 🛠️ script arguments +- `--roboflow_api_key` (optional): The API key for Roboflow services. If not provided + directly, the script tries to fetch it from the `ROBOFLOW_API_KEY` environment + variable. Follow [this guide](https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key) + to acquire your `API KEY`. +- `--model_id` (optional): Designates the Roboflow model ID to be used. The default + value is `"yolov8x-1280"`. + - `--source_weights_path`: Required. Specifies the path to the YOLO model's weights file, which is essential for the object detection process. This file contains the data that the model uses to identify objects in the video. @@ -62,6 +69,17 @@ supervision package for multiple tasks such as tracking, annotations, etc. --confidence_threshold 0.3 \ --iou_threshold 0.5 ``` + +- inference + + ```bash + python inference_example.py \ + --roboflow_api_key \ + --source_video_path data/vehicles.mp4 \ + --target_video_path data/vehicles-result.mp4 \ + --confidence_threshold 0.3 \ + --iou_threshold 0.5 + ``` - ultralytics diff --git a/examples/speed_estimation/inference_example.py b/examples/speed_estimation/inference_example.py new file mode 100644 index 00000000..28441ddb --- /dev/null +++ b/examples/speed_estimation/inference_example.py @@ -0,0 +1,172 @@ +import argparse +import os +from collections import defaultdict, deque + +import cv2 +import numpy as np +from inference.models.utils import get_roboflow_model + +import supervision as sv + +SOURCE = np.array([ + [1252, 787], + [2298, 803], + [5039, 2159], + [-550, 2159] +]) + +TARGET_WIDTH = 25 +TARGET_HEIGHT = 250 + +TARGET = np.array([ + [0, 0], + [TARGET_WIDTH - 1, 0], + [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], + [0, TARGET_HEIGHT - 1] +]) + + +class ViewTransformer: + + def __init__(self, source: np.ndarray, target: np.ndarray) -> None: + source = source.astype(np.float32) + target = target.astype(np.float32) + self.m = cv2.getPerspectiveTransform(source, target) + + def transform_points(self, points: np.ndarray) -> np.ndarray: + reshaped_points = points.reshape(-1, 1, 2).astype(np.float32) + transformed_points = cv2.perspectiveTransform(reshaped_points, self.m) + return transformed_points.reshape(-1, 2) + + +def parse_arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Vehicle Speed Estimation using Inference and Supervision" + ) + parser.add_argument( + "--model_id", + default="yolov8x-1280", + help="Roboflow model ID", + type=str, + ) + parser.add_argument( + "--roboflow_api_key", + default=None, + help="Roboflow API KEY", + type=str, + ) + parser.add_argument( + "--source_video_path", + required=True, + help="Path to the source video file", + type=str, + ) + parser.add_argument( + "--target_video_path", + required=True, + help="Path to the target video file (output)", + type=str, + ) + parser.add_argument( + "--confidence_threshold", + default=0.3, + help="Confidence threshold for the model", + type=float, + ) + parser.add_argument( + "--iou_threshold", + default=0.7, + help="IOU threshold for the model", + type=float + ) + + return parser.parse_args() + + +if __name__ == "__main__": + args = parse_arguments() + + api_key = args.roboflow_api_key + api_key = os.environ.get("ROBOFLOW_API_KEY", api_key) + if api_key is None: + raise ValueError( + "Roboflow API key is missing. Please provide it as an argument or set the " + "ROBOFLOW_API_KEY environment variable." + ) + args.roboflow_api_key = api_key + + video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) + model = get_roboflow_model(model_id=args.model_id, api_key=args.roboflow_api_key) + + byte_track = sv.ByteTrack( + frame_rate=video_info.fps, + track_thresh=args.confidence_threshold) + + thickness = sv.calculate_dynamic_line_thickness( + resolution_wh=video_info.resolution_wh) + text_scale = sv.calculate_dynamic_text_scale( + resolution_wh=video_info.resolution_wh) + bounding_box_annotator = sv.BoundingBoxAnnotator( + thickness=thickness) + label_annotator = sv.LabelAnnotator( + text_scale=text_scale, + text_thickness=thickness, + text_position=sv.Position.BOTTOM_CENTER) + trace_annotator = sv.TraceAnnotator( + thickness=thickness, + trace_length=video_info.fps * 2, + position=sv.Position.BOTTOM_CENTER) + + frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) + + polygon_zone = sv.PolygonZone( + polygon=SOURCE, + frame_resolution_wh=video_info.resolution_wh) + view_transformer = ViewTransformer(source=SOURCE, target=TARGET) + + coordinates = defaultdict(lambda: deque(maxlen=video_info.fps)) + + with sv.VideoSink(args.target_video_path, video_info) as sink: + for frame in frame_generator: + results = model.infer(frame)[0] + detections = sv.Detections.from_inference(results) + detections = detections[detections.confidence > args.confidence_threshold] + detections = detections[polygon_zone.trigger(detections)] + detections = detections.with_nms(threshold=args.iou_threshold) + detections = byte_track.update_with_detections(detections=detections) + + points = detections.get_anchors_coordinates(anchor=sv.Position.BOTTOM_CENTER) + points = view_transformer.transform_points(points=points).astype(int) + + for tracker_id, [_, y] in zip(detections.tracker_id, points): + coordinates[tracker_id].append(y) + + labels = [] + for tracker_id in detections.tracker_id: + if len(coordinates[tracker_id]) < video_info.fps / 2: + labels.append(f"#{tracker_id}") + else: + coordinate_start = coordinates[tracker_id][-1] + coordinate_end = coordinates[tracker_id][0] + distance = abs(coordinate_start - coordinate_end) + time = len(coordinates[tracker_id]) / video_info.fps + speed = distance / time * 3.6 + labels.append(f"#{tracker_id} {int(speed)} km/h") + + annotated_frame = frame.copy() + annotated_frame = trace_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = bounding_box_annotator.annotate( + scene=annotated_frame, + detections=detections) + annotated_frame = label_annotator.annotate( + scene=annotated_frame, + detections=detections, + labels=labels) + + sink.write_frame(annotated_frame) + cv2.imshow("frame", annotated_frame) + if cv2.waitKey(1) & 0xFF == ord("q"): + break + cv2.destroyAllWindows() From 4ae9131f0af901eac3d2ad2ee7aed374b85c1323 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:03:30 +0000 Subject: [PATCH 12/18] =?UTF-8?q?fix(pre=5Fcommit):=20=F0=9F=8E=A8=20auto?= =?UTF-8?q?=20format=20pre-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/speed_estimation/.gitignore | 2 +- examples/speed_estimation/README.md | 10 +-- .../speed_estimation/inference_example.py | 67 ++++++++--------- examples/speed_estimation/requirements.txt | 2 +- .../speed_estimation/ultralytics_example.py | 69 ++++++++---------- examples/speed_estimation/yolo_nas_example.py | 73 +++++++++---------- examples/traffic_analysis/.gitignore | 2 +- 7 files changed, 104 insertions(+), 121 deletions(-) diff --git a/examples/speed_estimation/.gitignore b/examples/speed_estimation/.gitignore index 27cca3bd..5b855697 100644 --- a/examples/speed_estimation/.gitignore +++ b/examples/speed_estimation/.gitignore @@ -1,2 +1,2 @@ data/ -venv*/ \ No newline at end of file +venv*/ diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index a982f9f8..0500ab0d 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -2,7 +2,7 @@ ## 👋 hello -This example performs speed estimation analysis using various object-detection models +This example performs speed estimation analysis using various object-detection models and ByteTrack - a simple yet effective online multi-object tracking method. It uses the supervision package for multiple tasks such as tracking, annotations, etc. @@ -27,13 +27,13 @@ supervision package for multiple tasks such as tracking, annotations, etc. ```bash pip install -r requirements.txt ``` - + - download `vehicles.mp4` file ```bash ./setup.sh ``` - + ## 🛠️ script arguments - `--roboflow_api_key` (optional): The API key for Roboflow services. If not provided @@ -69,7 +69,7 @@ supervision package for multiple tasks such as tracking, annotations, etc. --confidence_threshold 0.3 \ --iou_threshold 0.5 ``` - + - inference ```bash @@ -103,4 +103,4 @@ This demo integrates two main components, each with its own licensing: based on the Supervision library, which is licensed under the [MIT license](https://github.com/roboflow/supervision/blob/develop/LICENSE.md). This makes the Supervision part of the code fully open source and freely usable in your - projects. \ No newline at end of file + projects. diff --git a/examples/speed_estimation/inference_example.py b/examples/speed_estimation/inference_example.py index 28441ddb..d7762c5e 100644 --- a/examples/speed_estimation/inference_example.py +++ b/examples/speed_estimation/inference_example.py @@ -8,26 +8,22 @@ from inference.models.utils import get_roboflow_model import supervision as sv -SOURCE = np.array([ - [1252, 787], - [2298, 803], - [5039, 2159], - [-550, 2159] -]) +SOURCE = np.array([[1252, 787], [2298, 803], [5039, 2159], [-550, 2159]]) TARGET_WIDTH = 25 TARGET_HEIGHT = 250 -TARGET = np.array([ - [0, 0], - [TARGET_WIDTH - 1, 0], - [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], - [0, TARGET_HEIGHT - 1] -]) +TARGET = np.array( + [ + [0, 0], + [TARGET_WIDTH - 1, 0], + [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], + [0, TARGET_HEIGHT - 1], + ] +) class ViewTransformer: - def __init__(self, source: np.ndarray, target: np.ndarray) -> None: source = source.astype(np.float32) target = target.astype(np.float32) @@ -74,10 +70,7 @@ def parse_arguments() -> argparse.Namespace: type=float, ) parser.add_argument( - "--iou_threshold", - default=0.7, - help="IOU threshold for the model", - type=float + "--iou_threshold", default=0.7, help="IOU threshold for the model", type=float ) return parser.parse_args() @@ -99,29 +92,30 @@ if __name__ == "__main__": model = get_roboflow_model(model_id=args.model_id, api_key=args.roboflow_api_key) byte_track = sv.ByteTrack( - frame_rate=video_info.fps, - track_thresh=args.confidence_threshold) + frame_rate=video_info.fps, track_thresh=args.confidence_threshold + ) thickness = sv.calculate_dynamic_line_thickness( - resolution_wh=video_info.resolution_wh) - text_scale = sv.calculate_dynamic_text_scale( - resolution_wh=video_info.resolution_wh) - bounding_box_annotator = sv.BoundingBoxAnnotator( - thickness=thickness) + resolution_wh=video_info.resolution_wh + ) + text_scale = sv.calculate_dynamic_text_scale(resolution_wh=video_info.resolution_wh) + bounding_box_annotator = sv.BoundingBoxAnnotator(thickness=thickness) label_annotator = sv.LabelAnnotator( text_scale=text_scale, text_thickness=thickness, - text_position=sv.Position.BOTTOM_CENTER) + text_position=sv.Position.BOTTOM_CENTER, + ) trace_annotator = sv.TraceAnnotator( thickness=thickness, trace_length=video_info.fps * 2, - position=sv.Position.BOTTOM_CENTER) + position=sv.Position.BOTTOM_CENTER, + ) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) polygon_zone = sv.PolygonZone( - polygon=SOURCE, - frame_resolution_wh=video_info.resolution_wh) + polygon=SOURCE, frame_resolution_wh=video_info.resolution_wh + ) view_transformer = ViewTransformer(source=SOURCE, target=TARGET) coordinates = defaultdict(lambda: deque(maxlen=video_info.fps)) @@ -135,7 +129,9 @@ if __name__ == "__main__": detections = detections.with_nms(threshold=args.iou_threshold) detections = byte_track.update_with_detections(detections=detections) - points = detections.get_anchors_coordinates(anchor=sv.Position.BOTTOM_CENTER) + points = detections.get_anchors_coordinates( + anchor=sv.Position.BOTTOM_CENTER + ) points = view_transformer.transform_points(points=points).astype(int) for tracker_id, [_, y] in zip(detections.tracker_id, points): @@ -155,15 +151,14 @@ if __name__ == "__main__": annotated_frame = frame.copy() annotated_frame = trace_annotator.annotate( - scene=annotated_frame, - detections=detections) + scene=annotated_frame, detections=detections + ) annotated_frame = bounding_box_annotator.annotate( - scene=annotated_frame, - detections=detections) + scene=annotated_frame, detections=detections + ) annotated_frame = label_annotator.annotate( - scene=annotated_frame, - detections=detections, - labels=labels) + scene=annotated_frame, detections=detections, labels=labels + ) sink.write_frame(annotated_frame) cv2.imshow("frame", annotated_frame) diff --git a/examples/speed_estimation/requirements.txt b/examples/speed_estimation/requirements.txt index 7365d559..8a43a381 100644 --- a/examples/speed_estimation/requirements.txt +++ b/examples/speed_estimation/requirements.txt @@ -3,4 +3,4 @@ supervision ultralytics super-gradients -inference \ No newline at end of file +inference diff --git a/examples/speed_estimation/ultralytics_example.py b/examples/speed_estimation/ultralytics_example.py index b397a527..6bb2b2f6 100644 --- a/examples/speed_estimation/ultralytics_example.py +++ b/examples/speed_estimation/ultralytics_example.py @@ -7,26 +7,22 @@ from ultralytics import YOLO import supervision as sv -SOURCE = np.array([ - [1252, 787], - [2298, 803], - [5039, 2159], - [-550, 2159] -]) +SOURCE = np.array([[1252, 787], [2298, 803], [5039, 2159], [-550, 2159]]) TARGET_WIDTH = 25 TARGET_HEIGHT = 250 -TARGET = np.array([ - [0, 0], - [TARGET_WIDTH - 1, 0], - [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], - [0, TARGET_HEIGHT - 1] -]) +TARGET = np.array( + [ + [0, 0], + [TARGET_WIDTH - 1, 0], + [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], + [0, TARGET_HEIGHT - 1], + ] +) class ViewTransformer: - def __init__(self, source: np.ndarray, target: np.ndarray) -> None: source = source.astype(np.float32) target = target.astype(np.float32) @@ -61,10 +57,7 @@ def parse_arguments() -> argparse.Namespace: type=float, ) parser.add_argument( - "--iou_threshold", - default=0.7, - help="IOU threshold for the model", - type=float + "--iou_threshold", default=0.7, help="IOU threshold for the model", type=float ) return parser.parse_args() @@ -74,32 +67,33 @@ if __name__ == "__main__": args = parse_arguments() video_info = sv.VideoInfo.from_video_path(video_path=args.source_video_path) - model = YOLO('yolov8x.pt') + model = YOLO("yolov8x.pt") byte_track = sv.ByteTrack( - frame_rate=video_info.fps, - track_thresh=args.confidence_threshold) + frame_rate=video_info.fps, track_thresh=args.confidence_threshold + ) thickness = sv.calculate_dynamic_line_thickness( - resolution_wh=video_info.resolution_wh) - text_scale = sv.calculate_dynamic_text_scale( - resolution_wh=video_info.resolution_wh) - bounding_box_annotator = sv.BoundingBoxAnnotator( - thickness=thickness) + resolution_wh=video_info.resolution_wh + ) + text_scale = sv.calculate_dynamic_text_scale(resolution_wh=video_info.resolution_wh) + bounding_box_annotator = sv.BoundingBoxAnnotator(thickness=thickness) label_annotator = sv.LabelAnnotator( text_scale=text_scale, text_thickness=thickness, - text_position=sv.Position.BOTTOM_CENTER) + text_position=sv.Position.BOTTOM_CENTER, + ) trace_annotator = sv.TraceAnnotator( thickness=thickness, trace_length=video_info.fps * 2, - position=sv.Position.BOTTOM_CENTER) + position=sv.Position.BOTTOM_CENTER, + ) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) polygon_zone = sv.PolygonZone( - polygon=SOURCE, - frame_resolution_wh=video_info.resolution_wh) + polygon=SOURCE, frame_resolution_wh=video_info.resolution_wh + ) view_transformer = ViewTransformer(source=SOURCE, target=TARGET) coordinates = defaultdict(lambda: deque(maxlen=video_info.fps)) @@ -113,7 +107,9 @@ if __name__ == "__main__": detections = detections.with_nms(threshold=args.iou_threshold) detections = byte_track.update_with_detections(detections=detections) - points = detections.get_anchors_coordinates(anchor=sv.Position.BOTTOM_CENTER) + points = detections.get_anchors_coordinates( + anchor=sv.Position.BOTTOM_CENTER + ) points = view_transformer.transform_points(points=points).astype(int) for tracker_id, [_, y] in zip(detections.tracker_id, points): @@ -133,15 +129,14 @@ if __name__ == "__main__": annotated_frame = frame.copy() annotated_frame = trace_annotator.annotate( - scene=annotated_frame, - detections=detections) + scene=annotated_frame, detections=detections + ) annotated_frame = bounding_box_annotator.annotate( - scene=annotated_frame, - detections=detections) + scene=annotated_frame, detections=detections + ) annotated_frame = label_annotator.annotate( - scene=annotated_frame, - detections=detections, - labels=labels) + scene=annotated_frame, detections=detections, labels=labels + ) sink.write_frame(annotated_frame) cv2.imshow("frame", annotated_frame) diff --git a/examples/speed_estimation/yolo_nas_example.py b/examples/speed_estimation/yolo_nas_example.py index 9862dfbf..5847d759 100644 --- a/examples/speed_estimation/yolo_nas_example.py +++ b/examples/speed_estimation/yolo_nas_example.py @@ -1,34 +1,29 @@ import argparse from collections import defaultdict, deque -from super_gradients.training import models -from super_gradients.common.object_names import Models - import cv2 import numpy as np +from super_gradients.common.object_names import Models +from super_gradients.training import models import supervision as sv -SOURCE = np.array([ - [1252, 787], - [2298, 803], - [5039, 2159], - [-550, 2159] -]) +SOURCE = np.array([[1252, 787], [2298, 803], [5039, 2159], [-550, 2159]]) TARGET_WIDTH = 25 TARGET_HEIGHT = 250 -TARGET = np.array([ - [0, 0], - [TARGET_WIDTH - 1, 0], - [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], - [0, TARGET_HEIGHT - 1] -]) +TARGET = np.array( + [ + [0, 0], + [TARGET_WIDTH - 1, 0], + [TARGET_WIDTH - 1, TARGET_HEIGHT - 1], + [0, TARGET_HEIGHT - 1], + ] +) class ViewTransformer: - def __init__(self, source: np.ndarray, target: np.ndarray) -> None: source = source.astype(np.float32) target = target.astype(np.float32) @@ -63,10 +58,7 @@ def parse_arguments() -> argparse.Namespace: type=float, ) parser.add_argument( - "--iou_threshold", - default=0.7, - help="IOU threshold for the model", - type=float + "--iou_threshold", default=0.7, help="IOU threshold for the model", type=float ) return parser.parse_args() @@ -79,29 +71,30 @@ if __name__ == "__main__": model = models.get(Models.YOLO_NAS_L, pretrained_weights="coco") byte_track = sv.ByteTrack( - frame_rate=video_info.fps, - track_thresh=args.confidence_threshold) + frame_rate=video_info.fps, track_thresh=args.confidence_threshold + ) thickness = sv.calculate_dynamic_line_thickness( - resolution_wh=video_info.resolution_wh) - text_scale = sv.calculate_dynamic_text_scale( - resolution_wh=video_info.resolution_wh) - bounding_box_annotator = sv.BoundingBoxAnnotator( - thickness=thickness) + resolution_wh=video_info.resolution_wh + ) + text_scale = sv.calculate_dynamic_text_scale(resolution_wh=video_info.resolution_wh) + bounding_box_annotator = sv.BoundingBoxAnnotator(thickness=thickness) label_annotator = sv.LabelAnnotator( text_scale=text_scale, text_thickness=thickness, - text_position=sv.Position.BOTTOM_CENTER) + text_position=sv.Position.BOTTOM_CENTER, + ) trace_annotator = sv.TraceAnnotator( thickness=thickness, trace_length=video_info.fps * 2, - position=sv.Position.BOTTOM_CENTER) + position=sv.Position.BOTTOM_CENTER, + ) frame_generator = sv.get_video_frames_generator(source_path=args.source_video_path) polygon_zone = sv.PolygonZone( - polygon=SOURCE, - frame_resolution_wh=video_info.resolution_wh) + polygon=SOURCE, frame_resolution_wh=video_info.resolution_wh + ) view_transformer = ViewTransformer(source=SOURCE, target=TARGET) coordinates = defaultdict(lambda: deque(maxlen=video_info.fps)) @@ -115,7 +108,8 @@ if __name__ == "__main__": detections = byte_track.update_with_detections(detections=detections) points = detections.get_anchors_coordinates( - anchor=sv.Position.BOTTOM_CENTER) + anchor=sv.Position.BOTTOM_CENTER + ) points = view_transformer.transform_points(points=points).astype(int) for tracker_id, [_, y] in zip(detections.tracker_id, points): @@ -135,18 +129,17 @@ if __name__ == "__main__": annotated_frame = frame.copy() annotated_frame = trace_annotator.annotate( - scene=annotated_frame, - detections=detections) + scene=annotated_frame, detections=detections + ) annotated_frame = bounding_box_annotator.annotate( - scene=annotated_frame, - detections=detections) + scene=annotated_frame, detections=detections + ) annotated_frame = label_annotator.annotate( - scene=annotated_frame, - detections=detections, - labels=labels) + scene=annotated_frame, detections=detections, labels=labels + ) sink.write_frame(annotated_frame) cv2.imshow("frame", annotated_frame) if cv2.waitKey(1) & 0xFF == ord("q"): break - cv2.destroyAllWindows() \ No newline at end of file + cv2.destroyAllWindows() diff --git a/examples/traffic_analysis/.gitignore b/examples/traffic_analysis/.gitignore index 9435cafc..cea2fc37 100644 --- a/examples/traffic_analysis/.gitignore +++ b/examples/traffic_analysis/.gitignore @@ -1,2 +1,2 @@ data/ -venv/ \ No newline at end of file +venv/ From 8bab49157def36290a10f4b2586e4db512ce38f3 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 13:52:09 +0100 Subject: [PATCH 13/18] working version of `inference_example.py` --- examples/speed_estimation/README.md | 5 ++++- examples/speed_estimation/inference_example.py | 2 +- examples/speed_estimation/requirements.txt | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index a982f9f8..4ce85df3 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -17,8 +17,11 @@ supervision package for multiple tasks such as tracking, annotations, etc. - setup python environment and activate it [optional] + > [!NOTE] + > YOLO-NAS is compatible with Python versions up to and including Python 3.10. + ```bash - python3 -m venv venv + python3.10 -m venv venv source venv/bin/activate ``` diff --git a/examples/speed_estimation/inference_example.py b/examples/speed_estimation/inference_example.py index 28441ddb..ad140df1 100644 --- a/examples/speed_estimation/inference_example.py +++ b/examples/speed_estimation/inference_example.py @@ -45,7 +45,7 @@ def parse_arguments() -> argparse.Namespace: ) parser.add_argument( "--model_id", - default="yolov8x-1280", + default="yolov8x-640", help="Roboflow model ID", type=str, ) diff --git a/examples/speed_estimation/requirements.txt b/examples/speed_estimation/requirements.txt index 7365d559..928656b6 100644 --- a/examples/speed_estimation/requirements.txt +++ b/examples/speed_estimation/requirements.txt @@ -1,5 +1,5 @@ gdown -supervision +supervision==0.18.0rc1 ultralytics super-gradients From d596d10b3ffd4018f77dde38cfbfc357c0f0e71f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:52:33 +0000 Subject: [PATCH 14/18] =?UTF-8?q?fix(pre=5Fcommit):=20=F0=9F=8E=A8=20auto?= =?UTF-8?q?=20format=20pre-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/speed_estimation/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index 9b35cdb1..3c73e754 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -17,7 +17,7 @@ supervision package for multiple tasks such as tracking, annotations, etc. - setup python environment and activate it [optional] - > [!NOTE] + > [!NOTE] > YOLO-NAS is compatible with Python versions up to and including Python 3.10. ```bash From f0142344aed1825050e4f411d0d4660f8d8e6163 Mon Sep 17 00:00:00 2001 From: SkalskiP Date: Mon, 8 Jan 2024 13:57:17 +0100 Subject: [PATCH 15/18] update note in speed estimation emo `README.md` --- examples/speed_estimation/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index 9b35cdb1..68bc1440 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -8,6 +8,9 @@ supervision package for multiple tasks such as tracking, annotations, etc. ## 💻 install +> [!NOTE] +> YOLO-NAS is compatible with Python versions up to and including Python 3.10. + - clone repository and navigate to example directory ```bash @@ -17,9 +20,6 @@ supervision package for multiple tasks such as tracking, annotations, etc. - setup python environment and activate it [optional] - > [!NOTE] - > YOLO-NAS is compatible with Python versions up to and including Python 3.10. - ```bash python3.10 -m venv venv source venv/bin/activate From be5748c08682e5d6e92b3026770b2b9d7591444b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:57:52 +0000 Subject: [PATCH 16/18] =?UTF-8?q?fix(pre=5Fcommit):=20=F0=9F=8E=A8=20auto?= =?UTF-8?q?=20format=20pre-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/speed_estimation/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index 68bc1440..c6ddbc1b 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -8,7 +8,7 @@ supervision package for multiple tasks such as tracking, annotations, etc. ## 💻 install -> [!NOTE] +> [!NOTE] > YOLO-NAS is compatible with Python versions up to and including Python 3.10. - clone repository and navigate to example directory From a72ad4262866db53daa6c830ab562c8a3b024561 Mon Sep 17 00:00:00 2001 From: Piotr Skalski Date: Mon, 8 Jan 2024 14:02:27 +0100 Subject: [PATCH 17/18] Update README.md --- examples/speed_estimation/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index c6ddbc1b..780368e8 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -6,6 +6,8 @@ This example performs speed estimation analysis using various object-detection m and ByteTrack - a simple yet effective online multi-object tracking method. It uses the supervision package for multiple tasks such as tracking, annotations, etc. +https://github.com/roboflow/supervision/assets/26109316/0542fd3c-bb5f-475e-b96c-793560abeb18 + ## 💻 install > [!NOTE] From a337ee591ade3a3e676fba5d51f7adc29b4a7da5 Mon Sep 17 00:00:00 2001 From: Onuralp SEZER Date: Tue, 9 Jan 2024 05:15:28 +0300 Subject: [PATCH 18/18] =?UTF-8?q?feat:=20=E2=9C=A8=20supervison=20download?= =?UTF-8?q?er=20added?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Onuralp SEZER --- examples/speed_estimation/README.md | 2 +- examples/speed_estimation/requirements.txt | 4 ++-- examples/speed_estimation/setup.sh | 14 -------------- examples/speed_estimation/video_downloader.py | 8 ++++++++ 4 files changed, 11 insertions(+), 17 deletions(-) delete mode 100644 examples/speed_estimation/setup.sh create mode 100644 examples/speed_estimation/video_downloader.py diff --git a/examples/speed_estimation/README.md b/examples/speed_estimation/README.md index 780368e8..35685938 100644 --- a/examples/speed_estimation/README.md +++ b/examples/speed_estimation/README.md @@ -36,7 +36,7 @@ https://github.com/roboflow/supervision/assets/26109316/0542fd3c-bb5f-475e-b96c- - download `vehicles.mp4` file ```bash - ./setup.sh + python3.10 video_downloader.py ``` ## 🛠️ script arguments diff --git a/examples/speed_estimation/requirements.txt b/examples/speed_estimation/requirements.txt index 3d57d9d6..63f20432 100644 --- a/examples/speed_estimation/requirements.txt +++ b/examples/speed_estimation/requirements.txt @@ -1,6 +1,6 @@ -gdown supervision==0.18.0rc1 - +tqdm +requests ultralytics super-gradients inference diff --git a/examples/speed_estimation/setup.sh b/examples/speed_estimation/setup.sh deleted file mode 100644 index 6e9e82bb..00000000 --- a/examples/speed_estimation/setup.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -# Get the directory where the script is located -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Check if 'data' directory does not exist and then create it -if [[ ! -e $DIR/data ]]; then - mkdir "$DIR/data" -else - echo "'data' directory already exists." -fi - -# Download the vehicles.mp4 file from Google Drive -gdown -O "$DIR/data/vehicles.mp4" "https://drive.google.com/uc?id=1pz68D1Gsx80MoPg-_q-IbEdESEmyVLm-" diff --git a/examples/speed_estimation/video_downloader.py b/examples/speed_estimation/video_downloader.py new file mode 100644 index 00000000..4272120b --- /dev/null +++ b/examples/speed_estimation/video_downloader.py @@ -0,0 +1,8 @@ +import os + +from supervision.assets import VideoAssets, download_assets + +if not os.path.exists("data"): + os.makedirs("data") +os.chdir("data") +download_assets(VideoAssets.VEHICLES)