Spaces:
Sleeping
Sleeping
File size: 6,055 Bytes
dfd3880 5897aa9 1e2f3c9 dfd3880 064f359 5897aa9 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 5897aa9 dfd3880 d26187e 7198c83 1e2f3c9 5897aa9 1e2f3c9 5808aa0 623838a 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 5897aa9 1e2f3c9 d26187e dfd3880 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 5897aa9 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 5897aa9 1e2f3c9 dfd3880 1e2f3c9 5897aa9 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 dfd3880 1e2f3c9 5897aa9 1e2f3c9 5897aa9 1e2f3c9 5897aa9 1e2f3c9 5c15472 dfd3880 1e2f3c9 7198c83 dfd3880 5897aa9 7198c83 dfd3880 1e2f3c9 7198c83 dfd3880 7198c83 d26187e 1e2f3c9 d26187e 1e2f3c9 dfd3880 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | import os
import tempfile
import cv2
import numpy as np
import gradio as gr
import supervision as sv
from ultralytics import YOLO
model = YOLO("yolo11n.pt")
CLASS_NAMES_DICT = model.model.names
SELECTED_CLASS_NAMES = ['car', 'bus', 'truck', 'motorcycle']
SELECTED_CLASS_IDS = [
{value: key for key, value in CLASS_NAMES_DICT.items()}[name]
for name in SELECTED_CLASS_NAMES
]
box_annotator = sv.BoxAnnotator(thickness=4)
label_annotator = sv.LabelAnnotator(text_thickness=2, text_scale=1.5, text_color=sv.Color.BLACK)
trace_annotator = sv.TraceAnnotator(thickness=4, trace_length=50)
line_zone_annotator = sv.LineZoneAnnotator(
thickness=4, text_thickness=2, text_scale=2,
display_in_count=False, display_out_count=False
)
def process_video(video_path, orientation="Ngang"):
"""Xử lý video: nhận dạng phương tiện và trả về video đã annotate."""
if video_path is None:
return None
if isinstance(video_path, dict):
video_path = video_path.get("path", video_path)
video_info = sv.VideoInfo.from_video_path(video_path)
w, h = video_info.width, video_info.height
ori = str(orientation).strip().lower()
is_horizontal = ori.startswith("n") or ori.startswith("h")
if is_horizontal:
line_pos = int(h * 0.5)
line_start = sv.Point(int(w * 0.005), line_pos)
line_end = sv.Point(int(w * 0.995), line_pos)
else:
line_pos = int(w * 0.5)
line_start = sv.Point(line_pos, int(h * 0.005))
line_end = sv.Point(line_pos, int(h * 0.995))
line_zone = sv.LineZone(start=line_start, end=line_end)
byte_tracker = sv.ByteTrack(
track_activation_threshold=0.25,
lost_track_buffer=30,
minimum_matching_threshold=0.8,
frame_rate=video_info.fps or 30,
minimum_consecutive_frames=3
)
byte_tracker.reset()
previous_positions = {}
class_counts = {name: 0 for name in SELECTED_CLASS_NAMES}
crossed_ids = set()
def callback(frame: np.ndarray, index: int) -> np.ndarray:
nonlocal previous_positions, class_counts, crossed_ids
results = model(frame, verbose=False)[0]
detections = sv.Detections.from_ultralytics(results)
detections = detections[np.isin(detections.class_id, SELECTED_CLASS_IDS)]
detections = byte_tracker.update_with_detections(detections)
if detections.tracker_id is not None:
xyxy = detections.xyxy
for i in range(len(detections)):
tid = int(detections.tracker_id[i])
cls_id = int(detections.class_id[i])
cls_name = CLASS_NAMES_DICT[cls_id]
cx = (xyxy[i, 0] + xyxy[i, 2]) / 2
cy = (xyxy[i, 1] + xyxy[i, 3]) / 2
curr_coord = cy if is_horizontal else cx
if tid in previous_positions:
prev_coord = previous_positions[tid]
if prev_coord < line_pos and curr_coord > line_pos and (tid, 'pos') not in crossed_ids:
crossed_ids.add((tid, 'pos'))
class_counts[cls_name] = class_counts.get(cls_name, 0) + 1
elif prev_coord > line_pos and curr_coord < line_pos and (tid, 'neg') not in crossed_ids:
crossed_ids.add((tid, 'neg'))
class_counts[cls_name] = class_counts.get(cls_name, 0) + 1
previous_positions[tid] = curr_coord
labels = [
f"#{tid} {CLASS_NAMES_DICT[cid]} {conf:0.2f}"
for conf, cid, tid in zip(
detections.confidence, detections.class_id, detections.tracker_id
)
]
annotator_frame = frame.copy()
annotator_frame = trace_annotator.annotate(scene=annotator_frame, detections=detections)
annotator_frame = box_annotator.annotate(scene=annotator_frame, detections=detections)
annotator_frame = label_annotator.annotate(scene=annotator_frame, detections=detections, labels=labels)
line_zone.trigger(detections)
annotator_frame = line_zone_annotator.annotate(annotator_frame, line_counter=line_zone)
fh, fw, _ = annotator_frame.shape
box_w, box_h = 280, 50 + len(SELECTED_CLASS_NAMES) * 28
x0, y0 = fw - box_w - 20, 20
overlay = annotator_frame.copy()
cv2.rectangle(overlay, (x0, y0), (x0 + box_w, y0 + box_h), (0, 0, 0), -1)
annotator_frame = cv2.addWeighted(overlay, 0.6, annotator_frame, 0.4, 0)
total = sum(class_counts.values())
cv2.putText(annotator_frame, f'Total: {total}', (x0 + 10, y0 + 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
for i, cls_name in enumerate(SELECTED_CLASS_NAMES):
cnt = class_counts.get(cls_name, 0)
cv2.putText(annotator_frame, f'{cls_name.capitalize()}: {cnt}',
(x0 + 10, y0 + 60 + i * 28),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
return annotator_frame
output_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
sv.process_video(
source_path=video_path,
target_path=output_path,
callback=callback
)
return output_path
with gr.Blocks(title="Object Detection", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🚗 Nhận dạng phương tiện (YOLOv8 + ByteTrack)")
gr.Markdown("Tải lên video, hệ thống sẽ nhận dạng phương tiện trong video.")
with gr.Row():
video_input = gr.Video(label="Video đầu vào")
video_output = gr.Video(label="Video đã xử lý")
orientation_input = gr.Radio(
choices=["Ngang", "Dọc"],
value="Ngang",
label="Vị trí line"
)
btn = gr.Button("▶️ Xử lý video")
btn.click(fn=process_video, inputs=[video_input, orientation_input], outputs=video_output)
gr.Markdown("""
### Author: Trần Hải Nam - 223332840
""")
if __name__ == "__main__":
demo.launch()
|