Offline-first biometric attendance for NHAI highway worksites
National Highways Authority of India Β· Hackathon 7.0 Β· Datalake 3.0 Ready
π Full Demo Page Β Β·Β π₯ Download APK Β Β·Β π§ Training Notebook Β Β·Β π Model Details Β Β·Β β¨ All Features
| Command Centre | Face Enrolment | Analytics Dashboard |
|---|---|---|
![]() |
![]() |
![]() |
| Live KPIs Β· Quick actions | CNN embed Β· BioHash protect | Security metrics Β· 7-day trend |
| Attendance | Calendar | Worker Registry |
|---|---|---|
![]() |
![]() |
![]() |
| Check-in / check-out | Monthly attendance view | Enrolled worker roster |
| Auth History | Admin Console | System Settings |
|---|---|---|
![]() |
![]() |
![]() |
| Filterable auth log | 2FA protected controls | Full configuration |
NHAI manages 50,000+ construction workers across remote highway stretches with little or no connectivity. Marking attendance reliably β and proving who was actually on-site β is hard:
- π Paper registers are tampered with β proxy punching is widespread
- π Cloud biometric APIs are useless without a signal
- π No way to prove a worker is physically at the correct site
- βοΈ No enforcement of safety gear (helmet, hi-vis vest) at entry
A fully offline Android app that solves all four problems at once:
Face detected β 3 liveness challenges β anti-spoof check β CNN match (99.28% LFW)
β GPS geofence check β PPE compliance check β attendance logged β sync to Datalake 3.0
Everything runs on-device. No server. No internet. No cloud. Works in the most remote highway stretch in India.
We did not use an off-the-shelf API. We trained MobileFaceNet + ArcFace from scratch.
| Metric | Our Result | Hackathon Constraint | Verdict |
|---|---|---|---|
| LFW 10-fold Accuracy | 99.28% | > 95% | β +4.28% above requirement |
| Model Size (INT8) | 1.15 MB | < 20 MB | β 17Γ smaller than limit |
| CPU Latency/Face | 63 ms | < 1000 ms | β 16Γ faster than limit |
| Self-trained | MobileFaceNet + ArcFace | Required | β 100% custom |
| Setting | Value |
|---|---|
| Dataset | CASIA-WebFace β 490,623 images / 10,572 identities |
| Backbone | MobileFaceNet (~1.0 M params, 128-D embedding) |
| Loss | ArcFace (s=64, m=0.50) |
| Optimizer | SGD momentum=0.9, wd=5e-4 + warmup + cosine LR |
| Precision | AMP mixed fp16 |
| Hardware | Kaggle Tesla T4 GPU |
| Best checkpoint | Epoch 36 β 99.28% LFW |
| Training time | ~6.6 hours |
| Export | PyTorch β ONNX FP32 β dynamic INT8 (parity-checked) |
π Full training curve (click to expand)
| Epoch | LFW Acc | Epoch | LFW Acc | |
|---|---|---|---|---|
| 1 | 85.90% | 20 | 98.18% | |
| 2 | 94.47% | 24 | 98.57% | |
| 4 | 96.43% | 28 | 98.83% | |
| 7 | 97.22% | 31 | 99.07% | |
| 10 | 97.78% | 33 | 99.13% | |
| 12 | 98.07% | 36 | 99.28% β BEST | |
| 17 | 98.47% | 40 | 99.15% |
On-device resilience: the app runs the ONNX FP32 model with an eye-aligned geometric landmark fallback β recognition works on every Android phone, even those whose ONNX runtime lacks the quantized operator set.
π Reproduce it yourself: FaceAuthApp/notebook/mobilefacenet_training.ipynb β open on Kaggle, attach CASIA-WebFace, set GPU T4, Run All.
π¦ Trained weights: FaceAuthApp/artifacts/ β mobilefacenet_fp32.pt Β· mobilefacenet_fp32.onnx Β· mobilefacenet_int8.onnx
π§ Face Recognition & Matching
- Custom MobileFaceNet CNN β 128-D L2-normalised embeddings, 99.28% LFW
- Eye-aligned ArcFace 112Γ112 similarity transform (matches training exactly)
- Cosine similarity matching with method-adaptive thresholds (CNN: 0.42, geometric: 0.80)
- Duplicate enrolment detection β blocks re-registration of the same person
- Geometric landmark fallback β eye-aligned, pose/scale invariant, runs on every device
ποΈ Liveness + Anti-Spoofing (3-layer)
- Layer 1: Active liveness β 3 randomized challenges (blink / smile / head-turn)
- Baseline-relative head-turn detection β works at any camera angle
- Live progress bar guides the user in real time
- Randomized order every session β defeats pre-recorded video attacks
- Layer 2: Passive anti-spoof β Laplacian-variance texture analysis (native Kotlin, <10 ms)
- Printed photos and phone screens blocked before matching begins
- Layer 3: Face classification quality β eye-open probability + smile probability gating
π Privacy & Security
- BioHash (ISO/IEC 24745) β raw face embedding never stored, cancellable templates
- AES-256-GCM encryption at rest for all biometric data
- 3-attempt lockout + 30 s cooldown against brute-force
- GDPR-style data retention with automatic purge of expired records
- Aadhaar Verhoeff checksum validation + masked display (
XXXX XXXX 1234)
π Field Features
- GPS Geofencing β Haversine distance vs configured site radius; check-in outside the site fails
- PPE Compliance β helmet + hi-vis vest detection gates site entry (configurable: warn or hard-block)
- Offline-first sync β all writes to encrypted local store; background push to Datalake 3.0 with exponential-backoff retry
- Live analytics β liveness pass rate, match confidence, spoof blocks, geofence compliance, 7-day trend
- Hindi / English voice prompts (TTS) + high-contrast outdoor UI
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β React Native 0.85 (Hermes, New Arch) β
β Home Β· Enrol Β· Authenticate Β· PPE Β· Dashboard Β· Admin Β· β¦ β
βββββββββββββββββββ¬βββββββββββββββββββββββββββββββ¬ββββββββββββββββ
β β
ββββββββββββββΌβββββββββββββ ββββββββββββββΌβββββββββββββββ
β Kotlin Native Module β β TypeScript Services β
β FaceProcessor β β embeddingUtils (cosine) β
β β’ ML Kit async detect β β bioHash (ISO/IEC 24745) β
β β’ MobileFaceNet FP32 β β encryption (AES-256-GCM) β
β β’ Eye-aligned crop β β geofencing Β· ppeDetection β
β β’ Laplacian anti-spoof β β syncService Β· datalake β
β β’ Geometric fallback β β adaptiveThreshold Β· i18n β
ββββββββββββββ¬βββββββββββββ ββββββββββββββ¬βββββββββββββββ
β β
ββββββββββββββΌβββββββββββββββββββββββββββββββΌβββββββββββββββ
β Encrypted local store (AsyncStorage + AES-256-GCM) β
β Background sync β NHAI Datalake 3.0 API β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
End-to-end pipeline latency: 300β500 ms (capture 50ms + detect 100ms + embed 63ms + match <10ms + record <50ms)
| Threat | Attack | Mitigation | Status |
|---|---|---|---|
| Photo spoof | Printed photo to camera | Laplacian-variance texture (native Kotlin) | β |
| Screen replay | Video on another phone | Laplacian flat-texture detection + liveness | β |
| Pre-recorded video | Video with correct moves | Randomized 3-of-4 challenge order | β |
| Proxy attendance | Person A for person B | CNN recognition 99.28% + liveness | β |
| Location fraud | Remote / GPS spoof | Haversine geofence vs site boundary | β |
| Duplicate enrolment | Re-register same person | Cosine similarity β₯ 0.55 rejection | β |
| Device theft | Physical access | AES-256-GCM encrypted store + lockout | β |
| Biometric extraction | Steal template | BioHash ISO/IEC 24745 β raw never stored | β |
| Brute force | Repeated attempts | 3-attempt lockout + 30 s cooldown | β |
| Record tampering | Edit attendance | Server-timestamp validation + audit trail | β |
| Capability | β NHAI Face Auth | β Typical Systems |
|---|---|---|
| Offline operation | Full offline β every feature on-device | Requires connectivity |
| Recognition model | Self-trained 99.28% LFW, 1.15 MB | Cloud API or 10β50 MB models |
| Template protection | BioHash ISO/IEC 24745 β raw never stored | Raw embedding stored |
| Liveness | 3 randomized challenges + passive anti-spoof | Single factor or none |
| Device coverage | CNN + geometric fallback β every phone | Fails on unsupported ops |
| Safety gate | GPS geofence + PPE helmet/vest check | Attendance only |
| Privacy | ISO/IEC 24745, AES-256, GDPR retention | Varies / none |
| Identity | Aadhaar Verhoeff + masked display | Not integrated |
| Analytics | Live on-device dashboard β works offline | Cloud only |
import { FaceAuthModule } from './FaceAuthApp/src/services/datalakeIntegration';
// One call: face auth + liveness + geofence + attendance + sync
const result = await FaceAuthModule.markAttendance(imagePath);
// result.authenticated β true / false
// result.withinGeofence β true / false
// result.attendanceAction β "CHECKED IN" / "CHECKED OUT"
// result.matchScore β 0.0 β 1.0
// result.livenessPassed β true / false
// result.bioHashVerified β true / false
// Background sync when online
await FaceAuthModule.syncToServer();REST API endpoints: POST /enroll Β· POST /auth/verify Β· POST /attendance/sync Β· GET /sites Β· POST /ppe/report Β· GET /models/latest
# Download from GitHub Releases, then:
adb install -r NHAI-FaceAuth.apk
# Open app β Enrol New Worker β Scan & Authenticategit clone https://github.com/Eartherai/FaceAuthApp.git
cd FaceAuthApp/FaceAuthApp
npm install
cd android && ./gradlew assembleDebug
# β android/app/build/outputs/apk/debug/app-debug.apkPrerequisites: Node β₯ 18, JDK 17, Android SDK 35 + NDK (via Android Studio)
1. Open FaceAuthApp/notebook/mobilefacenet_training.ipynb on Kaggle
2. Attach CASIA-WebFace .rec dataset
3. Settings β Accelerator β GPU T4
4. Run All β exports fp32.pt / fp32.onnx / int8.onnx + constraints check
cd FaceAuthApp
npx jest # bioHash, embeddings, qualityGate, Aadhaar, retryPolicyβ¦
npx tsc --noEmit # TypeScript type-checknhai-face-auth/
βββ README.md β you are here
βββ LICENSE (MIT)
βββ docs/ GitHub Pages site
β βββ index.html full interactive demo page
β βββ nhai_logo.png
β βββ screenshots/ 9 app screenshots
β βββ MODEL.md model training deep-dive
β βββ FEATURES.md complete feature notes
β βββ ARCHITECTURE.md system design
β βββ SECURITY.md threat model
β βββ BUILD.md reproducible build guide
βββ FaceAuthApp/ React Native application
β βββ src/
β β βββ screens/ 12 screens (Home, Enrol, Auth, PPEβ¦)
β β βββ services/ bioHash Β· encryption Β· geofencing Β· syncβ¦
β βββ android/
β β βββ app/src/main/java/β¦/
β β βββ FaceProcessorModule.kt Kotlin: ML Kit + ONNX + anti-spoof
β βββ notebook/
β β βββ mobilefacenet_training.ipynb full Kaggle training notebook
β βββ artifacts/
β β βββ mobilefacenet_fp32.pt PyTorch checkpoint
β β βββ mobilefacenet_fp32.onnx FP32 ONNX (4.0 MB)
β β βββ mobilefacenet_int8.onnx INT8 ONNX (1.15 MB) β used on device
β βββ __tests__/ unit tests
β βββ TECHNICAL_DOCUMENT.md full technical reference
βββ presentation/
βββ NHAI_FaceAuth_FINAL.pptx hackathon pitch deck
| Layer | Technology |
|---|---|
| Framework | React Native 0.85, New Architecture, Hermes |
| Camera | VisionCamera v5.0.11 |
| Face Detection | Google ML Kit (offline, bundled) |
| Recognition Model | Custom MobileFaceNet + ArcFace (self-trained) |
| ML Runtime | ONNX Runtime Android 1.18 |
| Native Module | Kotlin (FaceProcessorModule) |
| Encryption | AES-256-GCM |
| Storage | AsyncStorage (encrypted) |
| Navigation | React Navigation 7 |
| Language | TypeScript 5.8 |
| Training | PyTorch 2.x, ONNX, scikit-learn |
| Platform | Android 7.0+ (API 24), Target API 35 |
| Document | Description |
|---|---|
| π Full Demo Page | Interactive site: every feature, model details, architecture, comparison |
| π MODEL.md | Training setup, architecture, results, reproduction, integration |
| β¨ FEATURES.md | Every feature, how it works, why it matters, criterion map |
| ποΈ ARCHITECTURE.md | Pipeline, modules, data flow, performance budget |
| π‘οΈ SECURITY.md | Full threat model, mitigations, privacy guarantees |
| π¨ BUILD.md | Prerequisites, clean build, run, test, troubleshooting |
| π TECHNICAL_DOCUMENT.md | Complete technical reference |
| π§ Training Notebook | Kaggle notebook: train β evaluate β export |








