Spaces:
Runtime error
Runtime error
| import os | |
| import gradio as gr | |
| import queue | |
| import threading | |
| from concurrent.futures import ThreadPoolExecutor | |
| from ai_alert_generator import AIAlertGenerator, DrowsinessDetectionSystem | |
| class GradioWebRTCInterface: | |
| """Enhanced Gradio interface with WebRTC support""" | |
| def __init__(self): | |
| self.detection_system = None | |
| self.ai_alert_generator = None | |
| self.processing = False | |
| def initialize_system(self, gemini_key): | |
| """Initialize the detection system""" | |
| try: | |
| self.detection_system = DrowsinessDetectionSystem() | |
| self.ai_alert_generator = AIAlertGenerator(gemini_key if gemini_key.strip() else None) | |
| return "β System initialized successfully!", "π Ready for detection" | |
| except Exception as e: | |
| return f"β Error: {str(e)}", "β Initialization failed" | |
| def process_video_stream(self, frame, gemini_key): | |
| """Process video stream""" | |
| if self.detection_system is None: | |
| self.detection_system = DrowsinessDetectionSystem() | |
| self.ai_alert_generator = AIAlertGenerator(gemini_key if gemini_key.strip() else None) | |
| try: | |
| # Process frame | |
| processed_frame, status_list, should_alert, metrics = self.detection_system.process_frame(frame) | |
| # Generate alert if needed | |
| alert_text = "" | |
| alert_audio = None | |
| if should_alert and metrics.get('indicators'): | |
| alert_text = self.ai_alert_generator.generate_alert_text( | |
| metrics['indicators'], | |
| metrics.get('severity', 'medium') | |
| ) | |
| # Create audio alert | |
| try: | |
| audio_file, _ = self.ai_alert_generator.create_audio_alert(alert_text) | |
| alert_audio = audio_file | |
| except Exception as e: | |
| print(f"Audio generation error: {e}") | |
| # Format status | |
| status_text = "\n".join(status_list) | |
| # Get logs | |
| logs = self.detection_system.get_logs() | |
| return processed_frame, status_text, alert_text, alert_audio, logs | |
| except Exception as e: | |
| error_msg = f"Processing error: {str(e)}" | |
| return frame, error_msg, "", None, error_msg | |
| def create_interface(self): | |
| """Create the Gradio interface with WebRTC support""" | |
| with gr.Blocks( | |
| title="π AI Driver Drowsiness Detection System", | |
| theme=gr.themes.Soft(), | |
| css=""" | |
| .alert-box { | |
| background-color: #ffebee; | |
| border: 2px solid #f44336; | |
| border-radius: 8px; | |
| padding: 10px; | |
| } | |
| .status-box { | |
| background-color: #e8f5e8; | |
| border: 2px solid #4caf50; | |
| border-radius: 8px; | |
| padding: 10px; | |
| } | |
| .metric-display { | |
| font-family: 'Courier New', monospace; | |
| font-size: 14px; | |
| } | |
| .header-text { | |
| text-align: center; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| padding: 20px; | |
| border-radius: 10px; | |
| margin-bottom: 20px; | |
| } | |
| """ | |
| ) as interface: | |
| gr.HTML(""" | |
| <div class="header-text"> | |
| <h1>π Drive Paddy/h1> | |
| <p><strong>Real-time monitoring with OpenCV, Computer Vision & AI Alerts</strong></p> | |
| </div> | |
| """) | |
| with gr.Tab("π₯ Live Detection"): | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| # WebRTC video input | |
| webcam_options = gr.WebcamOptions(mirror=False) | |
| video_input = gr.Video( | |
| label="πΉ Camera Feed (WebRTC Streaming)", | |
| sources=["webcam"], | |
| streaming=True, | |
| webcam_options=webcam_options, | |
| height=480 | |
| ) | |
| # System controls | |
| with gr.Row(): | |
| gemini_key = os.getenv("GEMINI_API_KEY") | |
| init_btn = gr.Button("π Initialize", variant="primary", scale=1) | |
| with gr.Column(scale=1): | |
| # System status | |
| init_status = gr.Textbox( | |
| label="π§ System Status", | |
| interactive=False, | |
| lines=2, | |
| elem_classes=["status-box"] | |
| ) | |
| # Detection metrics | |
| current_status = gr.Textbox( | |
| label="π Detection Metrics", | |
| interactive=False, | |
| lines=8, | |
| elem_classes=["metric-display"] | |
| ) | |
| # Alert display | |
| alert_text_display = gr.Textbox( | |
| label="π¨ Active Alert", | |
| interactive=False, | |
| lines=3, | |
| elem_classes=["alert-box"] | |
| ) | |
| # Audio alert output | |
| alert_audio = gr.Audio( | |
| label="π Alert Sound", | |
| autoplay=True, | |
| visible=True | |
| ) | |
| # System logs panel | |
| with gr.Row(): | |
| system_logs = gr.Textbox( | |
| label="π System Activity Log", | |
| lines=6, | |
| interactive=False, | |
| elem_classes=["metric-display"] | |
| ) | |
| with gr.Tab("βοΈ System Configuration"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown(""" | |
| ### π§ Detection Parameters | |
| **Current OpenCV-based thresholds:** | |
| - **Eye Aspect Ratio (EAR)**: < 0.20 for 15+ frames | |
| - **Mouth Aspect Ratio (MAR)**: > 0.8 for 10+ frames | |
| - **Head Nod Angle**: > 20Β° deviation for 8+ frames | |
| - **Alert Cooldown**: 8 seconds between alerts | |
| ### π― Detection Methods | |
| - **Primary**: MediaPipe Face Mesh (if available) | |
| - **Fallback**: OpenCV Haar Cascades | |
| - **No external downloads**: Uses built-in OpenCV models | |
| """) | |
| with gr.Column(): | |
| gr.Markdown(""" | |
| ### π Easy Setup | |
| **Install dependencies:** | |
| ```bash | |
| pip install opencv-python gradio numpy scipy google-generativeai | |
| # Optional for better detection: | |
| pip install mediapipe | |
| ``` | |
| **No model downloads required!** | |
| - Uses OpenCV's built-in face detection | |
| - MediaPipe auto-detects if available | |
| - Gemini API key is optional for AI alerts | |
| """) | |
| gr.Markdown(""" | |
| ### π Advanced Features | |
| - **Real-time WebRTC Processing**: Low latency video streaming | |
| - **Multi-modal Detection**: Eyes, mouth, and head pose analysis | |
| - **AI-Powered Alerts**: Contextual voice messages via Gemini | |
| - **Adaptive Fallback**: Graceful degradation without external models | |
| - **Visual Feedback**: Live metrics overlay on video | |
| - **Comprehensive Logging**: Detailed activity tracking | |
| """) | |
| with gr.Tab("π Detection Info"): | |
| gr.Markdown(""" | |
| ### ποΈ Eye Aspect Ratio (EAR) | |
| **How it works:** | |
| - Calculates ratio of eye height to width | |
| - Lower values indicate closed/closing eyes | |
| - Triggers alert when consistently low | |
| **Detection method:** | |
| - **MediaPipe**: Uses precise eye landmarks | |
| - **OpenCV**: Estimates from eye rectangles | |
| ### π Mouth Aspect Ratio (MAR) | |
| **Yawn detection:** | |
| - Measures mouth opening relative to width | |
| - Higher values indicate yawning | |
| - Accounts for talking vs. yawning patterns | |
| ### π Head Pose Estimation | |
| **Nodding detection:** | |
| - Tracks head tilt and position | |
| - Detects forward head movement | |
| - Uses nose-chin alignment for pose estimation | |
| ### π§ AI Alert Generation | |
| **Smart alerts:** | |
| - Context-aware messages via Gemini | |
| - Severity-based escalation | |
| - Fallback to audio beeps | |
| - Cooldown prevents alert spam | |
| """) | |
| # Event handlers | |
| init_btn.click( | |
| fn=self.initialize_system, | |
| inputs=[gemini_key], | |
| outputs=[init_status, alert_text_display] | |
| ) | |
| # WebRTC stream processing | |
| video_input.stream( | |
| fn=self.process_video_stream, | |
| inputs=[video_input, gemini_key], | |
| outputs=[video_input, current_status, alert_text_display, alert_audio, system_logs], | |
| stream_every=0.1, # 10 FPS processing | |
| show_progress=False | |
| ) | |
| # Safety notice | |
| gr.HTML(""" | |
| <div style="margin-top: 20px; padding: 15px; background: linear-gradient(135deg, #ffeaa7 0%, #fab1a0 100%); border-radius: 8px; border-left: 5px solid #e17055;"> | |
| <h3>β οΈ Important Safety Notice</h3> | |
| <p><strong>This system is for demonstration and research purposes only.</strong></p> | |
| <ul style="margin: 10px 0;"> | |
| <li><strong>Not a substitute</strong> for responsible driving practices</li> | |
| <li><strong>Pull over safely</strong> if you feel drowsy while driving</li> | |
| <li><strong>Ensure proper setup</strong>: good lighting, stable camera position</li> | |
| <li><strong>Use as supplementary tool</strong> alongside other safety measures</li> | |
| </ul> | |
| <p style="margin-top: 15px;"><em>Always prioritize real-world driving safety over technology assistance.</em></p> | |
| </div> | |
| """) | |
| return interface |