Spaces:
Sleeping
Sleeping
Pedro Henrique Conrado
commited on
Commit
·
c2d34b4
1
Parent(s):
6266ca4
first commit
Browse files- .gitignore.txt +7 -0
- app.py +121 -0
- requirements.txt +44 -0
.gitignore.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
flagged/
|
2 |
+
*.mp4
|
3 |
+
*.jpg
|
4 |
+
*.pt
|
5 |
+
*.png
|
6 |
+
*.mkv
|
7 |
+
gradio_cached_examples/
|
app.py
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from ultralytics import YOLO
|
2 |
+
from dataclasses import dataclass
|
3 |
+
from yolox.tracker.byte_tracker import BYTETracker, STrack
|
4 |
+
from onemetric.cv.utils.iou import box_iou_batch
|
5 |
+
from dataclasses import dataclass
|
6 |
+
from supervision import Point
|
7 |
+
from supervision import Detections, BoxAnnotator
|
8 |
+
from supervision import draw_text
|
9 |
+
from supervision import Color
|
10 |
+
from supervision import VideoInfo
|
11 |
+
from supervision import get_video_frames_generator
|
12 |
+
from supervision import VideoSink
|
13 |
+
from typing import List
|
14 |
+
import numpy as np
|
15 |
+
import gradio as gr
|
16 |
+
from tqdm import tqdm
|
17 |
+
|
18 |
+
MODEL = "./best.pt"
|
19 |
+
|
20 |
+
SOURCE_VIDEO_PATH = "./examples"
|
21 |
+
|
22 |
+
TARGET_VIDEO_PATH = "test.mp4"
|
23 |
+
|
24 |
+
CLASS_ID = [0,1,2,3]
|
25 |
+
|
26 |
+
model = YOLO(MODEL)
|
27 |
+
model.fuse()
|
28 |
+
|
29 |
+
classes = CLASS_ID
|
30 |
+
|
31 |
+
@dataclass(frozen=True)
|
32 |
+
class BYTETrackerArgs:
|
33 |
+
track_thresh: float = 0.25
|
34 |
+
track_buffer: int = 30
|
35 |
+
match_thresh: float = 0.8
|
36 |
+
aspect_ratio_thresh: float = 3.0
|
37 |
+
min_box_area: float = 1.0
|
38 |
+
mot20: bool = False
|
39 |
+
|
40 |
+
|
41 |
+
# converts Detections into format that can be consumed by match_detections_with_tracks function
|
42 |
+
def detections2boxes(detections : Detections) -> np.ndarray:
|
43 |
+
return np.hstack((
|
44 |
+
detections.xyxy,
|
45 |
+
detections.confidence[:, np.newaxis]
|
46 |
+
))
|
47 |
+
|
48 |
+
|
49 |
+
# converts List[STrack] into format that can be consumed by match_detections_with_tracks function
|
50 |
+
def tracks2boxes(tracks: List[STrack]) -> np.ndarray:
|
51 |
+
return np.array([
|
52 |
+
track.tlbr
|
53 |
+
for track
|
54 |
+
in tracks
|
55 |
+
], dtype=float)
|
56 |
+
|
57 |
+
|
58 |
+
# matches our bounding boxes with predictions
|
59 |
+
def match_detections_with_tracks(
|
60 |
+
detections: Detections,
|
61 |
+
tracks: List[STrack],
|
62 |
+
) -> Detections:
|
63 |
+
if not np.any(detections.xyxy) or len(tracks) == 0:
|
64 |
+
return np.empty((0,))
|
65 |
+
|
66 |
+
tracks_boxes = tracks2boxes(tracks=tracks)
|
67 |
+
iou = box_iou_batch(tracks_boxes, detections.xyxy)
|
68 |
+
track2detection = np.argmax(iou, axis=1)
|
69 |
+
|
70 |
+
tracker_ids = [None] * len(detections)
|
71 |
+
|
72 |
+
for tracker_index, detection_index in enumerate(track2detection):
|
73 |
+
if iou[tracker_index, detection_index] != 0:
|
74 |
+
tracker_ids[detection_index] = tracks[tracker_index].track_id
|
75 |
+
|
76 |
+
return tracker_ids
|
77 |
+
|
78 |
+
def ObjectDetection(video_path):
|
79 |
+
byte_tracker = BYTETracker(BYTETrackerArgs())
|
80 |
+
video_info = VideoInfo.from_video_path(video_path)
|
81 |
+
generator = get_video_frames_generator(video_path)
|
82 |
+
box_annotator = BoxAnnotator(thickness=5, text_thickness=5, text_scale=1)
|
83 |
+
|
84 |
+
with VideoSink(TARGET_VIDEO_PATH, video_info) as sink:
|
85 |
+
# loop over video frames
|
86 |
+
for frame in tqdm(generator, total=video_info.total_frames):
|
87 |
+
results = model(frame)
|
88 |
+
detections = Detections(
|
89 |
+
xyxy=results[0].boxes.xyxy.cpu().numpy(),
|
90 |
+
confidence=results[0].boxes.conf.cpu().numpy(),
|
91 |
+
class_id=results[0].boxes.cls.cpu().numpy().astype(int)
|
92 |
+
)
|
93 |
+
# filtering out detections with unwanted classes
|
94 |
+
detections = detections[np.isin(detections.class_id, [0,1,2,3])]
|
95 |
+
# tracking detections
|
96 |
+
tracks = byte_tracker.update(
|
97 |
+
output_results=detections2boxes(detections = detections),
|
98 |
+
img_info=frame.shape,
|
99 |
+
img_size=frame.shape
|
100 |
+
)
|
101 |
+
tracker_id = match_detections_with_tracks(detections=detections, tracks=tracks)
|
102 |
+
detections.tracker_id = np.array(tracker_id)
|
103 |
+
# filtering out detections without trackers
|
104 |
+
detections = detections[np.not_equal(detections.tracker_id, None)]
|
105 |
+
# format custom labels
|
106 |
+
labels = [
|
107 |
+
f"#{tracker_id} {classes[class_id]} {confidence:0.2f}"
|
108 |
+
for _, _, confidence, class_id, tracker_id
|
109 |
+
in detections
|
110 |
+
]
|
111 |
+
t = np.unique(detections.class_id, return_counts =True)
|
112 |
+
for x in zip(t[0], t[1]):
|
113 |
+
frame = draw_text(background_color=Color.white(), scene=frame, text=' '.join((str(classes[x[0]]), ':', str(x[1]))), text_anchor=Point(x=50, y=300 + (50 * x[0])), text_scale = 2, text_thickness = 4, )
|
114 |
+
# annotate and display frame
|
115 |
+
frame = box_annotator.annotate(scene=frame, detections=detections, labels=labels)
|
116 |
+
sink.write_frame(frame)
|
117 |
+
|
118 |
+
return TARGET_VIDEO_PATH
|
119 |
+
|
120 |
+
demo = gr.Interface(fn=ObjectDetection, inputs=gr.Video(), outputs=gr.Video(), examples=SOURCE_VIDEO_PATH, cache_examples=False)
|
121 |
+
demo.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Ultralytics requirements
|
2 |
+
# Usage: pip install -r requirements.txt
|
3 |
+
|
4 |
+
# Base ----------------------------------------
|
5 |
+
matplotlib>=3.2.2
|
6 |
+
opencv-python>=4.6.0
|
7 |
+
pillow>=7.1.2
|
8 |
+
pyyaml>=5.3.1
|
9 |
+
requests>=2.23.0
|
10 |
+
scipy>=1.4.1
|
11 |
+
torch>=1.7.0
|
12 |
+
torchvision>=0.8.1
|
13 |
+
tqdm>=4.64.0
|
14 |
+
|
15 |
+
# Logging -------------------------------------
|
16 |
+
# tensorboard>=2.13.0
|
17 |
+
# dvclive>=2.12.0
|
18 |
+
# clearml
|
19 |
+
# comet
|
20 |
+
|
21 |
+
# Plotting ------------------------------------
|
22 |
+
pandas>=1.1.4
|
23 |
+
seaborn>=0.11.0
|
24 |
+
|
25 |
+
# Export --------------------------------------
|
26 |
+
# coremltools>=6.0,<=6.2 # CoreML export
|
27 |
+
# onnx>=1.12.0 # ONNX export
|
28 |
+
# onnxsim>=0.4.1 # ONNX simplifier
|
29 |
+
# nvidia-pyindex # TensorRT export
|
30 |
+
# nvidia-tensorrt # TensorRT export
|
31 |
+
# scikit-learn==0.19.2 # CoreML quantization
|
32 |
+
# tensorflow>=2.4.1 # TF exports (-cpu, -aarch64, -macos)
|
33 |
+
# tflite-support
|
34 |
+
# tensorflowjs>=3.9.0 # TF.js export
|
35 |
+
# openvino-dev>=2023.0 # OpenVINO export
|
36 |
+
|
37 |
+
# Extras --------------------------------------
|
38 |
+
psutil # system utilization
|
39 |
+
py-cpuinfo # display CPU info
|
40 |
+
# thop>=0.1.1 # FLOPs computation
|
41 |
+
# ipython # interactive notebook
|
42 |
+
# albumentations>=1.0.3 # training augmentations
|
43 |
+
# pycocotools>=2.0.6 # COCO mAP
|
44 |
+
# roboflow
|