Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚗 Driver Drowsiness Alert - Dashboard

A real-time driver drowsiness detection system with a browser-based dashboard. OpenCV watches a webcam feed for closed eyes; when the driver's eyes stay shut past a threshold, the dashboard sounds an alarm and sends an email alert with an IP-based location link - all shown live on a night-instrument-cluster style web UI.

This is a rebuild of the original desktop (cv2.imshow) version as a Flask web app, with security hardening and an attractive dashboard front end. See Security notes below for the full list of hardening changes and their limits.

✨ Features

  • 👁️ Real-time face/eye tracking (OpenCV Haar cascades), streamed to the browser as a live MJPEG feed
  • 🔔 Looping audio alarm + rate-limited email alert with an IP-based Google Maps link, once eyes are closed past the threshold
  • 📊 Dashboard UI: live "alertness gauge", status telltales (face / eyes / alarm), and a scrolling event log
  • 🔒 Security headers (CSP, X-Frame-Options, Permissions-Policy, etc.), no debug tracebacks by default, and no state-changing endpoints at all - the alarm, email alerts, and developer-tools lock are all set via .env only, with zero UI footprint
  • 🖥️ Optional, honestly-labeled developer-tools lock, set by the operator via .env (deterrent, not a real security boundary - see below)

🛠️ Tech stack

Layer Choice Why
Backend Flask Lightweight, no build step, well suited to serving an MJPEG stream from an OpenCV loop
Computer vision OpenCV (Haar cascades) Same detection approach as the original, kept on the last 4.x release - see the requirements.txt note on why
Frontend Plain HTML/CSS/JS No bundler needed for a single-page local dashboard; keeps the whole client auditable in two small files
Audio alerts Pygame Unchanged from the original
Email alerts smtplib (Gmail SMTP) Unchanged from the original, now cooldown-limited
Geolocation geocoder (IP-based) Unchanged from the original

📋 How it works

  1. A background thread captures webcam frames and runs Haar-cascade face and eye detection on each one.
  2. The dashboard polls /api/status every second and streams the annotated video from /video_feed.
  3. If no eyes are detected continuously past the threshold, the alarm sounds and (if configured and outside the cooldown window) an email alert goes out with an approximate location link.
  4. Everything resets once eyes are detected again.

🚀 Getting started

Prerequisites

  • Python 3.12–3.14 (tested on 3.14.6; opencv-python ships abi3 wheels, so it installs cleanly on 3.14 without waiting for a Python-version-specific build)
  • A working webcam
  • A Gmail account with an App Password if you want email alerts (do not use your real password)

Installation

git clone https://github.com/mageshit24/Driver-Drowsiness-Alert.git
cd Driver-Drowsiness-Alert

# Create and activate a virtual environment
python -m venv venv

# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt
# or, for a byte-for-byte reproducible install:
pip install -r requirements-lock.txt

Configuration

# .env
HOST=127.0.0.1
PORT=5000
FLASK_DEBUG=false
SECRET_KEY=secret_key_generated
CAMERA_INDEX=0
CLOSE_THRESHOLD_SECONDS=5
JPEG_QUALITY=80
ALARM_ENABLED=true
EMAIL_ALERTS_ENABLED=true
DEVTOOLS_LOCK_ENABLED=false
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
EMAIL_SENDER=sender_email
EMAIL_PASSWORD=sender_app_password
EMAIL_RECEIVER=receiver_email
ALERT_EMAIL_COOLDOWN_SECONDS=120

Fill in .env with your values. At minimum, set a SECRET_KEY:

python -c "import secrets; print(secrets.token_hex(32))"

Email alerts are optional - if EMAIL_SENDER / EMAIL_PASSWORD / EMAIL_RECEIVER are left blank, the dashboard just shows email alerts as "not configured" and the alarm/detection still work normally.

The alarm sound, email alerts, and developer-tools lock are all operator-set booleans in .env - ALARM_ENABLED, EMAIL_ALERTS_ENABLED, and DEVTOOLS_LOCK_ENABLED. None of these appears in the dashboard UI at all, not even as a read-only indicator - they're purely server configuration. To change one, edit .env and restart the app (Ctrl+C, then python app.py again - config is only read at startup). See Security notes for what the devtools lock does and doesn't protect against before turning it on.

Run

python app.py

Open http://127.0.0.1:5000 in your browser. By default the server only binds to localhost - see Security notes before setting HOST=0.0.0.0 to expose it on your network.

🔒 Security notes

This documents what changed from the original desktop script and, just as importantly, what the changes do and don't protect against. This app is built for local, single-user use (you, monitoring your own drive) - it is not designed for multi-tenant or public deployment.

What was fixed

Credential handling

  • No credential ever had a hardcoded fallback (this was already true in the original app.py, and is preserved here). EMAIL_SENDER, EMAIL_PASSWORD, EMAIL_RECEIVER, SECRET_KEY all come from .env, which is git-ignored.
  • If email isn't configured, the feature disables itself with a status message instead of crashing or logging a scary warning at import time.

Code / information exposure

  • DEBUG defaults to off. The Werkzeug debugger (which lets anyone who can reach an error page execute arbitrary Python) is never enabled unless you explicitly set FLASK_DEBUG=true.
  • Custom 404/500 handlers return a minimal JSON error instead of a stack trace, so even a misconfiguration can't leak file paths or internals.
  • requirements.txt was UTF-16-encoded in the original repo (an encoding artifact, not a security issue by itself, but it silently breaks pip install -r requirements.txt on some setups) — rewritten as plain UTF-8 with real, current, verified pins. See the note at the top of that file about the OpenCV 5.x CascadeClassifier removal.
  • requirements.txt uses pygame-ce instead of pygame. Plain pygame has no prebuilt wheel for Python 3.14 yet, so installing it on 3.14 tries to compile from source and fails (missing distutils.msvccompiler, which modern Python removed). pygame-ce is the actively maintained, API-compatible community fork - import pygame still works unchanged - and it ships a real Python 3.14 wheel.
  • The app binds to 127.0.0.1 by default. Setting HOST=0.0.0.0 to reach it from other devices is an explicit, opt-in choice - read that as "now anyone on this network can watch the camera feed and flip your alarm/email toggles" before doing it.

Response hardening - every response carries:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY (can't be framed/clickjacked)
  • Referrer-Policy: no-referrer
  • Permissions-Policy: camera=(), microphone=(), geolocation=() - the browser never needs any of these (video comes from the server-side OpenCV loop, not getUserMedia; location comes from server-side IP lookup, not the browser's Geolocation API), so they're explicitly denied
  • A Content-Security-Policy restricting scripts/styles/connections to the app's own origin plus Google Fonts

Request hardening

  • Every route in this app is read-only (/, /video_feed, /api/status). The alarm, email alerts, and developer-tools lock are all read from .env at startup - there is no endpoint that accepts a POST and changes server state, so there's no CSRF surface to defend in the first place. This is a deliberate simplification over an earlier version that had a toggle-driven /api/settings endpoint and a dashboard panel showing these settings; both are gone now - the settings are server configuration, not part of the app's surface.
  • Session cookies are HttpOnly and SameSite=Lax.

Alert abuse prevention

  • send_alert() is cooldown-limited (ALERT_EMAIL_COOLDOWN_SECONDS, default 120s). Without this, a flickering camera or false detection loop could spam the receiver's inbox indefinitely.
  • SMTP failures are caught and summarized as failed: <ExceptionType> in the server log only - never returned to the browser, never including the raw exception text (which could echo back connection details).

Dependency hygiene All pinned versions in requirements.txt / requirements-lock.txt were checked with pip-audit against the PyPI advisory database - no known vulnerabilities at time of writing. Re-run pip-audit -r requirements-lock.txt periodically; pins go stale.

The developer-tools lock - read this before enabling it

The dashboard can lock developer tools on its own tab, controlled by DEVTOOLS_LOCK_ENABLED in .env (default false). It is not a dashboard toggle on purpose - a setting anyone using the UI could flip wouldn't be worth much, so it's server-configured only. Being honest about what it does:

  • When on, it blocks F12, Ctrl+Shift+I/J/C, Ctrl+U, and right-click, and shows a warning overlay if it detects the browser window resizing in a way consistent with docked dev tools.
  • This is a client-side JavaScript deterrent, not a security boundary. Anyone can disable JavaScript, use their browser's menu instead of a shortcut, undock dev tools before the resize check triggers, or open dev tools on a different tab and navigate over. There is no way to actually prevent a user from inspecting a page their own browser renders - no website can.
  • It exists because it's a common ask for internal/demo tools where the goal is discouraging casual poking, not stopping a determined person. Don't rely on it to hide anything sensitive.

The real reason this app is safe to open dev tools on: there's nothing sensitive in the browser to find. Camera frames are processed server-side; only the rendered JPEG stream and a small non-secret status JSON (booleans, durations) ever reach the client. Credentials, SMTP details, and the geolocation lookup all stay server-side. That's the actual "code exposure prevention" here - the devtools lock is a UX nicety on top of it, not the mechanism.

What this app still doesn't do (be aware)

  • No authentication. Anyone who can reach the bound host/port sees the live camera feed. Keep HOST at 127.0.0.1 unless you add auth in front of it (e.g. a reverse proxy with basic auth) first.
  • No HTTPS/TLS out of the box - fine for 127.0.0.1, not fine if you expose this beyond your own machine.
  • No rate limiting on /video_feed or /api/status beyond what a single-user local tool needs.

🗺️ Roadmap

  • Yawn / mouth detection for additional fatigue signals
  • SMS alerts via Twilio
  • Deep learning-based eye state classification (CNN) for higher accuracy
  • Mobile companion app

👤 Author

Magesh Hariram K

LinkedIn

📄 License

This project is open source. Consider adding an MIT License file if you plan to accept contributions.

About

Real-time driver drowsiness detection system using OpenCV that triggers an audio alarm and sends an email alert with GPS location when the driver's eyes stay closed too long.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages