Skip to content

Repository files navigation

🚀 You will never miss attendance again.

VisionAI Pro replaces paper rolls, manual sign-ins, and brittle QR codes with a single webcam, a 128-dimensional biometric neural embedding, and a browser tab.
Point your camera. Watch names appear. Done.


Python Flask OpenCV YuNet SFace Tests Version License


"From zero to a fully automated attendance system in under 5 minutes —
no cloud API keys, no subscriptions, no latency tax."


📸 What It Looks Like

┌─────────────────────────────────────────────────────────────┐
│  VISION AI PRO  v2.5          YuNet+SFace  Anti-Spoof: ON  │
├─────────────┬───────────────────────────────────────────────┤
│  Enrolled   │  ┌──────── Live Biometric Scanner ──────────┐ │
│  Students   │  │   ┌─────────────────────────────────┐    │ │
│    12       │  │   │  ⬜                           ⬜  │    │ │
│             │  │   │      ╔═══════════════╗          │    │ │
│  Today's   │  │   │      ║  Nikhil Kumar  ║          │    │ │
│ Attendance │  │   │      ║   97.3% Match  ║          │    │ │
│     8       │  │   │      ╚═══════════════╝          │    │ │
│             │  │   │  ⬜                           ⬜  │    │ │
│  Embeddings │  │   └─────────────────────────────────┘    │ │
│    240      │  │  ◉ AI ACTIVE          2 FACES IN VIEW     │ │
│             │  └──────────────────────────────────────────┘ │
│  FPS: 28.4  │  [ Pause Feed ] [ Register Face ] [Snapshot]  │
└─────────────┴───────────────────────────────────────────────┘

✨ Why VisionAI Pro?

Problem VisionAI Pro Solution
Paper rolls are slow & forgeable Millisecond biometric match — impossible to fake
QR codes can be shared / screenshotted Anti-spoof blocks printed photos & screen replays
Cloud vision APIs cost money & need internet Fully offline, runs on any laptop with a webcam
Old Haar-cascade detectors false-trigger on walls YuNet deep CNN: 0% false positives on backgrounds
One wrong login marks wrong person 128-dim ArcFace embedding — sub-millimetre face identity
No audit trail CSV export + per-record deletion + manual override

🔬 How It Works (The Technical Stack)

Webcam Frame
     │
     ▼
┌──────────────────┐
│  YuNet Deep CNN  │  ← Face detection, 5-point landmarks, confidence score
│  (ONNX, 320KB)   │    Rejects walls, objects, pictures → 0% false positives
└────────┬─────────┘
         │ Detected face ROI + landmarks
         ▼
┌──────────────────┐
│  Anti-Spoof      │  ← Laplacian blur · YCrCb skin · RGB glare · variance
│  Liveness Check  │    Blocks printed photos, phone screens, video replays
└────────┬─────────┘
         │ is_real=True
         ▼
┌──────────────────┐
│  SFace ArcFace   │  ← Aligns face via 5 landmarks
│  128-dim Embedder│    Extracts unique biometric vector (ONNX, 37MB)
└────────┬─────────┘
         │ feature[128]
         ▼
┌──────────────────┐
│  Cosine Matcher  │  ← Top-3 average similarity across all enrolled faces
│  threshold=0.38  │    Returns: name + confidence (0–1)
└────────┬─────────┘
         │ name, confidence ≥ threshold
         ▼
┌──────────────────┐
│ AttendanceManager│  ← Thread-safe, one-mark-per-day dedup
│  CSV + Memory    │    Persists to attendance.csv with backup
└──────────────────┘

🏗️ Architecture

Full System Flow

graph TD
    subgraph "🖥️ Frontend — Browser / Desktop"
        UI[Web Dashboard index.html]
        MJPEG[MJPEG Video Stream]
        LogsTab[Attendance Logs Tab]
        RosterTab[Enrolled Roster Tab]
        SysTab[System Info Tab]
    end

    subgraph "⚙️ Backend — Flask app.py"
        Flask[Flask Server]
        RateLimit[Rate Limiter]
        API[REST API Endpoints]
    end

    subgraph "🧠 Core Services — src/"
        CamSvc[CameraService\nThread-safe MJPEG]
        FaceEng[FaceEngine\nYuNet + SFace]
        AntiSpoof[Anti-Spoofing\nLiveness Check]
        AttMgr[AttendanceManager\nCSV + Memory]
        Config[AppConfig\nEnv + Paths]
    end

    subgraph "💾 Data"
        Webcam[📷 Webcam]
        PKL[(face_data.pkl\n128-dim vectors)]
        CSV[(attendance.csv)]
        Faces[(faces/ folder\nDataset images)]
        Models[(models/\nYuNet + SFace ONNX)]
    end

    UI -->|poll /api/stats every 1.5s| Flask
    UI -->|poll /attendance every 3s| Flask
    MJPEG -->|/video_feed stream| Flask
    Flask --> RateLimit --> API
    API --> CamSvc & FaceEng & AttMgr
    CamSvc -->|read frames| Webcam
    CamSvc -->|process_frame| FaceEng
    FaceEng -->|check_liveness| AntiSpoof
    FaceEng -->|cosine match| PKL
    FaceEng -->|load models| Models
    CamSvc -->|mark_attendance| AttMgr
    AttMgr -->|write/read| CSV
    FaceEng -->|train_model| Faces
Loading

Directory Layout

facetrack/
├── src/                            # Core package
│   ├── __init__.py                 # Public exports
│   ├── config.py                   # Centralised env + path settings
│   ├── face_engine.py              # YuNet detection · SFace matching · anti-spoof
│   ├── attendance_manager.py       # Thread-safe CSV persistence & dedup
│   └── camera_service.py           # Multi-threaded capture · MJPEG generator
│
├── templates/
│   └── index.html                  # Full-stack web dashboard (Inter + JetBrains Mono)
│
├── static/
│   ├── favicon.png
│   └── logo.jpg
│
├── tests/
│   ├── test_app.py                 # 25 Flask endpoint integration tests
│   ├── test_attendance_manager.py  # 8 AttendanceManager unit tests
│   └── test_config.py              # 3 config validation tests
│
├── models/                         # Auto-downloaded ONNX models (git-ignored)
├── faces/                          # Registered face datasets (git-ignored)
│
├── app.py                          # Flask web server entry point
├── attendance.py                   # OpenCV desktop GUI runner
├── register.py                     # CLI face registration utility
├── train.py                        # CLI model training utility
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── README.md

⚡ Quick Start (5 minutes)

Prerequisites

  • Python 3.8+
  • A webcam (built-in or USB)
  • ~100 MB disk space (for ONNX models — auto-downloaded on first run)

1. Clone & Install

git clone https://github.com/bhedanikhilkumar-code/facetrack.git
cd facetrack

python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activate

pip install -r requirements.txt

2. Launch the Dashboard

python app.py

Open http://localhost:5000 in your browser.
The YuNet and SFace models download automatically (~40 MB, once).

3. Enroll Your First Student

  1. Click Register Face (top-right of scanner)
  2. Enter the student name
  3. Click Snap Live Frame 3–5 times (or Upload Photos)
  4. Click Save & Train Model

The model retrains in seconds. The student will be recognised on the very next frame.

4. Take Attendance

Just stand in front of the webcam. VisionAI Pro marks you present automatically, once per day.


🐳 Docker Deployment

# Build and run
docker-compose up --build

# Access dashboard
open http://localhost:5000

Note: Camera access inside Docker requires host video device passthrough.
See docker-compose.yml for the /dev/video0 mapping.


⚙️ Configuration

All settings can be overridden with environment variables or a .env file:

Variable Description Default
CAMERA_INDEX Webcam device index (0 = default) 0
HOST Flask bind address 0.0.0.0
PORT Flask port 5000
DEBUG Enable Flask debug mode False
LOG_LEVEL Logging verbosity (INFO, DEBUG) INFO
API_KEY Optional Bearer key for POST endpoints (unset = open)

Example .env:

CAMERA_INDEX=1
PORT=8080
API_KEY=my-secret-key-here

🌐 REST API Reference

All responses are JSON. Rate-limited POST endpoints return 429 when exceeded.

Core

Method Endpoint Description
GET / Web dashboard UI
GET /video_feed MJPEG live stream with face overlays
GET /api/health { status, uptime, version }
GET /api/stats Live metrics (FPS, faces, attendance count…)
GET /api/model/info Embedding count, persons list, pkl size

Attendance

Method Endpoint Body Description
GET /attendance All attendance records as array
POST /api/attendance/manual { name } Manually mark a student present
POST /api/attendance/delete { name, date, time } Remove a specific record
POST /api/attendance/clear Wipe today's records
GET /api/export_csv Download attendance.csv

Face Registration

Method Endpoint Body Description
POST /api/register { name, images[] } Enroll person + retrain model
GET /api/persons List enrolled persons + sample count
DELETE /api/persons/<name> Delete person + retrain model

Camera

Method Endpoint Description
GET /api/camera/status { active, fps, faces_detected }
GET /api/camera/health { camera_connected, worker_alive, uptime_seconds, … }
GET /api/camera/snapshot Base64 JPEG of current frame
POST /api/camera/toggle Toggle camera on/off
POST /api/camera/state { active: bool } — explicit set

🧪 Testing

pytest tests/ -v
36 passed in 0.91s

Test breakdown:

  • 25 tests — Flask endpoint integration (auth, rate-limiting, all routes)
  • 8 testsAttendanceManager unit tests (mark, dedup, delete, clear, CSV)
  • 3 testsAppConfig validation (types, threshold ranges, defaults)

🛡️ Security Features

  • Rate limiting — All mutating POST endpoints capped (10 req/min for most, 60/min for deletes)
  • API key auth — Optional X-API-Key header enforcement via API_KEY env var
  • Input sanitisation — HTML stripped from all user-supplied strings before storage
  • Security headersX-Content-Type-Options, X-Frame-Options, X-XSS-Protection on all responses
  • Anti-spoofing — Liveness detection blocks photo prints, screen replays, and deepfakes
  • Atomic CSV writes — Backup .bak copy created before every rewrite

🔧 CLI Utilities

Register a student via webcam (no browser needed)

python register.py --name "Nikhil Kumar" --samples 20

Captures 20 face frames from webcam, saves to faces/Nikhil Kumar/, and auto-trains.

Re-train the model manually

python train.py

Scans all faces/*/ folders, extracts 128-dim SFace embeddings, writes face_data.pkl.

Run as desktop OpenCV window

python attendance.py
# With options:
python attendance.py --camera-index 1 --fullscreen

Camera hardware diagnostic

python camera.py --duration 10

🏆 Feature Changelog — v2.5.0

Category Change
🐛 Fix Deadlock removed_ensure_worker_running() no longer acquires _lock while set_active() holds it
🐛 Fix Stale frame metadata — frame-skip logic desynchronised face_count/rec_names from displayed frame; now every frame processed
🐛 Fix API key guardbefore_request blocked ALL POST requests even when API_KEY not configured
🐛 Fix register.py wrong kwarg — called sample_count= instead of max_samples=
🐛 Fix Missing </style> tag in HTML caused entire stylesheet to be skipped
🐛 Fix captureLiveSnapshot() discarded the snap — called openRegisterModal() after snapping, which reset capturedFrames = []
✨ New Manual Attendance modal — mark any enrolled student present by name with autocomplete
✨ New Delete individual log entry — trash button on every attendance row
✨ New System Info tab — real-time camera health, worker status, uptime, frame count
✨ New /api/camera/health endpoint — exposes all CameraService health metrics
✨ New MJPEG auto-recovery — falls back to snapshot polling if stream fails in 1.5s
✨ New Snapshot download — scanner footer button downloads current frame as JPEG
✨ New XSS protection — all dynamic table content passes through escHtml()
🎨 UI Full redesign — Inter/JetBrains Mono, tokenised CSS, CSS corner-bracket reticles
🧪 Tests 36 tests (was 11) — rate-limiter isolation, new endpoints, delete flows

🛠️ Tech Stack

Layer Technology
Language Python 3.8+
Web Framework Flask 3.0
Computer Vision OpenCV 4.8+ (cv2.FaceDetectorYN, cv2.FaceRecognizerSF)
DNN Models YuNet (face detection) · SFace ArcFace (biometric embedding)
Numerical NumPy
Image I/O Pillow
Frontend Vanilla HTML5 / CSS3 / ES6 JavaScript
Font Inter · JetBrains Mono (Google Fonts)
Icons Lucide Icons
Testing pytest
Containerisation Docker · Docker Compose

🤝 Contributing

  1. Fork the repo
  2. Create a feature branch: git checkout -b feat/your-feature
  3. Make changes and add tests
  4. Run pytest tests/ -v — all 36 must pass
  5. Open a pull request

👤 Author

Nikhil Kumar Bheda
GitHub: @bhedanikhilkumar-code
Email: bhedanikhilkumar@gmail.com


📄 License

Distributed under the MIT License. See LICENSE for details.


Made with ❤️ and a lot of cv2.imencode

⭐ Star this repo if it saved you from writing another attendance sheet

ot of `cv2.imencode`

⭐ Star this repo if it saved you from writing another attendance sheet

About

Real-time face recognition attendance system - YuNet + SFace + Anti-Spoof, Flask dashboard

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages