| import gradio as gr |
| import cv2 |
| import pandas as pd |
| import numpy as np |
| from ultralytics import YOLO |
| import tempfile |
| import time |
| import os |
|
|
| |
| os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics" |
|
|
| |
| model = YOLO("yolov8n.pt") |
|
|
| detections_log = [] |
|
|
| def process_video(video, conf_threshold): |
| global detections_log |
| detections_log = [] |
|
|
| if video is None: |
| return None, None, "Upload video first", pd.DataFrame() |
|
|
| try: |
| video_path = video["name"] if isinstance(video, dict) else str(video) |
|
|
| if not os.path.exists(video_path): |
| return None, None, "File not found", pd.DataFrame() |
|
|
| cap = cv2.VideoCapture(video_path) |
|
|
| if not cap.isOpened(): |
| return None, None, "Cannot open video", pd.DataFrame() |
|
|
| |
| fps = cap.get(cv2.CAP_PROP_FPS) |
| if fps <= 0 or fps > 60: |
| fps = 20 |
|
|
| output_fps = max(10, fps * 0.6) |
|
|
| width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) or 640 |
| height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) or 480 |
|
|
| output_path = os.path.join(tempfile.gettempdir(), f"out_{int(time.time())}.mp4") |
|
|
| fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
| out = cv2.VideoWriter(output_path, fourcc, output_fps, (width, height)) |
|
|
| if not out.isOpened(): |
| return None, None, "VideoWriter failed", pd.DataFrame() |
|
|
| pothole_count = 0 |
| frame_count = 0 |
|
|
| |
| frame_skip = 2 |
| frame_id = 0 |
|
|
| while cap.isOpened(): |
| ret, frame = cap.read() |
| if not ret: |
| break |
|
|
| frame_id += 1 |
|
|
| if frame_id % frame_skip != 0: |
| continue |
|
|
| frame = cv2.resize(frame, (width, height)) |
|
|
| |
| frame = cv2.GaussianBlur(frame, (3, 3), 0) |
|
|
| results = model(frame)[0] |
|
|
| for box in results.boxes: |
| conf = float(box.conf[0]) |
|
|
| |
| if conf < max(conf_threshold, 0.4): |
| continue |
|
|
| x1, y1, x2, y2 = map(int, box.xyxy[0]) |
|
|
| |
| cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 4) |
|
|
| label = f"Pothole {conf:.2f}" |
|
|
| |
| (w, h), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2) |
| cv2.rectangle(frame, (x1, y1 - h - 10), (x1 + w, y1), (0, 0, 255), -1) |
|
|
| |
| cv2.putText(frame, label, |
| (x1, y1 - 5), |
| cv2.FONT_HERSHEY_SIMPLEX, |
| 0.6, |
| (255, 255, 255), |
| 2) |
|
|
| pothole_count += 1 |
|
|
| detections_log.append({ |
| "Frame": frame_count, |
| "Confidence": round(conf, 2), |
| "Time": time.strftime("%H:%M:%S") |
| }) |
|
|
| out.write(frame) |
| frame_count += 1 |
|
|
| cap.release() |
| out.release() |
| time.sleep(1) |
|
|
| if not os.path.exists(output_path) or os.path.getsize(output_path) < 1000: |
| return None, None, "Output video failed", pd.DataFrame() |
|
|
| df = pd.DataFrame(detections_log) |
|
|
| msg = f"Detections: {pothole_count} | Frames: {frame_count}" |
|
|
| return video_path, output_path, msg, df |
|
|
| except Exception as e: |
| return None, None, str(e), pd.DataFrame() |
|
|
|
|
| |
| with gr.Blocks() as demo: |
|
|
| gr.Markdown("# π§ Smart Pothole Detection (Improved)") |
|
|
| with gr.Row(): |
|
|
| |
| with gr.Column(scale=1): |
| video_input = gr.Video(label="Upload Video") |
| conf = gr.Slider(0, 1, value=0.4, step=0.05, label="Confidence") |
| btn = gr.Button("Run Detection") |
|
|
| |
| with gr.Column(scale=3): |
| with gr.Row(): |
| before = gr.Video(label="Original") |
| after = gr.Video(label="Detected") |
|
|
| result = gr.Textbox(label="Summary") |
| table = gr.Dataframe(label="Detection Log") |
|
|
| btn.click( |
| process_video, |
| inputs=[video_input, conf], |
| outputs=[before, after, result, table] |
| ) |
|
|
|
|
| |
| if __name__ == "__main__": |
| demo.launch() |
|
|