🔐 A production-grade Biometric Verification & Emotion Intelligence platform — Built on Google’s MediaPipe Face Mesh AI engine and served over a high-performance Flask backend, this system performs real-time 468-point facial landmark tracking, liveness verification, blink-based access gating, and emotion analysis — all through a dark-mode glassmorphic web dashboard.
The Face Mesh Verification System is a real-time biometric AI platform designed to bridge the gap between classical computer vision and modern web-based access control. Unlike simple face detection libraries, this system uses Google MediaPipe’s 468-point 3D Face Mesh — originally designed for AR effects — and repurposes it for liveness detection, blink-gated verification, and multi-expression tracking, all delivered through a zero-dependency browser client.
┌─────────────────────────────────────────────────────────────────┐
│ │
│ BIOMETRIC INPUT ──► AI INFERENCE ──► TELEMETRY ──► WEB UI │
│ │
│ Webcam Feed MediaPipe Flask API Dashboard │
│ (30+ FPS) Face Mesh 468 /telemetry Dark Mode │
│ Landmarks /video_feed Glass UI │
│ │
│ ◄─────────────── Real-time closed loop (<33ms) ───────────► │
│ │
└─────────────────────────────────────────────────────────────────┘
| Capability | Basic Detection | This System |
|---|---|---|
| Face presence | ✅ Yes | ✅ Yes |
| Landmark count | ~5–68 points | 468 3D points |
| Blink tracking | ❌ | ✅ EAR per frame |
| Emotion inference | ❌ | ✅ MAR + lip geometry |
| Liveness check | ❌ | ✅ Anti-spoof via blink gate |
| Cursor control | ❌ | ✅ Nose-tip mapping |
| Web dashboard | ❌ | ✅ Glassmorphic real-time UI |
| Verification gate | ❌ | ✅ Blink-triggered access |
| Frame throughput | N/A | 30+ FPS MJPEG stream |
This section explains how the Face Mesh engine functions as a biometric security layer — not just a visual tool.
The most critical security feature in any face-based system is distinguishing a live person from a photograph, video replay, or deepfake. This system addresses that with a Blink-Gated Liveness Check:
┌──────────────────────────────────────────────────────────────┐
│ ANTI-SPOOFING LIVENESS PIPELINE │
├──────────────────────────────────────────────────────────────┤
│ │
│ Frame Input ──► Landmark Extraction (468 pts) │
│ │ │
│ ▼ │
│ Calculate EAR (Eye Aspect Ratio) │
│ │ │
│ ┌────────────┴────────────┐ │
│ │ │ │
│ EAR < 0.25 EAR >= 0.25 │
│ │ │ │
│ ▼ ▼ │
│ BLINK DETECTED EYE OPEN STATE │
│ │ │ │
│ Increment Counter Hold Counter │
│ │ │
│ Blink Threshold Met? ──Yes──► ✅ LIVENESS CONFIRMED │
│ │ │
│ No │
│ │ │
│ ❌ LIVENESS PENDING (Prompt user to blink) │
│ │
└──────────────────────────────────────────────────────────────┘
Why this works against spoofing:
- 📷 Photos — cannot blink; EAR stays constant → verification never clears
- 🎥 Recorded videos — unless blink is captured at the right moment + right timing, pattern fails
- 🤖 Deepfakes — unnatural blink cadence is detected through EAR variance monitoring
| Threat Vector | Mitigation Strategy | Implementation |
|---|---|---|
| Photo spoofing | Blink-gate liveness check | EAR < 0.25 threshold detection |
| Static video replay | Blink timing randomization | Frame-by-frame EAR tracking |
| Cursor hijacking | PyAutoGUI failsafe toggle | In-UI hardware control toggle |
| Unauthorized stream access | Local-only binding | Flask bound to 127.0.0.1 |
| Cross-site sniffing | MJPEG boundary isolation | Multipart frame delivery |
| Replay attacks | Session-scoped telemetry | Per-connection state reset |
| Brute force access | Blink count threshold | Configurable N-blink gate |
USER APPROACHES CAMERA
│
▼
┌─────────────────────┐
│ Face Detected? │──── NO ──► Reject + Alert
└─────────────────────┘
│ YES
▼
┌─────────────────────┐
│ 468 Landmarks │
│ Extracted? (>95%) │──── NO ──► Partial face / obstructed
└─────────────────────┘
│ YES
▼
┌─────────────────────┐
│ Liveness: Blink │
│ Detected N times? │──── NO ──► LIVENESS FAIL → Reject
└─────────────────────┘
│ YES
▼
┌─────────────────────┐
│ Emotion / State │
│ Logged to Session │
└─────────────────────┘
│
▼
✅ ACCESS GRANTED
Telemetry Snapshot Saved
| Feature | Description | Status |
|---|---|---|
| 🧿 468-Point Face Mesh | Full MediaPipe AI landmark map in 3D space | ✅ Live |
| 👁️ Blink Detection (EAR) | Eye Aspect Ratio across 12 anchor points | ✅ Live |
| 😶 Emotion Estimation | MAR + lip corner geometry → Neutral/Happy/Surprised | ✅ Live |
| 🖱️ Nose Cursor Control | Nose-tip XY → system cursor translation | ✅ Beta |
| 🔐 Liveness Gate | Blink-verified anti-spoofing check | ✅ Live |
| 📡 MJPEG Streaming | Real-time annotated video over HTTP | ✅ Live |
| 📊 Async Telemetry API | /telemetry JSON polling at 250ms |
✅ Live |
| 🌙 Glassmorphic UI | Dark mode + blur + animated dashboard | ✅ Live |
| UI Component | Technology | Update Rate |
|---|---|---|
| Live webcam feed | MJPEG stream → <img> tag |
30 FPS |
| Blink counter widget | Async fetch → DOM update | 250ms |
| Emotion state badge | JS fetch + class toggling | 250ms |
| Landmark confidence | JSON field render | 250ms |
| Cursor control toggle | Button → POST to backend | On click |
| FPS overlay | Frame delta calculation | Per frame |
╔══════════════════════════════════════════════════════════════════════╗
║ SYSTEM ARCHITECTURE ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ ┌────────────────────────────────────────────────────────────────┐ ║
║ │ LAYER 1 — HARDWARE │ ║
║ │ ┌──────────────────────────────────────────────────────────┐ │ ║
║ │ │ 📷 USB / Integrated Webcam │ 🖱️ OS Mouse / Display │ │ ║
║ │ └──────────────────────────────────────────────────────────┘ │ ║
║ └──────────────────────────┬───────────────────────┬─────────────┘ ║
║ │ Video frames │ Cursor events ║
║ ┌──────────────────────────▼───────────────────────▼─────────────┐ ║
║ │ LAYER 2 — CV ENGINE │ ║
║ │ ┌────────────────┐ ┌────────────────┐ ┌──────────────────┐ │ ║
║ │ │ OpenCV │ │ engine.py │ │ PyAutoGUI │ │ ║
║ │ │ VideoCapture │ │ MediaPipe │ │ moveTo() │ │ ║
║ │ │ BGR→RGB │ │ FaceMesh │ │ click() │ │ ║
║ │ │ Frame Buffer │ │ EAR/MAR Calc │ │ FAILSAFE toggle │ │ ║
║ │ └────────────────┘ └────────────────┘ └──────────────────┘ │ ║
║ └──────────────────────────┬─────────────────────────────────────┘ ║
║ │ Annotated frame + telemetry dict ║
║ ┌──────────────────────────▼─────────────────────────────────────┐ ║
║ │ LAYER 3 — APPLICATION SERVER │ ║
║ │ ┌──────────────────────────────────────────────────────────┐ │ ║
║ │ │ app.py (Flask) │ │ ║
║ │ │ Route: / → Render index.html │ │ ║
║ │ │ Route: /video_feed → MJPEG multipart stream │ │ ║
║ │ │ Route: /telemetry → JSON snapshot │ │ ║
║ │ │ Route: /toggle_ctrl → Enable/Disable cursor mode │ │ ║
║ │ └──────────────────────────────────────────────────────────┘ │ ║
║ └──────────────────────────┬─────────────────────────────────────┘ ║
║ │ HTTP responses ║
║ ┌──────────────────────────▼─────────────────────────────────────┐ ║
║ │ LAYER 4 — WEB DASHBOARD │ ║
║ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ ║
║ │ │ index.html │ │ main.js │ │ style.css │ │ ║
║ │ │ Jinja2 tmpl │ │ AJAX fetch │ │ Glassmorphism │ │ ║
║ │ │ Layout grid │ │ DOM update │ │ Dark Mode │ │ ║
║ │ │ Video mount │ │ 250ms poll │ │ CSS animations │ │ ║
║ │ └──────────────┘ └──────────────┘ └──────────────────────┘ │ ║
║ └────────────────────────────────────────────────────────────────┘ ║
╚══════════════════════════════════════════════════════════════════════╝
graph TD
classDef frontend fill:#1e3a8a,stroke:#3b82f6,stroke-width:2px,color:#fff;
classDef backend fill:#14532d,stroke:#22c55e,stroke-width:2px,color:#fff;
classDef engine fill:#7e22ce,stroke:#a855f7,stroke-width:2px,color:#fff;
classDef hardware fill:#451a03,stroke:#f59e0b,stroke-width:2px,color:#fff;
classDef security fill:#7f1d1d,stroke:#ef4444,stroke-width:2px,color:#fff;
subgraph Hardware["⚙️ Hardware Layer"]
Camera["📷 Webcam\nRaw Video Input"]:::hardware
OS["🖥️ Operating System\nMouse / Display"]:::hardware
end
subgraph CVEngine["🧠 Computer Vision Engine"]
OCV["OpenCV\nVideoCapture + BGR→RGB"]:::engine
MP["engine.py\nMediaPipe FaceMesh\n468 Landmarks"]:::engine
EAR["👁️ EAR Calculator\nBlink Detection"]:::engine
MAR["😮 MAR Calculator\nEmotion Estimation"]:::engine
NOSE["👃 Nose Mapper\nCursor Coordinates"]:::engine
PAGU["PyAutoGUI\nSystem Cursor Control"]:::engine
end
subgraph Security["🔐 Security Gate"]
LIVENESS["Liveness Engine\nBlink Count Gate"]:::security
SPOOF["Anti-Spoof Check\nEAR Variance Analysis"]:::security
end
subgraph Flask["🌐 Flask Application Server"]
APP["app.py\nRoute Controller"]:::backend
VF["GET /video_feed\nMJPEG Multipart"]:::backend
TEL["GET /telemetry\nJSON Snapshot"]:::backend
CTRL["POST /toggle_ctrl\nCursor Mode Toggle"]:::backend
end
subgraph Frontend["💻 Web Dashboard"]
HTML["index.html\nJinja2 Template"]:::frontend
JS["main.js\nAsync Fetch + DOM"]:::frontend
CSS["style.css\nGlassmorphism Dark UI"]:::frontend
end
Camera -->|Raw Frames| OCV
OCV -->|RGB Frame Buffer| MP
MP --> EAR
MP --> MAR
MP --> NOSE
EAR --> LIVENESS
LIVENESS --> SPOOF
NOSE -->|XY Translate| PAGU
PAGU -->|moveTo/click| OS
MP -->|Annotated Frame + Dict| APP
APP --> VF
APP --> TEL
APP --> CTRL
VF -->|MJPEG Stream| HTML
TEL -->|JSON Payload| JS
JS -->|DOM Mutations| HTML
HTML --> CSS
MediaPipe detects 468 unique 3D landmarks across the face. Each region has a dedicated anchor cluster used by this engine:
MEDIAPIPE FACE MESH — LANDMARK REGIONS
═══════════════════════════════════════════════════════════════
[10]
___________
/ \
[109] [338]
/ \
FOREHEAD ──► [54] [284] ◄── FOREHEAD
| ___ ___ |
| / L \ / R \ |
LEFT EYE ──► [33] [159] [145] [246][362][385][380][373] ◄── RIGHT EYE
| EAR ANCHOR POINTS (12 total) |
| |
[234] NOSE [454]
CHEEK ──► | [1][4] | ◄── CHEEK
| NOSE TIP ──► [4] |
| |
[136] [365]
\ MOUTH REGION /
\ _______________ /
UPPER LIP ──► [61][185][40][39][37][267][269][270][409][291]
LOWER LIP ──► [146][91][181][84][17][314][405][321][375][61]
└──── MAR ANCHOR POINTS (8 total) ────┘
\ /
\_____________________/
[175]
CHIN LANDMARK
═══════════════════════════════════════════════════════════════
KEY LANDMARKS USED BY THIS ENGINE:
───────────────────────────────────────────────────────────────
LEFT EYE EAR : [33, 160, 158, 133, 153, 144]
RIGHT EYE EAR : [362, 385, 387, 263, 373, 380]
MOUTH MAR : [61, 291, 39, 181, 0, 17, 269, 405]
LIP CORNERS : [61] LEFT | [291] RIGHT
CENTER LIP : [0] UPPER | [17] LOWER
NOSE TIP : [4] (cursor anchor)
═══════════════════════════════════════════════════════════════
| Region | Landmark IDs | Use Case | Algorithm |
|---|---|---|---|
| Left Eye | 33, 160, 158, 133, 153, 144 | Blink detection | EAR < 0.25 |
| Right Eye | 362, 385, 387, 263, 373, 380 | Blink detection | EAR < 0.25 |
| Upper Lip | 61, 185, 40, 39, 37, 0 | Mouth open tracking | MAR > 0.6 |
| Lower Lip | 146, 91, 181, 84, 17, 314 | Mouth open tracking | MAR > 0.6 |
| Lip Corners | 61 (left), 291 (right) | Smile detection | Corner displacement |
| Nose Tip | 4 | Cursor control | XY → screen mapping |
| Chin | 152 | Face boundary | Aspect ratio validation |
| Forehead | 10 | Head pose | Roll/pitch estimation |
The EAR metric was originally proposed by Soukupová & Čech (2016) and is the gold standard for real-time blink detection:
│ p2 - p6 │ + │ p3 - p5 │
EAR = ─────────────────────────────────────
2 × │ p1 - p4 │
WHERE:
─────────────────────────────────────────────
p1 = left corner of eye (landmark 33 / 362)
p4 = right corner of eye (landmark 133 / 263)
p2 = upper-inner lid (landmark 160 / 385)
p3 = upper-outer lid (landmark 158 / 387)
p5 = lower-outer lid (landmark 144 / 380)
p6 = lower-inner lid (landmark 153 / 373)
─────────────────────────────────────────────
Eye States:
┌───────────────┬───────────────┬──────────────────────────┐
│ EAR Value │ Eye State │ Meaning │
├───────────────┼───────────────┼──────────────────────────┤
│ 0.30 – 0.40 │ OPEN │ Normal resting state │
│ 0.25 – 0.30 │ CLOSING │ Beginning of blink │
│ 0.00 – 0.25 │ CLOSED │ Full blink — detected! │
└───────────────┴───────────────┴──────────────────────────┘
Final averaged EAR = (EAR_left + EAR_right) / 2
│ m2 - m8 │ + │ m3 - m7 │ + │ m4 - m6 │
MAR = ─────────────────────────────────────────────────────
2 × │ m1 - m5 │
Emotion Decision Tree:
┌──────────────────────────────────────────────────────────┐
│ │
│ MAR > 0.6 ─────────────────────► 😮 SURPRISED │
│ │
│ MAR < 0.6 AND corner_displacement > threshold │
│ ─────────────────────► 😄 HAPPY │
│ │
│ MAR < 0.6 AND corner_displacement ≤ threshold │
│ ─────────────────────► 😐 NEUTRAL │
│ │
└──────────────────────────────────────────────────────────┘
Lip Corner Displacement:
─────────────────────────────────────────────────────────────
delta_x = |left_corner.x - center_lip.x|
+ |right_corner.x - center_lip.x|
If delta_x normalized > 0.35 → HAPPY expression confirmed
Webcam Space → Screen Space Linear Transform:
┌────────────────────────────────────────────────────────┐
│ │
│ Webcam Frame: W × H pixels (e.g. 640 × 480) │
│ Screen Space: SW × SH (e.g. 1920 × 1080) │
│ │
│ nose_x_norm = landmark[4].x ∈ [0.0, 1.0] │
│ nose_y_norm = landmark[4].y ∈ [0.0, 1.0] │
│ │
│ cursor_x = (1 - nose_x_norm) × SW ← mirrored │
│ cursor_y = nose_y_norm × SH │
│ │
│ pyautogui.moveTo(cursor_x, cursor_y, duration=0.1) │
│ │
│ CLICK TRIGGER: if EAR < 0.25 during cursor mode │
│ → pyautogui.click() │
│ │
└────────────────────────────────────────────────────────┘
sequenceDiagram
participant U as 👤 User / Camera
participant F as 💻 Browser Dashboard
participant B as 🌐 Flask Backend
participant E as 🧠 CV Engine
participant OS as 🖥️ Operating System
U->>B: HTTP GET /
B->>F: Serve Dashboard (HTML + CSS + JS)
loop 🔁 Real-time Frame Loop (30+ FPS)
B->>E: Capture raw frame
E->>E: BGR → RGB conversion
E->>E: MediaPipe FaceMesh inference
E->>E: Extract 468 3D landmarks
E->>E: Calculate EAR (both eyes averaged)
E->>E: Calculate MAR + lip corner delta
E->>E: Annotate frame with landmarks + overlays
alt 🔐 Liveness Gate Active
E->>E: Check blink count vs threshold
E-->>B: Set liveness_status in telemetry
end
alt 🖱️ Cursor Control Enabled
E->>OS: pyautogui.moveTo(nose_x, nose_y)
opt 👁️ Blink Detected in Cursor Mode
E->>OS: pyautogui.click()
end
end
E-->>B: Return annotated CV2 frame + telemetry dict
B-->>F: Stream frame → multipart/x-mixed-replace
end
loop ⏱️ Async Telemetry Poll (every 250ms)
F->>B: fetch GET /telemetry
B-->>F: JSON { blinks, emotion, ear, mar, liveness, fps }
F->>F: Update dashboard widgets via DOM
end
opt 🔘 User Toggles Cursor Mode
F->>B: POST /toggle_ctrl
B->>E: Flip cursor_control flag
B-->>F: { status: "enabled" / "disabled" }
end
stateDiagram-v2
[*] --> EyeOpen : System Start
EyeOpen : Eye Open\nEAR ≥ 0.25
EyeClosing : Eye Closing\nEAR < 0.25
BlinkConfirmed : Blink Confirmed\nCounter++
LivenessCleared : Liveness Cleared\nGate Open
EyeOpen --> EyeClosing : EAR drops below 0.25
EyeClosing --> EyeOpen : EAR rises above 0.25\n(too fast - no blink)
EyeClosing --> BlinkConfirmed : Sustained below threshold\n(≥ 2 consecutive frames)
BlinkConfirmed --> EyeOpen : Reset state
BlinkConfirmed --> LivenessCleared : blink_count ≥ N
LivenessCleared --> EyeOpen : Continue monitoring
Face-Mesh-Verification-System/
│
├── 📄 app.py # Core routing layer, Flask init, CV video stream controller
├── 🧠 engine.py # AI inference engine — EAR, MAR, landmark math, liveness gate
├── 🔧 mesh.py # Standalone base script for raw MediaPipe landmark viz
├── 📋 requirements.txt # Pinned dependency manifest
│
├── 📂 static/
│ ├── ⚡ main.js # Async fetch loop, DOM manipulation, cursor toggle events
│ └── 🎨 style.css # Glassmorphism dark-mode UI — blur, gradients, animations
│
├── 📂 templates/
│ └── 🖼️ index.html # Jinja2 base layout — video mount, telemetry widgets, controls
│
└── 📄 README.md # You are here
| File | Layer | Primary Responsibility | Key Exports/Routes |
|---|---|---|---|
app.py |
Server | Flask init, route registration, frame generation loop | /, /video_feed, /telemetry, /toggle_ctrl |
engine.py |
CV Engine | MediaPipe inference, EAR/MAR, cursor math, liveness | process_frame(), get_telemetry() |
mesh.py |
Utility | Standalone landmark visualization without server | Visual debugging |
main.js |
Frontend | Async telemetry fetch, DOM update, UI event binding | fetchTelemetry(), toggleCursor() |
style.css |
Frontend | Glassmorphic layout, animations, dark theme | CSS variables, blur effects |
index.html |
Frontend | HTML skeleton, MJPEG <img>, widget containers |
Jinja2 template blocks |
| Category | Technology | Version | Purpose |
|---|---|---|---|
| Language | Python | 3.10+ | Core runtime |
| AI Framework | MediaPipe | Latest | 468-point Face Mesh inference |
| Computer Vision | OpenCV | 4.x | Camera capture, frame processing, annotation |
| Web Framework | Flask | 2.x | HTTP routing, MJPEG streaming, REST API |
| System Control | PyAutoGUI | Latest | OS cursor movement and click injection |
| Frontend | HTML5 / CSS3 | — | Glassmorphic dashboard layout |
| Frontend JS | Vanilla JS | ES2020+ | AJAX polling, DOM manipulation |
| Styling | CSS Glassmorphism | — | Dark mode, blur, gradient UI |
| Math | NumPy | Latest | Euclidean distance, landmark geometry |
| Streaming | MJPEG | — | Real-time annotated video over HTTP |
Requires Python 3.10+ and a working webcam. Windows, macOS, and Linux supported.
git clone https://github.com/RishvinReddy/Face-Mesh-Verification-System.git
cd Face-Mesh-Verification-System# Windows
python -m venv venv
.\venv\Scripts\activate
# macOS / Linux
python3 -m venv venv
source venv/bin/activatepip install -r requirements.txtpython app.pyNavigate to http://localhost:5000 in any modern browser.
requirements.txt
────────────────────────────────────────────
opencv-python # Webcam capture + CV2 frame ops
mediapipe # 468-point face mesh AI model
flask # HTTP server + template engine
pyautogui # OS cursor control interface
numpy # Landmark math (distance, matrix)
────────────────────────────────────────────
| Library | Min Version | Install Cmd |
|---|---|---|
| opencv-python | 4.5.0 | pip install opencv-python |
| mediapipe | 0.9.0 | pip install mediapipe |
| flask | 2.0.0 | pip install flask |
| pyautogui | 0.9.53 | pip install pyautogui |
| numpy | 1.21.0 | pip install numpy |
The Flask backend exposes a lightweight REST API for frontend telemetry consumption.
| Method | Route | Description | Response Type |
|---|---|---|---|
GET |
/ |
Render main dashboard HTML | text/html |
GET |
/video_feed |
MJPEG annotated webcam stream | multipart/x-mixed-replace |
GET |
/telemetry |
Real-time biometric telemetry snapshot | application/json |
POST |
/toggle_ctrl |
Enable/disable nose cursor control | application/json |
{
"blink_count": 12,
"ear": 0.287,
"mar": 0.142,
"emotion": "Happy",
"liveness": true,
"cursor_control": false,
"fps": 31.4,
"landmarks_found": true
}| Field | Type | Description |
|---|---|---|
blink_count |
int |
Total blinks counted since session start |
ear |
float |
Averaged Eye Aspect Ratio (both eyes) |
mar |
float |
Mouth Aspect Ratio (current frame) |
emotion |
string |
Current estimated emotion state |
liveness |
bool |
Whether liveness gate has been cleared |
cursor_control |
bool |
Cursor control mode active flag |
fps |
float |
Current processing frame rate |
landmarks_found |
bool |
Whether face was successfully detected |
| Resolution | Average FPS | Inference Time | Landmark Points |
|---|---|---|---|
| 320 × 240 | ~45 FPS | ~12ms | 468 |
| 640 × 480 | ~30 FPS | ~22ms | 468 |
| 1280 × 720 | ~18 FPS | ~40ms | 468 |
| 1920 × 1080 | ~10 FPS | ~75ms | 468 |
Benchmarked on Intel Core i5-11th Gen, 8GB RAM, integrated webcam
| Metric | Condition | Accuracy |
|---|---|---|
| Face detection rate | Normal lighting, frontal | ~99% |
| Blink detection accuracy | EAR threshold 0.25 | ~97% |
| Emotion accuracy (Happy) | Open smile, no mask | ~85% |
| Emotion accuracy (Surprised) | Mouth open > 2cm | ~88% |
| Liveness spoof rejection (photo) | Printed photo | ~95%+ |
| Nose cursor precision | 1080p display | ± 15px |
┌─────────────────────────────────────────────────────────────────────┐
│ SECURITY LAYERS │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ LAYER 1 — NETWORK │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Flask bound to 127.0.0.1 (localhost only) │ │
│ │ No external network exposure by default │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ LAYER 2 — LIVENESS DETECTION │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ EAR-based blink gate — rejects static images │ │
│ │ Frame-sustained blink validation (≥2 frames below threshold) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ LAYER 3 — SESSION ISOLATION │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Telemetry state resets per connection │ │
│ │ Blink counter scoped to live session │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ LAYER 4 — HARDWARE CONTROL SAFETY │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Cursor control disabled by default │ │
│ │ Explicit toggle required via UI button │ │
│ │ FAILSAFE can be re-enabled for production deployments │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
graph LR
classDef threat fill:#7f1d1d,stroke:#ef4444,color:#fff
classDef mitigation fill:#14532d,stroke:#22c55e,color:#fff
classDef partial fill:#78350f,stroke:#f59e0b,color:#fff
T1["📷 Photo Spoof Attack"]:::threat --> M1["✅ EAR Blink Gate\nRejects static faces"]:::mitigation
T2["🎥 Video Replay Attack"]:::threat --> M2["⚠️ Timing-based blink\nPartial mitigation"]:::partial
T3["🤖 Deepfake Video"]:::threat --> M3["⚠️ EAR variance check\nPartial mitigation"]:::partial
T4["🌐 Remote Access"]:::threat --> M4["✅ Localhost binding\nNo external exposure"]:::mitigation
T5["🖱️ Cursor Hijack"]:::threat --> M5["✅ Explicit UI toggle\nDisabled by default"]:::mitigation
T6["📡 Stream Interception"]:::threat --> M6["✅ MJPEG isolation\nMultipart boundary"]:::mitigation
| Phase | Feature | Priority | Status |
|---|---|---|---|
| v1.0 | 468-point face mesh tracking | Core | ✅ Done |
| v1.0 | EAR blink detection | Core | ✅ Done |
| v1.0 | MAR emotion estimation | Core | ✅ Done |
| v1.0 | Glassmorphic web dashboard | Core | ✅ Done |
| v1.0 | Nose cursor control | Beta | ✅ Done |
| v1.1 | Configurable blink threshold via UI | Enhancement | 🔲 Planned |
| v1.1 | Session history export (JSON/CSV) | Enhancement | 🔲 Planned |
| v1.2 | Head pose estimation (roll/pitch/yaw) | Feature | 🔲 Planned |
| v1.2 | Iris tracking integration | Feature | 🔲 Planned |
| v2.0 | Face registration + identity matching | Major | 🔲 Future |
| v2.0 | Multi-face support | Major | 🔲 Future |
| v2.0 | Advanced deepfake detection layer | Security | 🔲 Future |
| v2.0 | Mobile-responsive PWA | Major | 🔲 Future |
When nose cursor control is enabled, your head position controls the OS mouse cursor and blinks trigger clicks.
- 🐭 Moving your head moves the cursor in real-time
- 👁️ Blinking activates a mouse click at current cursor position
⚠️ PyAutoGUIFAILSAFEis disabled by default to prevent edge-case crashes at screen corners- 🔘 To regain instant hardware mouse control: click the toggle button in the dashboard UI
- 🛡️ For production deployments, re-enable
pyautogui.FAILSAFE = Trueinengine.py
Contributions, feature suggestions, and bug reports are welcome!
# Fork the repo, then:
git checkout -b feature/your-feature-name
git commit -m "feat: add your feature description"
git push origin feature/your-feature-name
# Open a Pull Request on GitHubContribution Guidelines:
- Follow the existing code style in
engine.pyandapp.py - New detection algorithms should be added to
engine.pywith isolated functions - Frontend changes should maintain the glassmorphic dark-mode design language
- Include comments for any new landmark anchor clusters used
This project is licensed under the MIT License — see the file for details.
MIT License — Free to use, modify, and distribute with attribution.
Copyright (c) 2024 Rishvin Reddy