EyeGuard 20-20-20 πŸ‘οΈ

A robust computer-vision application that enforces the 20-20-20 rule for eye health β€” with anti-spoofing protection against one-eye-closed tricks.

The 20-20-20 Rule

  • Every 20 minutes of screen time
  • Look at something 20 feet away
  • For at least 20 seconds

Features

Core Functionality

  • Real-time webcam eye tracking using MediaPipe Face Mesh (468 landmarks)
  • Per-eye EAR (Eye Aspect Ratio) calculation β€” each eye tracked independently
  • 20-minute timer with visual countdown
  • 20-second rest enforcement β€” both eyes must stay closed
  • Blink filtering β€” brief blinks (< 0.5s) don't count as rest

Anti-Spoofing / Anti-Cheating

  • One-eye-closed trick = DETECTED β€” requires BOTH eyes closed simultaneously for the full 20 seconds
  • Face disappearance detection β€” if the face leaves the camera during rest, the rest attempt fails
  • Hysteresis thresholds β€” prevents flickering between open/closed states
  • Temporal smoothing β€” median filter over 5 frames for stable EAR readings
  • Geometric verification β€” uses facial landmark geometry, not just single-frame classification

State Machine

  1. SCREENING β€” Normal work, counting down 20 minutes
  2. ALERT β€” Time for a break! Flashing red banner asks user to close both eyes
  3. RESTING β€” Both eyes confirmed closed, counting 20 seconds
  4. REST_COMPLETE β€” Break finished successfully, timer resets
  5. SPOOFING β€” One-eye trick detected! 3-second penalty before retry
  6. NO_FACE β€” Face not visible, waiting for user

Requirements

pip install opencv-python-headless mediapipe==0.10.13 numpy

Usage

Basic Usage (default webcam)

python eye_guard_2020.py

Different Camera

python eye_guard_2020.py --camera 1

Adjust Sensitivity

python eye_guard_2020.py --ear-open 0.18 --ear-closed 0.12

Key Controls (during runtime)

  • q β€” Quit
  • r β€” Reset the 20-minute timer
  • t β€” Test mode (force alert immediately)

How It Works

Eye Aspect Ratio (EAR)

EAR = (||P2-P6|| + ||P3-P5||) / (2 * ||P1-P4||)

Open eye: EAR β‰ˆ 0.25–0.35
Closed eye: EAR β‰ˆ 0.05–0.15

Hysteresis

  • Eye is closed only when EAR drops below ear_closed (default 0.18)
  • Eye is open only when EAR rises above ear_open (default 0.22)
  • This 0.04 gap provides stable state transitions

Blink Rejection

A closure must last at least 15 consecutive frames (~0.5s at 30fps) to count as "resting". Normal blinks (100–300ms) are filtered out.

One-Eye Trick Detection

During RESTING, if either eye re-opens while the other stays closed:

  1. Status immediately switches to SPOOFING
  2. The rest attempt is marked as failed
  3. A 3-second penalty is enforced
  4. The user must start the 20-second rest over

Testing

python test_eyeguard_synthetic.py

Tests cover:

  1. βœ… Normal rest cycle (both eyes closed)
  2. βœ… Spoofing detection (one eye closed)
  3. βœ… Blink filtering (brief closures ignored)
  4. βœ… Rest interruption (early opening)
  5. βœ… No-face detection during rest
  6. βœ… One-eye trick during alert phase

Why This Approach?

Our geometric approach cannot be fooled by closing one eye because it computes EAR for each eye independently and enforces an AND gate β€” both must be closed. This is fundamentally more robust than deep-learning classifiers that operate on whole-face images and can be confused by partial closures.

Parameters

Parameter Default Description
ear_open 0.22 EAR threshold to mark eye as open
ear_closed 0.18 EAR threshold to mark eye as closed
SCREEN_TIME_ALERT_SECONDS 1200 20 minutes in seconds
REST_DURATION_SECONDS 20 Rest duration in seconds
MIN_CONSECUTIVE_CLOSED_FRAMES 15 Minimum frames (~0.5s) to count as rest start

License

MIT β€” free for personal and commercial use. Protect your eyes! πŸ‘€

Generated by ML Intern

This model repository was generated by ML Intern, an agent for machine learning research and development on the Hugging Face Hub.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support