face_recognition_engine 1.0.0
face_recognition_engine: ^1.0.0 copied to clipboard
On-device face recognition for Flutter using MobileFaceNet embeddings and cosine matching, with multi-angle enrollment storage and anti-spoofing hooks.
face_recognition_engine #
On-device face recognition for Flutter. MobileFaceNet embeddings (112×112 → 192-d) with cosine matching, guided multi-angle enrollment, liveness / anti-spoofing, and ready-made camera UI — all running locally, no server.
Two one-call flows do the heavy lifting:
FaceRecognitionKit.enroll(context)— opens a guided camera and returns the face embeddings.FaceRecognitionKit.detect(context, candidates: …)— opens a live camera, runs liveness / anti-spoof checks, and matches against embeddings you supply.
The ML Kit face detector ships with the package. The MobileFaceNet model is
not bundled — you supply your own .tflite (see
Model & license) — which keeps the package tiny and avoids
redistributing weights of uncertain provenance. Lower-level pieces are available
if you want to build your own UI.
Features #
- 📸 Ready-made camera screens — guided multi-angle enrollment + live recognition, behind two function calls.
- 🧠 Bring-your-own model — load any MobileFaceNet
.tflitefrom an asset orUint8List; nothing heavy bundled. - 🛡️ Liveness & anti-spoofing — blink / head-turn / smile challenges
(optionally randomized) plus a passive texture/CNN
SpoofDetector(BYO model). - 👥 Multi-angle enrollment — several templates per person; optional
file-backed persistence (
FaceProfileStore). - 🔍 1:N identification — match a probe against all enrolled people by best cosine similarity.
- ⚙️ One config object —
RecognitionConfigdrives both flows (thresholds, challenges, spoof gate); immutable,copyWith, JSON-serialisable.
Install #
dependencies:
face_recognition_engine: ^1.0.0
Platform setup #
This package uses the camera and TensorFlow Lite. Follow the platform setup for
camera and
tflite_flutter — most
importantly camera permissions in AndroidManifest.xml / Info.plist, and on
Android minSdkVersion 21.
Provide a model #
No model ships with the package. Add a MobileFaceNet .tflite (112×112 input →
192-d output) to your app and declare it:
flutter:
assets:
- assets/mobilefacenet.tflite
Then pass its asset key (or raw bytes) to the calls below via modelAsset:
(or modelBytes:). See Model & license for sourcing notes.
Quick start #
import 'package:face_recognition_engine/face_recognition_engine.dart';
const config = RecognitionConfig(matchThreshold: 0.8, enrollSamples: 3);
const model = 'assets/mobilefacenet.tflite'; // your bundled model
// 1. ENROLL — opens the guided camera, returns embeddings.
final enrolled =
await FaceRecognitionKit.enroll(context, config: config, modelAsset: model);
if (enrolled != null) {
final profile = FaceProfile(
id: 'alice',
name: 'Alice',
photoPath: '', // optionally persist enrolled.photoJpg
templates: enrolled.templates,
);
// Persist `profile` (e.g. with FaceProfileStore, or your own storage).
}
// 2. DETECT — opens the live camera, gates on liveness, matches a face.
final match = await FaceRecognitionKit.detect(
context,
candidates: myEnrolledProfiles, // List<FaceProfile>
config: config,
modelAsset: model,
);
if (match != null) {
print('Welcome ${match.profile.name} '
'(${(match.similarity * 100).toStringAsFixed(1)}%)');
}
Both calls return null if the user backs out (and detect also returns null
when the liveness check fails).
Persisting enrollments #
The package doesn't persist for you, but FaceProfileStore is provided if you
want a ready-made file-backed store:
final store = FaceProfileStore();
await store.load();
await store.add(profile);
// ...later: pass store.all as `candidates` to detect().
It also offers findDuplicate, mergeInto (re-enroll and cap templates),
removeById, and clear. You can persist enrolled.photoJpg yourself and set
photoPath, or call FaceProfileStore.savePhoto.
Configuring liveness & anti-spoofing #
Everything is on RecognitionConfig, passed to both flows:
const config = RecognitionConfig(
matchThreshold: 0.8,
livenessEnabled: true,
randomizeLiveness: true, // pick one challenge at random per attempt
requireBlink: true,
requireHeadTurn: false,
requireSmile: true,
livenessTimeoutSec: 20,
passiveSpoofEnabled: false, // set true + pass spoofModelAsset to detect()
);
Headless engine (build your own UI) #
If you don't want the bundled screens, drive FaceRecognizer directly:
final recognizer =
await FaceRecognizer.create(config: config, modelAsset: model);
final probe = recognizer.embedFrame(rgbFrame, faceRect); // your own detection
final result = recognizer.identify(probe, profiles);
Anti-spoofing #
Active-liveness thresholds (blink / head-turn / smile) live in
RecognitionConfig for you to drive your own UI challenges. For passive,
single-frame spoof detection, supply a TFLite model (e.g. a MiniFASNet from
Silent-Face-Anti-Spoofing) and use SpoofDetector:
final spoof = SpoofDetector(modelAsset: 'assets/antispoof.tflite');
await spoof.load(); // fails open: isAvailable == false if missing
final pLive = spoof.liveProbability(rgbFrame, faceRect); // null => skip gate
API surface #
| Type | Purpose |
|---|---|
FaceRecognitionKit |
enroll / detect — the two camera flows |
EnrollmentResult |
Captured templates + front-pose JPEG |
DetectionResult |
Matched profile + similarity |
EnrollmentScreen / DetectionScreen |
The screen widgets, for custom navigation |
FaceRecognizer |
Load model, embed frames, identify probes (headless) |
RecognitionResult |
Best match + similarity + matched flag |
FaceProfile |
One enrolled person (name, photo, templates) |
FaceProfileStore |
Persistent, file-backed enrollment store |
RecognitionConfig |
Immutable thresholds (recognition + liveness) |
SpoofDetector |
Passive texture/CNN anti-spoof (BYO model) |
FaceRecognitionUtil |
Low-level decode / crop / embed / cosine |
Notes & limitations #
- Coordinate spaces.
embedFrame/embedCameraImageexpect the faceRectin the decoded RGB frame's coordinates. Front cameras are mirrored and preview frames are often rotated — map your detector's boxes accordingly. embedCameraImageassumes upright single-plane NV21. For other formats or rotations, decode/rotate yourself and callembedFrame.- The bundled screens are deliberately simple; for full control over the camera
preview and prompts, build your own UI on top of
FaceRecognizer.
Model & license #
- The package code (everything under
lib/) is licensed under the MIT License — © 2026 Nafis Hasrat Arnob. - No model is bundled. You supply a MobileFaceNet
.tflite(112×112 input → 192-d output) yourself, which keeps this package free of weights whose redistribution terms can't be guaranteed.
Sourcing a model #
MobileFaceNet was introduced in Chen et al., "MobileFaceNets: Efficient CNNs
for Accurate Real-time Face Verification on Mobile
Devices" (2018). The architecture is free to
implement, but a pre-trained .tflite's weights carry their own license —
and many copies circulating online ship with no license at all (which, by
default, means "all rights reserved" — not safe to redistribute).
Before using a model in a product, confirm its license. Safer routes:
- Train/convert your own from a clearly-licensed implementation (e.g. an
Apache-2.0 MobileFaceNet repo) and keep its
LICENSEalongside. - Use a model you have explicit rights to.
Load it with modelAsset: (an asset key) or modelBytes: on FaceRecognitionKit
and FaceRecognizer.create.
No anti-spoofing model is bundled either — SpoofDetector is bring-your-own (a
MiniFASNet from
Silent-Face-Anti-Spoofing
is a common choice; check its license too).