human_security 0.0.2
human_security: ^0.0.2 copied to clipboard
On-device face liveness verification with ML Kit active challenges, TFLite anti-spoofing, and optional face identity matching.
human_security #
On-device face liveness verification for Flutter. Combines active ML Kit challenges (blink, smile, head turns) with passive TensorFlow Lite anti-spoofing, and optional face identity matching against a reference photo.
All inference runs locally on the device — no server calls are required for liveness or face matching (except when loading a reference image from a URL).
Features #
Active liveness (Google ML Kit) #
- Randomized challenge sequence (blink, smile, turn head left, turn head right)
- Face positioning guidance with oval overlay
- Real-time instructions and progress indicator
- Configurable number of challenges (
challengeCount, default2) - Challenge timeouts and warmup periods to reduce false negatives
- Front/back camera flip button (when multiple cameras are available)
Passive anti-spoofing (TensorFlow Lite) #
- Bundled
anti_spoof.tflitemodel — no download step required - Runs during challenge and evaluation phases with frame sampling
- JPEG capture fallback when stream-based passive scores are unavailable
- Combined active + passive scoring (
60%active,40%passive by default) - Spoof detection for photos, screens, and static replays
- Can be disabled (
enablePassiveLiveness: false) for active-only mode
Face identity matching (optional) #
- Compare live capture against a reference image using
face_embedding.tflite - Reference sources: local file, in-memory bytes, or HTTP/HTTPS URL
- Cosine similarity with configurable threshold (
matchThreshold, default0.75) - Returns a unified
FaceMatchReportwith liveness + match results
UI widget #
- Drop-in
FaceLivenessDetectorwidget with camera preview - Customizable colors, instruction text style, and progress bar
- Success callback returns captured JPEG
Fileand optionalFaceMatchReport - Failure callback with human-readable reason
- Built-in error view with retry
Lower-level APIs (exported) #
| Export | Purpose |
|---|---|
FaceLivenessDetector |
Main camera + liveness UI widget |
FaceMatchService |
Standalone face embedding comparison |
ReferenceImageSource |
File / bytes / URL reference input |
FaceMatchReport |
Combined verification result |
LivenessChallenge |
Challenge action enum |
LivenessState / LivenessStatus |
Liveness flow state |
VerificationResult |
Active + passive score breakdown |
ScoreEvaluator |
Threshold and scoring configuration |
EmbeddingMath |
Cosine similarity helpers |
Platform support #
| Platform | Support |
|---|---|
| Android | ✅ API 24+ |
| iOS | ✅ iOS 15.5+ |
| Web | ❌ |
| Desktop | ❌ |
Getting started #
1. Add dependency #
dependencies:
human_security: ^0.0.1
2. Android configuration #
android/app/src/main/AndroidManifest.xml — add permissions inside <manifest>:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
android/app/build.gradle.kts (or build.gradle) — minimum SDK and TFLite settings:
android {
defaultConfig {
minSdk = 24
}
androidResources {
// Prevent Gradle from compressing bundled .tflite assets
noCompress += "tflite"
}
}
// Pin TensorFlow Lite versions used by tflite_flutter (recommended)
configurations.all {
resolutionStrategy {
force("org.tensorflow:tensorflow-lite:2.16.1")
force("org.tensorflow:tensorflow-lite-gpu:2.16.1")
force("org.tensorflow:tensorflow-lite-api:2.16.1")
}
}
Runtime: request camera permission before showing the liveness UI (e.g. with permission_handler).
3. iOS configuration #
Minimum deployment target: iOS 15.5 (required by google_mlkit_face_detection).
ios/Podfile:
platform :ios, '15.5'
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.5'
end
end
end
ios/Runner/Info.plist — privacy usage descriptions:
<key>NSCameraUsageDescription</key>
<string>Camera access is required for face liveness verification.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is required to pick a reference face image.</string>
If you load reference images from arbitrary URLs, ensure App Transport Security allows those hosts or use HTTPS.
4. Bundled models #
The package ships two TFLite models under assets/models/:
| Asset | Role |
|---|---|
anti_spoof.tflite |
Passive liveness / anti-spoof scoring |
face_embedding.tflite |
Face embedding extraction for identity match |
These are declared in the package pubspec.yaml and loaded via default asset paths — no extra setup in your app.
Usage #
Liveness only #
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:human_security/human_security.dart';
class LivenessPage extends StatelessWidget {
const LivenessPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: FaceLivenessDetector(
onSuccess: (File image, FaceMatchReport? report) {
Navigator.pop(context);
// image = captured live selfie
// report?.livenessResult has active/passive/combined scores
},
onFailure: (String reason) {
Navigator.pop(context);
// Show reason to user
},
),
);
}
}
Liveness + face match against a reference photo #
FaceLivenessDetector(
referenceImage: ReferenceImageSource.file(referenceFile),
// or: ReferenceImageSource.url('https://example.com/id-photo.jpg')
// or: ReferenceImageSource.bytes(imageBytes)
matchThreshold: 0.75,
onSuccess: (File image, FaceMatchReport? report) {
if (report?.isVerified ?? false) {
// Same person + live face
}
},
onFailure: (String reason) {
// Liveness failed or face did not match reference
},
)
Active-only mode (no TFLite anti-spoof) #
FaceLivenessDetector(
enablePassiveLiveness: false,
onSuccess: (image, report) { /* ... */ },
onFailure: (reason) { /* ... */ },
)
Customization #
FaceLivenessDetector(
challengeCount: 3,
matchThreshold: 0.80,
backgroundColor: Colors.black,
overlayColor: const Color(0xCC000000),
progressColor: Colors.greenAccent,
showCameraFlipButton: true,
instructionTextStyle: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w600,
),
onSuccess: (image, report) { /* ... */ },
onFailure: (reason) { /* ... */ },
)
Verification flow #
flowchart TD
A[Initialize camera + models] --> B[Position face in oval]
B --> C[Active challenges]
C --> D[Passive anti-spoof collection]
D --> E{Scores pass?}
E -->|No| F[onFailure]
E -->|Yes| G[Capture photo]
G --> H{Reference image set?}
H -->|No| I[onSuccess with liveness report]
H -->|Yes| J[Compare embeddings]
J --> K{Match + live?}
K -->|Yes| I
K -->|No| F
Scoring defaults #
ScoreEvaluator defaults:
| Setting | Default | Description |
|---|---|---|
passiveThreshold |
0.5 |
Minimum average passive score to count as live |
combinedThreshold |
0.75 |
Minimum combined active + passive score |
activeWeight |
0.6 |
Weight of active challenge completion |
passiveWeight |
0.4 |
Weight of passive anti-spoof score |
strongSpoofThreshold |
0.35 |
Frames below this trigger fast spoof failure |
Face match uses matchThreshold on cosine similarity (default 0.75).
Example app #
See the example/ directory for a full demo with:
- Full liveness (active + passive)
- Active-only mode
- Optional reference image from gallery or URL
- Result screen with scores and side-by-side comparison
cd example
flutter pub get
cd ios && pod install && cd ..
flutter run
Dependencies #
camera— live camera preview and capturegoogle_mlkit_face_detection— face landmarks and active challengestflite_flutter— on-device TFLite inferenceimage— JPEG decode for passive fallbackhttp— optional reference image download
Additional information #
- Repository: github.com/ShithinCherathuparambil/human_security
- Issues: GitHub Issues
- License: MIT — see LICENSE