Contents — 27 sections
Project Overview
Attendance by face — recognising who is present from a camera, with liveness checks that defeat a held-up photo, logged automatically.
Face-recognition attendance removes even the tap of a card: you simply look at the camera and your presence is recorded. It is genuinely useful — hands-free, hard to forget, and convenient — but it carries a danger the tap never did, which is that a face can be spoofed with a photo: hold up a printed picture or a phone showing someone's face and a naïve system will happily mark them present. So this project builds face-recognition attendance with the thing that makes it trustworthy — liveness detection — recognising who is present while checking that it is a real, live person, not a photo.
Recognition works by turning a face into a numeric embedding — a vector that captures a person's facial features — and comparing it to enrolled embeddings: if a new face's embedding is close enough to an enrolled one, it is a match. Enrolment stores one embedding per person; at attendance time the camera detects a face, computes its embedding, finds the nearest enrolled match within a threshold, and logs the person. Liveness sits in front of this: before trusting a recognition, the system verifies the face is live — via a challenge (blink, turn, smile), texture/depth analysis that distinguishes skin from a flat print, or motion cues — so a static photo is rejected.
The value is convenient, automatic, spoof-resistant attendance for offices, schools and secure entry. It is honest that this is a sensitive technology: face data is biometric personal data demanding consent, security and careful governance; recognition has real bias and error risks (accuracy can vary across demographics and must be validated); and liveness is an arms race (basic checks stop photos but sophisticated spoofs need stronger defences). Deployed responsibly, though, it delivers the real thing — hands-free attendance that knows who is present and refuses to be fooled by a picture — while being clear-eyed about the privacy and fairness obligations that come with recognising faces.
What this project does
- Recognises enrolled people from a camera to record attendance
- Turns faces into embeddings and matches to enrolled identities
- Checks liveness so a held-up photo is rejected
- Logs timestamped attendance automatically
- Enrols people from reference images
- Works hands-free for offices, schools, secure entry
- Handles face data as sensitive biometric personal data
Real-World Applications
| Setting | How it is used |
|---|---|
| Workplace attendance | Hands-free staff check-in with spoof resistance. |
| School / exam attendance | Automatic, hard-to-fake presence recording. |
| Secure access | Face-plus-liveness gating for entry. |
| Event check-in | Fast recognition of enrolled attendees. |
Deployment contexts where a build of this kind earns its keep.
Features & Capabilities
- Face detection + embedding + matching
- Anti-spoofing liveness detection
- Enrolment and identity management
- Timestamped attendance logging
- Match-threshold tuning (accept/reject)
- Privacy/security-conscious design
- Honest about bias, error and the liveness arms race
Difficulty, Time & Required Skills
| Attribute | Value |
|---|---|
| Difficulty level | Advanced |
| Estimated completion time | 14–22 hours |
| Indicative build cost | Software + camera; compute-dependent |
| Primary discipline | Computer Vision |
| Reference platform | Jetson/Pi (edge) or GPU workstation |
Skills you should have (or will pick up)
- Face detection and embedding (recognition) models
- Embedding matching and threshold tuning
- Liveness / anti-spoofing techniques
- Enrolment and identity data handling
- Biometric privacy, security and bias awareness
Bill of Materials
Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.
| Component | Key specification | Qty | Approx. cost |
|---|---|---|---|
| Raspberry Pi Camera Module 3 Pi 5 uses a narrower 22-pin CSI cable — the old 15-pin ribbon will not fit. | 12 MP IMX708, autofocus, HDR, 1080p50, CSI-2 ribbon | 1 | ₹2,600 |
| Raspberry Pi 4 Model B (4 GB) Use an official 5 V 3 A supply — brown-outs from phone chargers corrupt SD cards. | Quad-core Cortex-A72 @ 1.8 GHz, 4 GB LPDDR4, Gigabit Ethernet, Wi-Fi 5, BT 5.0, 2× USB 3.0, 40-pin GPIO | 1 | ₹5,800 |
| Camera (+ IR/depth ideal) Depth/IR helps anti-spoofing | RGB camera; IR/depth strengthens liveness | 1 | ₹1,800 |
| Edge/GPU compute | Jetson/Pi for edge, or GPU for training | 1 | — |
| Recognition model | Pretrained face-embedding model | 1 | — |
| Secure store Biometric data — protect it | Encrypted store for embeddings + logs | 1 | — |
Estimated total: ₹10,200, excluding tools, shipping and consumables.
Tools and consumables
- Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
- Digital multimeter — continuity, DC volts and current ranges
- Wire strippers, flush cutters and a small set of precision screwdrivers
- Heat-shrink tubing and a heat gun (or a lighter, carefully)
- A laptop with a USB port and the toolchain listed above
Hardware Specifications
| Part | Specification | Supply | Interface | Reference |
|---|---|---|---|---|
| Raspberry Pi Camera Module 3 | 12 MP IMX708, autofocus, HDR, 1080p50, CSI-2 ribbon | 3.3 V via CSI | CSI-2 | Datasheet |
| Raspberry Pi 4 Model B (4 GB) | Quad-core Cortex-A72 @ 1.8 GHz, 4 GB LPDDR4, Gigabit Ethernet, Wi-Fi 5, BT 5.0, 2× USB 3.0, 40-pin GPIO | 5 V / 3 A USB-C | GPIO, SPI, I²C, UART, CSI, DSI | Datasheet |
Consolidated electrical and interface specifications for every active part in the build.
Power Budget & Supply Sizing
Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.
| Load | Supply rail | Typical current (mA) | Notes |
|---|---|---|---|
| Raspberry Pi Camera Module 3 | 3.3 V via CSI | 250 | Pi 5 uses a narrower 22-pin CSI cable — the old 15-pin ribbon will not fit. |
| Raspberry Pi 4 Model B (4 GB) | 5 V / 3 A USB-C | 1200 | Use an official 5 V 3 A supply — brown-outs from phone chargers corrupt SD cards. |
Summed typical draw is 1450 mA. With a 1.5× design margin the supply should deliver at least 2200 mA continuously at the stated rail voltage.
Software Requirements & Development Environment
Reference toolchain: Python 3.11 + face-recognition / PyTorch. Anything newer normally works; anything older may lack the board definitions used here.
- Flash Raspberry Pi OS (64-bit) with Raspberry Pi Imager; pre-configure Wi-Fi, hostname and SSH in the Imager settings so the board comes up headless.
- Update first:
sudo apt update && sudo apt full-upgrade -y, then reboot. - Work inside a virtual environment —
python3 -m venv ~/venv && source ~/venv/bin/activate. Bookworm blocks system-widepip installby design. - Enable the buses you need with
sudo raspi-config→ Interface Options (I²C, SPI, Serial, Camera). - Develop over VS Code Remote-SSH so you edit on your laptop but run on the Pi.
Required libraries
| Library | Why it is needed | Install |
|---|---|---|
| Python 3.11+ | Runtime for the analysis, training and service code. | sudo apt install python3 python3-venv python3-pip |
| OpenCV 4.10+ | Frame capture, colour conversion, drawing and classical CV operators. | pip install opencv-python |
| PyTorch 2.4+ | Model definition, autograd and GPU training. | pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 |
| NumPy 1.26+ | Vectorised array maths underpinning every other library here. | pip install numpy |
| SQLite 3.45+ | Zero-configuration embedded database for local logs. | Bundled with Python (`import sqlite3`) |
Block Diagram
The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.
Circuit Diagram & Wiring
The "wiring" is the recognition data flow — a camera feeds faces to detection, embedding and liveness; a match within threshold on a live face produces a logged attendance record.
| Peripheral | Peripheral pin | Controller pin | Signal |
|---|---|---|---|
| Camera | frames | — | Face images |
| Liveness check | gate | — | Real vs photo |
| Embedding match | compare | — | Identity (threshold) |
| Attendance log | record | — | Who + when |
Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.
Wiring explanation
- The camera provides face images; an IR/depth camera strengthens liveness.
- Liveness gates recognition — verify a live person before trusting a match.
- Compute an embedding and match to enrolled identities within a threshold.
- Log a timestamped attendance record on a live, matched face.
- Store embeddings and logs securely — they are biometric personal data.
System Architecture
Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.
Working Principle
Face recognition for attendance is attractive because it is frictionless and hard to forget — you cannot leave your face at home — but its convenience hides a specific vulnerability that defines the whole design: a camera cannot, on its own, tell a real face from a photograph of that face. Hold up a printout or a phone screen and a recognition-only system marks the pictured person present. This "presentation attack" is the central threat, so a trustworthy system is not a recogniser bolted to a log — it is a recogniser gated by liveness. Getting that gate right is what separates a demo from something an organisation can rely on.
The recognition itself works through embeddings. A face-recognition network maps a face image to a compact numeric vector — an embedding — engineered so that images of the same person land close together in the vector space and different people land far apart. Enrolment stores one (or a few) embeddings per person. At attendance time, a detected face is embedded and compared, by distance, to the enrolled set; if the nearest enrolled embedding is within a match threshold, the person is identified. That threshold is a genuine trade-off: too loose and it confuses similar-looking people (false accepts); too tight and it rejects genuine users on an off day (false rejects). Recognition, then, is fundamentally a nearest-neighbour comparison in an embedding space, with a tunable acceptance radius.
Liveness detection is the defence, and it comes in escalating strengths. Challenge-response asks the user to do something a photo cannot — blink, turn the head, smile — and verifies it happened. Passive methods analyse the image itself for the tell-tales of a spoof: a printed photo lacks skin texture and micro-motion, has flat depth (an IR or depth camera sees a face as 3-D and a photo as flat), and shows print/screen artefacts. Stronger systems combine several cues. The key design principle is ordering: liveness must gate recognition — verify a live person first, and only then trust the identity — because recognising a photo perfectly is worthless if the system then acts on it.
What makes this project honest — and what any responsible deployment must foreground — is that face recognition is a sensitive technology with obligations the card-tap version never had. A face embedding is biometric personal data: it must be collected with consent, stored securely (encrypted, access-controlled — a leaked biometric cannot be reissued like a password), and governed carefully, often under specific legal regimes. Recognition also carries real fairness and accuracy risks: models can perform unevenly across demographic groups if trained on unrepresentative data, so accuracy must be validated across the actual population, not assumed. And liveness is an arms race — basic checks defeat casual photo spoofs, but sophisticated attacks (high-quality masks, replayed video) need stronger, evolving defences, so no liveness check should be treated as final. Built with those responsibilities in front — liveness gating recognition, embeddings matched within a validated threshold, biometric data protected, and bias actively checked — it delivers exactly what face attendance promises: convenient, automatic, spoof-resistant presence recording that knows who is there and refuses to be fooled by a picture.
The maths behind it
Recognition by embedding distance
embed(face) → vector v
match = argmin_i distance(v, enrolled_i)
accept if distance(v, enrolled_match) ≤ THRESHOLD
Same person → close; different → far. Threshold sets the
false-accept vs false-reject trade-off.
Liveness gate (order matters)
if NOT live(face): reject (photo/spoof) # FIRST
else if recognised(face): log attendance
else: unknown
Recognising a photo perfectly is worthless — verify a live
person BEFORE trusting the identity.
Error trade-off
loose threshold → more false accepts (wrong person in)
tight threshold → more false rejects (genuine user out)
Choose per risk; VALIDATE FAR/FRR across the real
population (bias can differ by group).
Program Flowchart
The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.
Assembly Instructions
Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.
Set up detection, embedding and enrolment
Detect and align faces, compute embeddings with a pretrained model, and enrol people from consented reference images into a secure store.
Add liveness as the gate
Verify a live person before trusting recognition — challenge (blink/turn), texture/depth, or combined cues — so a photo is rejected.
Match, log and tune
Match embeddings within a threshold, log attendance, and tune the threshold/liveness strictness for your risk and population.
Step-by-Step Implementation Guide
Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.
Gate on liveness, then recognise
Reject spoofs with liveness first, then match the face embedding to enrolled identities within a threshold and log the person.
pythonrecognise.pyimport numpy as np THRESHOLD = 0.6 def attend(frame, enrolled, embed, is_live): face = detect_and_align(frame) if face is None: return None if not is_live(face, frame): # LIVENESS gates recognition return "spoof_rejected" # a photo never gets past here v = embed(face) # embedding name, dist = min(((n, np.linalg.norm(v - e)) for n, e in enrolled.items()), key=lambda x: x[1]) return name if dist <= THRESHOLD else "unknown" # within radius = matchif not is_live(face, frame): # LIVENESS gates recognitionLiveness runs first and gates everything — a held-up photo is rejected before recognition is even trusted.v = embed(face) # embeddingThe face becomes a numeric vector engineered so the same person's faces are close and different people far apart.name, dist = min(((n, np.linalg.norm(v - e))Recognition is a nearest-neighbour search over enrolled embeddings — the closest identity by distance.return name if dist <= THRESHOLD else "unknown" # within radius = matchOnly a match inside the acceptance radius is trusted; the threshold sets the false-accept vs false-reject trade-off.Log securely and validate fairness
Record timestamped attendance to an encrypted store, and validate false-accept/false-reject rates across your population before trusting the system.
Complete Source Code
The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.
#!/usr/bin/env python3
"""
Face Recognition Attendance (with liveness)
Recognises enrolled people from a camera by matching face embeddings
within a threshold, GATED BY LIVENESS so a photo/video spoof is
rejected. Logs timestamped attendance. Face embeddings are biometric
personal data — consent, encryption, governance, and fairness required.
"""
import numpy as np, time
THRESHOLD = 0.6 # match radius (model-specific)
class FaceAttendance:
def __init__(self, embed, is_live, store):
self.embed = embed # face -> vector
self.is_live = is_live # liveness check
self.store = store # encrypted enrolments + logs
def enrol(self, name, images): # consented reference images
vecs = [self.embed(detect_and_align(im)) for im in images]
self.store.save_embedding(name, np.mean(vecs, axis=0)) # encrypted
def attend(self, frame):
face = detect_and_align(frame)
if face is None:
return None
if not self.is_live(face, frame): # LIVENESS FIRST
return "spoof_rejected" # photo/video never passes
v = self.embed(face)
name, dist = self.store.nearest(v) # nearest enrolled identity
if dist <= THRESHOLD: # within acceptance radius
self.store.log(name, time.time()) # timestamped attendance
return name
return "unknown" # no confident match
if __name__ == "__main__":
fa = FaceAttendance(embed_model, liveness_check, SecureStore())
for frame in camera(): # live
result = fa.attend(frame)
# result: a name (logged), "spoof_rejected", "unknown", or None
# Validate FAR/FRR across demographics before trusting in production.
Configuration & Calibration
Configuration steps
- Configure the embedding model, match threshold and liveness method/strictness.
- Configure enrolment (consented images) and the encrypted store.
- Configure attendance logging and retention.
- Configure fairness validation across your population.
Calibration procedure
An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.
Match threshold
Tune to balance false accepts (wrong person) vs false rejects (genuine user), per your risk.
Liveness
Verify photos/replays are rejected; balance strictness against user friction.
Fairness
Measure FAR/FRR across demographic groups; address large gaps before deployment.
Dataset, Model & Training
Dataset
Recognition uses a face-embedding model (often pretrained on large face datasets); enrolment provides reference images per person.
Liveness models/heuristics use real-vs-spoof samples (prints, screens, masks). Representative data across demographics is essential for fair accuracy.
| Dataset | Size | Licence | Use here |
|---|---|---|---|
| Face-embedding pretraining | Large (many identities) | Varies (check terms) | Base recognition embeddings |
| Enrolment images | Few per person | With consent | Enrol identities |
| Liveness / anti-spoof set | Real vs spoof | Varies | Train/validate liveness |
| Demographic validation set | Representative | With consent | Check bias/accuracy fairness |
Data preprocessing
- Detect and align the face (crop, normalise pose/scale) before embedding.
- Quality-gate frames (blur, lighting, occlusion) — bad inputs cause errors.
- For liveness, gather challenge responses or texture/depth cues.
| Layer / stage | Shape or configuration | Purpose |
|---|---|---|
| Detector | face detection + alignment | Find/normalise the face |
| Liveness | challenge / texture / depth | Reject photo/video spoofs |
| Embedding net | face → vector | Compact identity representation |
| Matcher | nearest neighbour + threshold | Identify enrolled person |
| Store | encrypted embeddings + logs | Protect biometric data |
Hyperparameters
| Hyperparameter | Value | Why |
|---|---|---|
| Match threshold | model-specific | False accept vs false reject |
| Liveness strictness | app-specific | Spoof resistance vs friction |
| Embedding dim | ≈ 128–512 | Model-defined identity vector |
| Enrol images/person | ≈ 1–5 | Robustness to pose/lighting |
Training process
- Use a pretrained embedding model; enrol by computing per-person embeddings (no full retraining needed).
- Train/tune liveness on real-vs-spoof samples; combine cues for strength.
- Validate false-accept/false-reject rates across demographics — do not assume uniform accuracy.
Evaluation, Metrics & Deployment
The key metrics are recognition error rates (false accept / false reject), liveness spoof-rejection, and — critically — fairness of accuracy across demographic groups.
| Metric | Value | What it tells you |
|---|---|---|
| False accept rate (FAR) | low (target) | Wrong person accepted |
| False reject rate (FRR) | low (target) | Genuine user rejected |
| Spoof rejection | high (target) | Photos/videos blocked |
| Fairness (by group) | validated | No large accuracy gaps |
Figures from the reference training run described above — reproduce them before trusting your own changes.
Inference example
import numpy as np
THRESHOLD = 0.6 # match radius (model-specific)
def recognise_and_log(frame, enrolled, embed, is_live, log):
face = detect_and_align(frame)
if face is None:
return None
if not is_live(face, frame): # LIVENESS FIRST — reject photo/video
return "spoof_rejected"
v = embed(face) # face -> embedding vector
# nearest enrolled identity by distance
name, dist = min(((n, np.linalg.norm(v - e)) for n, e in enrolled.items()),
key=lambda x: x[1])
if dist <= THRESHOLD: # within acceptance radius
log.record(name, now()) # timestamped attendance
return name
return "unknown" # no confident match
# NOTE: embeddings + logs are biometric personal data — store encrypted.
Testing Procedure & Expected Output
Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.
| Test | What you should see |
|---|---|
| Enrolled person looks at camera | Recognised and logged |
| Hold up a printed photo | Rejected by liveness |
| Replay a video of a face | Rejected (stronger liveness) — note arms race |
| Unenrolled person | "unknown" — not logged |
| Vary lighting/pose | Still recognised if enrolled well |
| Check group accuracy | No large FAR/FRR gaps across groups |
Bench-test checklist. If a row fails, stop and fix it before moving on.
Expected output
Automatic attendance for recognised live people, with spoof rejection and secure logging.
{
"name": "A. Verma",
"time": "2026-07-28T09:03:41",
"liveness": "passed",
"match_distance": 0.42,
"result": "present"
}
A. Verma was recognised as a live person (liveness passed, comfortable match distance) and logged present — a held-up photo would have been rejected before recognition was trusted.
Troubleshooting: Common Errors & Fixes
Performance Optimisation
- Gate recognition on liveness — verify a live person first.
- Tune the match threshold for your false-accept/false-reject risk.
- Combine liveness cues against stronger spoofs.
- Validate accuracy fairness across the real population.
- Pin the hot loop to one core with
tasksetand leave the others free for the OS. - Prefer MJPEG over raw YUY2 when capturing from USB cameras — the decode cost is far lower than the USB bandwidth cost.
- Log to a tmpfs RAM disk and flush to the SD card once a minute; per-sample SD writes are what kills cards.
- Run the service under
systemdwithRestart=alwaysso a crash never means a dead deployment. - Profile before optimising — print
micros()deltas around each stage and fix the slowest one first.
Safety Precautions
- Face embeddings are biometric personal data — consent, encryption, access control and governed retention are mandatory (a leaked biometric cannot be reissued).
- Validate accuracy across demographics; an unfair recogniser is unacceptable.
- Liveness is an arms race — do not treat any check as final; layer defences.
- Provide a fallback and human recourse for false rejects.
- Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
- Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
- Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.
Maintenance
- Re-validate FAR/FRR and fairness periodically and after model changes.
- Update enrolments as appearances change; manage joiners/leavers.
- Strengthen liveness as new spoofs emerge.
- Audit access to biometric data and logs.
- Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
- Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
- Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.
Future Improvements & Upgrades
A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.
- Add depth/IR cameras for stronger passive liveness.
- Add multi-frame/temporal liveness against video replay.
- Add on-device recognition so faces never leave the unit.
- Add a second factor for high-security contexts.
- Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
- Add connectivity — an ESP32 and an MQTT publish turn a local gadget into something you can graph, alert on and analyse over months.
- Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
- Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
- Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
- Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.
Frequently Asked Questions
References & Learning Resources
These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.
- Facial recognition systemReference
- Face embeddings (metric learning)Reference
- Liveness / presentation-attack detectionReference
- Biometric data protectionReference
- Bias in face recognitionReference