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 |