| | """ |
| | 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) |
| |
|