| """ |
| Vehicle Speed Estimation and Counting - Gradio Interface |
| ========================================================= |
| |
| A real-time vehicle detection, tracking, counting, and speed estimation system |
| using YOLO object detection and perspective transformation techniques. |
| |
| Authors: |
| - Abhay Gupta (0205CC221005) |
| - Aditi Lakhera (0205CC221011) |
| - Balraj Patel (0205CC221049) |
| - Bhumika Patel (0205CC221050) |
| |
| This application provides an interactive web interface for analyzing traffic videos |
| and estimating vehicle speeds using computer vision techniques. |
| """ |
|
|
| import os |
| import sys |
| import tempfile |
| import logging |
| from pathlib import Path |
| from typing import Optional, Tuple |
|
|
| import gradio as gr |
| import cv2 |
| import numpy as np |
|
|
| |
| logging.basicConfig( |
| level=logging.INFO, |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' |
| ) |
| logger = logging.getLogger(__name__) |
|
|
| |
| try: |
| import spaces |
| ZEROGPU_AVAILABLE = True |
| logger.info("β
ZeroGPU support enabled - GPU acceleration available") |
| except ImportError: |
| ZEROGPU_AVAILABLE = False |
| logger.info("βΉοΈ ZeroGPU not available - will use CPU (slower but functional)") |
| |
| class spaces: |
| @staticmethod |
| def GPU(func): |
| """Dummy decorator when ZeroGPU is not available""" |
| return func |
|
|
| |
| try: |
| from main import process_video |
| from config import VehicleDetectionConfig |
| except ImportError as e: |
| logger.error(f"Failed to import required modules: {e}") |
| raise |
|
|
|
|
| def validate_video_file(video_path: str) -> Tuple[bool, str]: |
| """ |
| Validate uploaded video file. |
| |
| Args: |
| video_path: Path to video file |
| |
| Returns: |
| Tuple of (is_valid, error_message) |
| """ |
| if not video_path: |
| return False, "No video file provided" |
| |
| if not os.path.exists(video_path): |
| return False, f"Video file not found: {video_path}" |
| |
| |
| file_size_mb = os.path.getsize(video_path) / (1024 * 1024) |
| if file_size_mb > 100: |
| return False, f"Video file too large ({file_size_mb:.1f}MB). Maximum size is 100MB" |
| |
| |
| try: |
| cap = cv2.VideoCapture(video_path) |
| if not cap.isOpened(): |
| return False, "Unable to open video file. Please ensure it's a valid video format" |
| |
| |
| ret, _ = cap.read() |
| cap.release() |
| |
| if not ret: |
| return False, "Video file appears to be empty or corrupted" |
| |
| return True, "" |
| except Exception as e: |
| return False, f"Error validating video: {str(e)}" |
|
|
|
|
| @spaces.GPU |
| def estimate_vehicle_speed( |
| video_file: str, |
| model_choice: str, |
| line_position: int, |
| confidence_threshold: float, |
| progress=gr.Progress() |
| ) -> Tuple[Optional[str], str]: |
| """ |
| Process video and estimate vehicle speeds. |
| |
| This function is decorated with @spaces.GPU to enable automatic GPU |
| acceleration when running on ZeroGPU Spaces. If GPU is not available, |
| it automatically falls back to CPU processing. |
| |
| Args: |
| video_file: Path to uploaded video |
| model_choice: YOLO model selection |
| line_position: Y-coordinate for counting line |
| confidence_threshold: Detection confidence threshold |
| progress: Gradio progress tracker |
| |
| Returns: |
| Tuple of (output_video_path, statistics_text) |
| """ |
| try: |
| |
| progress(0, desc="Validating video file...") |
| is_valid, error_msg = validate_video_file(video_file) |
| if not is_valid: |
| logger.error(f"Video validation failed: {error_msg}") |
| return None, f"β Error: {error_msg}" |
| |
| |
| output_path = tempfile.mktemp(suffix='.mp4') |
| |
| |
| progress(0.1, desc="Configuring detection parameters...") |
| config = VehicleDetectionConfig( |
| input_video=video_file, |
| output_video=output_path, |
| model_name=model_choice, |
| line_y=line_position, |
| confidence_threshold=confidence_threshold |
| ) |
| |
| |
| progress(0.2, desc="Processing video (this may take a few minutes)...") |
| logger.info(f"Starting video processing: {video_file}") |
| |
| try: |
| stats = process_video( |
| config=config, |
| progress_callback=lambda p: progress(0.2 + p * 0.7, desc=f"Processing... {int(p*100)}%") |
| ) |
| |
| progress(0.95, desc="Finalizing output...") |
| |
| |
| stats_text = f""" |
| ## π Processing Results |
| |
| ### Vehicle Count Statistics |
| - **Total Vehicles Detected:** {stats['total_count']} |
| - **Vehicles Entering (In):** {stats['in_count']} |
| - **Vehicles Exiting (Out):** {stats['out_count']} |
| |
| ### Speed Analysis |
| - **Average Speed:** {stats['avg_speed']:.1f} km/h |
| - **Maximum Speed:** {stats['max_speed']:.1f} km/h |
| - **Minimum Speed:** {stats['min_speed']:.1f} km/h |
| |
| ### Processing Information |
| - **Frames Processed:** {stats['frames_processed']} |
| - **Processing Time:** {stats['processing_time']:.2f} seconds |
| - **Model Used:** {model_choice} |
| - **Detection Confidence:** {confidence_threshold:.2f} |
| |
| β
**Processing completed successfully!** |
| """ |
| |
| progress(1.0, desc="Complete!") |
| logger.info("Video processing completed successfully") |
| return output_path, stats_text |
| |
| except Exception as e: |
| logger.error(f"Error during video processing: {e}", exc_info=True) |
| return None, f"β **Processing Error:** {str(e)}\n\nPlease try with different settings or a different video." |
| |
| except Exception as e: |
| logger.error(f"Unexpected error in estimate_vehicle_speed: {e}", exc_info=True) |
| return None, f"β **Unexpected Error:** {str(e)}" |
|
|
|
|
| def create_demo_interface() -> gr.Blocks: |
| """ |
| Create Gradio interface for vehicle speed estimation. |
| |
| Returns: |
| Gradio Blocks interface |
| """ |
| with gr.Blocks( |
| title="Vehicle Speed Estimation & Counting" |
| ) as demo: |
| |
| gr.Markdown(""" |
| # π Vehicle Speed Estimation & Counting System |
| |
| An intelligent traffic analysis system that detects, tracks, counts, and estimates the speed of vehicles in video footage using advanced computer vision techniques. |
| |
| ### π― Features |
| - **Real-time Vehicle Detection** using YOLO |
| - **Multi-Object Tracking** with ByteTrack |
| - **Accurate Speed Estimation** via perspective transformation |
| - **Vehicle Counting** with configurable detection zones |
| |
| ### π₯ Developed By |
| - **Abhay Gupta** (0205CC221005) |
| - **Aditi Lakhera** (0205CC221011) |
| - **Balraj Patel** (0205CC221049) |
| - **Bhumika Patel** (0205CC221050) |
| |
| --- |
| """) |
| |
| with gr.Row(): |
| with gr.Column(scale=1): |
| gr.Markdown("### π€ Input Configuration") |
| |
| video_input = gr.Video( |
| label="Upload Traffic Video", |
| format="mp4" |
| ) |
| |
| with gr.Accordion("βοΈ Advanced Settings", open=False): |
| model_choice = gr.Dropdown( |
| choices=["yolov8n", "yolov8s", "yolov8m", "yolov8l"], |
| value="yolov8n", |
| label="YOLO Model", |
| info="Larger models are more accurate but slower" |
| ) |
| |
| line_position = gr.Slider( |
| minimum=100, |
| maximum=1000, |
| value=480, |
| step=10, |
| label="Counting Line Position (Y-coordinate)", |
| info="Vertical position of the vehicle counting line" |
| ) |
| |
| confidence_threshold = gr.Slider( |
| minimum=0.1, |
| maximum=0.9, |
| value=0.3, |
| step=0.05, |
| label="Detection Confidence Threshold", |
| info="Higher values reduce false positives" |
| ) |
| |
| process_btn = gr.Button( |
| "π Process Video", |
| variant="primary", |
| size="lg" |
| ) |
| |
| gr.Markdown(""" |
| ### π Instructions |
| 1. Upload a traffic video (MP4 format, max 100MB) |
| 2. Adjust settings if needed (optional) |
| 3. Click "Process Video" and wait for results |
| 4. Download the annotated video with speed estimates |
| |
| ### π‘ Tips |
| - Use videos with clear vehicle visibility |
| - Ensure consistent camera angle |
| - Better lighting improves detection accuracy |
| """) |
| |
| with gr.Column(scale=1): |
| gr.Markdown("### π₯ Output Results") |
| |
| video_output = gr.Video( |
| label="Processed Video with Annotations" |
| ) |
| |
| stats_output = gr.Markdown( |
| label="Statistics", |
| value="*Processing results will appear here...*" |
| ) |
| |
| |
| gr.Markdown(""" |
| --- |
| ### π¬ Example Videos |
| Upload your own traffic video or use sample footage to test the system. |
| """) |
| |
| gr.Examples( |
| examples=[ |
| ["./data/vehicles.mp4", "yolov8n", 480, 0.3], |
| ], |
| inputs=[video_input, model_choice, line_position, confidence_threshold], |
| outputs=[video_output, stats_output], |
| fn=estimate_vehicle_speed, |
| cache_examples=False, |
| label="Sample Videos" |
| ) |
| |
| |
| process_btn.click( |
| fn=estimate_vehicle_speed, |
| inputs=[video_input, model_choice, line_position, confidence_threshold], |
| outputs=[video_output, stats_output] |
| ) |
| |
| gr.Markdown(""" |
| --- |
| ### π¬ Technical Details |
| |
| This system uses: |
| - **YOLO (You Only Look Once)** for real-time object detection |
| - **ByteTrack** for multi-object tracking across frames |
| - **Perspective Transformation** for accurate speed calculation |
| - **OpenCV** for video processing and computer vision operations |
| |
| ### π References |
| - [Ultralytics YOLO](https://github.com/ultralytics/ultralytics) |
| - [Supervision Library](https://github.com/roboflow/supervision) |
| - [OpenCV](https://opencv.org/) |
| |
| ### π License |
| MIT License - See LICENSE file for details |
| """) |
| |
| return demo |
|
|
|
|
| if __name__ == "__main__": |
| try: |
| logger.info("Starting Vehicle Speed Estimation application...") |
| demo = create_demo_interface() |
| demo.launch( |
| server_name="0.0.0.0", |
| server_port=7860, |
| share=False |
| ) |
| except Exception as e: |
| logger.error(f"Failed to launch application: {e}", exc_info=True) |
| sys.exit(1) |
|
|