All articles

Learn

Build a face recognition attendance system (student project guide)

The most-built student project, done right: voluntary check-in, real code, and the ethics tutorials skip.

By SightRadar EngineeringUpdated 11 min read Markdown

TL;DR

A face-recognition attendance system is three steps: enrol each participant's face once, recognise faces at check-in, and log the name + timestamp. This guide builds it with a hosted API (no GPU or model downloads) and points to the local library if you want to learn the ML. Crucially, it's framed as a voluntary class/club project: get consent, offer a non-face fallback, keep retention short, and don't repurpose it to monitor people — the part most tutorials skip.

Note: Read this first. Attendance-by-face is fine as a consented class/club project, but it becomes surveillance the moment it's imposed on people who can't say no — employees, or students required to submit their face. Keep it opt-in, always offer a manual check-in alternative, tell participants how long you keep their data, and delete it when the project ends. Don't build this to monitor a workplace.

How it works (three steps)

  1. Enrol — each participant opts in and you index one clear photo of their face, tagged with their name/id.
  2. Check in — at the session, a webcam or uploaded photo is searched against the enrolled collection.
  3. Log — a match writes name + timestamp to a CSV or database; no match asks them to try again or check in manually.
import os, csv, datetime, requests
BASE = "https://api.sightradar.com"
H = {"Authorization": f"Bearer {os.environ['SR_API_KEY']}"}
COLLECTION = "cs101_section_a"

def setup():
    requests.post(f"{BASE}/v1/collections", headers=H,
                  json={"collection_id": COLLECTION})

def enrol(student_id, name, photo_url):
    # only call this after the student has opted in
    r = requests.post(f"{BASE}/v1/collections/{COLLECTION}/index", headers=H,
                      json={"url": photo_url, "photoId": student_id})
    r.raise_for_status()
    print(f"enrolled {name} ({student_id})")
Create the collection once, then index one photo per consenting participant.

Step 2 — Recognise at check-in

def check_in(photo_url):
    r = requests.post(f"{BASE}/v1/collections/{COLLECTION}/search", headers=H,
                      json={"url": photo_url, "limit": 1})
    r.raise_for_status()
    data = r.json()
    if data.get("reason"):                 # e.g. no_face — ask for a clearer photo
        return None, "No face detected — try again or check in manually."
    matches = data.get("matches", [])
    if not matches:
        return None, "Not recognised — check in manually."
    m = matches[0]
    return m["photo_id"], f"Welcome, {m['photo_id']} (score {m['score']:.2f})"
Search the enrolled collection with the check-in photo.

Tip: The score is on a 0-1 scale. For attendance you want a fairly strict cutoff so you don't mark the wrong person present — but always keep a manual fallback for a genuine near-miss. See choosing a face-match threshold for how to pick the number on your own enrolled photos.

Step 3 — Log attendance

def log_attendance(student_id):
    with open("attendance.csv", "a", newline="") as f:
        csv.writer(f).writerow([student_id, datetime.datetime.now().isoformat()])

# tie it together
photo_id, msg = check_in("https://example.com/checkin.jpg")
print(msg)
if photo_id:
    log_attendance(photo_id)
Append name + timestamp to a CSV (swap for a DB in a bigger project).

Make it a great project (not just working code)

  • Handle the edge cases — no face, multiple faces in frame, a low-confidence near-match. Graders love seeing these handled, not ignored.
  • Report your threshold choice — show an FMR/FNMR sweep on your enrolled photos and justify the cutoff. This is the difference between a demo and an evaluated project.
  • Add liveness awareness — note that a photo of a photo could fool it, and that real deployments add liveness. Showing you know the limitation earns marks.
  • Write the ethics section — consent, retention, deletion, and the opt-out. It's genuinely part of the work in this domain.

Want to learn the ML instead of calling an API?

If your course wants you to understand the model, build the recognition core locally with the face_recognition library (dlib) or OpenCV, then wrap it in the same enrol → check-in → log flow. See the two-way Python tutorial. If you'd rather spend your time on the app, UI, and write-up, the API path above skips the GPU and install pain.

Get a free key and enrol your first faces on trial credits.

Start the quickstart

Frequently asked questions

How do I build a face recognition attendance system in Python?

Three steps: enrol each participant by indexing one clear photo tagged with their id, recognise faces at check-in by searching the enrolled collection with a webcam or uploaded photo, and log the matched name plus a timestamp to a CSV or database. You can do the recognition with a hosted API (no GPU) or a local library like face_recognition. Always keep enrollment opt-in and offer a manual check-in fallback.

Is it ethical to build a face recognition attendance system?

As a voluntary class or club project with consent, yes. It becomes a problem when imposed on people who can't opt out — employees or students required to submit their face — which is surveillance. Keep it opt-in, always provide a non-face check-in alternative, tell participants how long you retain their data, and delete it when the project ends. Don't deploy it to monitor a workplace.

Can someone fool it with a photo?

A basic system that only matches faces can be fooled by a photo of a photo or a phone screen — that's a spoofing / presentation attack. Real deployments add liveness detection (for example, checking for a blink or subtle motion) as a separate step. For a student project, noting this limitation and how you'd address it is a strong part of the write-up.

Do I need a GPU or a big dataset for an attendance project?

No. You only need one clear enrollment photo per participant, and recognition runs fine on a CPU (or on a hosted API that does the compute for you). You don't train a model from scratch — you use a pre-trained one to compute embeddings and compare them, so no large training dataset is required.

Keep reading