Skip to content

About

Flask attendance system for teachers with face recognition, RBAC and PDF/Excel exports

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Typing SVG



A teacher opens a camera, students are recognised and marked present, absentees' guardians get an email. Nobody else's data is ever reachable.

Why this exists

Roll calls burn class time, and paper registers are easy to lose and easy to fake. EduGuard AI lets a teacher register a class once, then take attendance by pointing a camera at the room, with a manual override for the cases a camera gets wrong.

The interesting engineering problem was not the face matching, it was making it safe to share one app between many teachers. Every class, student, attendance session, export and notification endpoint verifies that the logged-in teacher owns the resource before touching it, and that behaviour is covered by automated tests.

Key features

  • Teacher accounts: register / login / logout with hashed passwords (Werkzeug), username, email and password-length validation.
  • Class and student management with per-class uniqueness on student ID (UNIQUE(student_id, class_id)), so two classes can reuse roll numbers.
  • Face registration from uploaded student photos (.jpg, .jpeg, .png, .webp only); a face encoding is computed and stored with the student.
  • Camera attendance: a separate OpenCV process compares live faces against the class's stored encodings, tracks faces across frames, and writes the marked students to a results file the web app polls.
  • Manual override: toggle any student present/absent inline through /api/mark_attendance.
  • Absence notifications by email (SMTP) only for absent students who have not been notified yet; failures stay pending for retry.
  • Exports: attendance sheets and class rosters as PDF (ReportLab) or Excel (openpyxl).
  • Ownership checks on protected resources, with JSON 403 on API endpoints and flash-and-redirect on pages.
  • Self-healing database setup: single canonical instance/eduguard.db, automatic archive of a legacy root DB, and an automatic migration from a global unique student ID to the composite constraint.

Architecture

flowchart LR
    T([Teacher browser]) -->|login_required| F[Flask app<br/>routes.py]
    F --> O{Ownership check<br/>resource.teacher_id == current_user.id}
    O -- no --> D[403 / redirect with message]
    O -- yes --> DB[(SQLite<br/>instance/eduguard.db)]
    F -->|start_face_detection| P[[Separate process<br/>helpers.py: OpenCV + face_recognition]]
    P -->|reads student encodings| DB
    P -->|marked_students JSON in temp dir| R[/results file/]
    F -->|polls check_face_detection_results| R
    F -->|absent + not yet notified| M[SMTP email]
    F --> X[PDF / Excel export]
Loading

Data model: Teacher 1-N Class 1-N Student; Attendance (one per class and date) 1-N AttendanceRecord (student, present flag, notification_sent).

Design decisions and trade-offs

Decision Why Trade-off
Ownership check on every resource route (class, student, attendance, exports, notifications, detection) A teacher must never read or change another teacher's data, even by guessing IDs Repeated per route; a shared decorator or query scoping would reduce repetition
Camera loop runs in a separate process, results via a JSON file Keeps the Flask request thread free and isolates the OpenCV window and heavy model work Local-machine design (opens a desktop window), not a cloud-hosted camera pipeline
hog detector, frame skipping, 0.25 downscale for detection (helpers.py defaults) Real-time performance on ordinary laptops, with a cnn option available Lower accuracy on small or angled faces than a GPU CNN
Distance threshold 0.6 for matching against registered encodings, best match wins Standard face_recognition tolerance; picks the closest registered student Not a security control; the manual toggle exists for misses
Email only for absent and unsent records; failed sends stay pending Prevents duplicate mails and allows safe retry Requires SMTP credentials; skipped safely when unset
Composite (student_id, class_id) uniqueness with startup migration Real schools reuse roll numbers across classes SQLite table-rebuild migration is hand-written rather than using Alembic
Tests stub out face_recognition (tests/conftest.py) The suite runs without dlib or a camera, so it works in CI Face matching itself is not covered by tests

Tech stack

Layer Technology
Backend Flask, Flask-Login, Flask-SQLAlchemy
Database SQLite
Vision OpenCV, face_recognition (dlib), NumPy
Reports ReportLab (PDF), openpyxl (Excel)
Frontend Jinja templates, Bootstrap 5, vanilla JavaScript
Testing pytest

Setup

Prerequisite: face-recognition needs dlib, which needs CMake and a C++ toolchain to build on most machines.

git clone https://github.com/tchxm/EduGuard-AI.git
cd EduGuard-AI
python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
python run.py

App URL: http://127.0.0.1:5000

Environment variables

Set in .env (see .env.example):

Variable Purpose
SECRET_KEY Flask session signing key. Change it; a development default is used if unset.
EMAIL_HOST / EMAIL_PORT SMTP server (defaults smtp.gmail.com / 587)
EMAIL_USER / EMAIL_PASSWORD SMTP login (for Gmail, use an app password)
EMAIL_FROM Sender address

If email variables are missing, notification attempts are skipped safely.

Database

  • Single source of truth: instance/eduguard.db.
  • A legacy root eduGuard.db is migrated or archived automatically on startup when present.

Tests

The suite in tests/ has 8 tests in 3 files:

File Covers
test_auth.py Login redirect for anonymous users, invalid credentials, successful login
test_permissions.py 403 for a non-owner marking attendance, owner can update a record, cross-teacher blocks on class view, add / edit / delete student
test_notifications.py Emails only for absent and unsent students; failed sends stay pending
pytest -q

All 8 tests pass. face_recognition is stubbed in tests/conftest.py, so no camera or dlib install is needed to run them (face matching itself is not covered).

Screenshots

  • TODO: Login / register page
  • TODO: Teacher dashboard with classes
  • TODO: Live camera window recognising students
  • TODO: Attendance sheet with manual toggles and notification status
  • TODO: Exported PDF / Excel sample (with dummy data)

Project structure

app.py            app factory, DB path + legacy migration, face-detection process launcher
routes.py         all HTTP routes, ownership checks, email, PDF/Excel export
models.py         Teacher, Class, Student, Attendance, AttendanceRecord
helpers.py        OpenCV + face_recognition attendance process (run as a script)
run.py            entry point (0.0.0.0:5000)
templates/        Jinja pages    static/   CSS and (git-ignored) uploaded dataset
tests/            pytest suite

Roadmap

  • Factor the repeated ownership checks into a decorator or scoped queries
  • Added scipy to requirements.txt and dropped the unused twilio pin
  • Test coverage for exports and the face-matching path
  • SMS notifications
  • Liveness / anti-spoofing (a detect_liveness stub exists but is disabled by default)
  • Dockerfile and CI workflow running pytest

Built by

Mohammed Afnan, AI/ML student at REVA University. GitHub · Portfolio · LinkedIn

Licensed under MIT.

About

Flask attendance system for teachers with face recognition, RBAC and PDF/Excel exports

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages