kyc_engine 0.0.1
kyc_engine: ^0.0.1 copied to clipboard
A Flutter library for face verification and KYC processes.
KYC Engine π #
A powerful Flutter package for face verification and KYC (Know Your Customer) processes using TensorFlow Lite. Perfect for identity verification, face matching, and secure authentication systems.
β¨ Features #
- π― Face Verification - Compare two face images with high accuracy (97%+)
- π ID Verification - Verify ID card photos against live selfies
- π± On-Device ML - Privacy-first, all processing happens locally
- β‘ Fast Performance - 100-300ms inference time
- π§ Configurable - Multiple presets for different use cases
- π Secure - No data leaves the device
- π¦ Firebase Integration - Auto-download and cache ML models
- π Cross-Platform - Works on iOS and Android
πΈ Use Cases #
- KYC/Identity Verification - Verify customer identity for financial services
- Access Control - Secure building or system access
- Duplicate Detection - Find duplicate accounts or users
- Age Verification - Confirm user age matches ID
- Authentication - Face-based login systems
- Attendance Systems - Face recognition for check-in/check-out
π Quick Start #
Installation #
Add to your pubspec.yaml:
dependencies:
kyc_engine: ^0.0.1
firebase_core: ^4.2.1 # Required for model distribution
Then run:
flutter pub get
Basic Usage #
import 'package:kyc_engine/kyc_engine.dart';
import 'dart:io';
// 1. Initialize the engine
final kycEngine = KYCEngine();
await kycEngine.initialize();
// 2. Verify two faces
final result = await kycEngine.verifyFaces(
File('path/to/id_photo.jpg'),
File('path/to/selfie.jpg'),
);
// 3. Check the result
if (result.isSamePerson) {
print('β
Match! Confidence: ${result.confidencePercentage.toStringAsFixed(1)}%');
print('Similarity Score: ${result.similarityScore}');
} else {
print('β No match');
}
π Setup Guide #
1. Firebase Configuration #
Option A: Using FlutterFire CLI (Recommended)
# Install FlutterFire CLI
dart pub global activate flutterfire_cli
# Configure Firebase for your project
flutterfire configure
Option B: Manual Setup
- Go to Firebase Console
- Create a new project or select existing one
- Add your app (Android/iOS)
- Download configuration files:
- Android:
google-services.jsonβ Place inandroid/app/ - iOS:
GoogleService-Info.plistβ Place inios/Runner/
- Android:
2. Upload TFLite Model to Firebase #
- Go to Firebase Console β Machine Learning β Custom Models
- Click "Add Custom Model"
- Upload your
face_verification_model.tflitefile - Model name:
face_model(important!) - Click "Publish"
Note: For testing, you can use the default model from the example Firebase project.
3. Platform-Specific Setup #
iOS Setup
Update ios/Podfile:
platform :ios, '16.0'
Open your project in Xcode and set:
- Deployment Target β iOS 16.0
- Add
GoogleService-Info.plistto your project
Android Setup
Update android/app/build.gradle:
android {
defaultConfig {
minSdk 24 // Required for ML Kit
}
}
Add to android/build.gradle:
dependencies {
classpath 'com.google.gms:google-services:4.4.2'
}
Add to android/app/build.gradle (bottom):
apply plugin: 'com.google.gms.google-services'
4. Initialize Firebase in Your App #
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
π» API Reference #
KYCEngine #
The main class for face verification operations.
Initialization
final kycEngine = KYCEngine();
// Initialize with default configuration
await kycEngine.initialize();
// Or with custom configuration
await kycEngine.initialize(FaceDetectionConfig.accurate());
Methods
verifyFaces()
Compare two face images and get detailed results.
Future<VerificationResult> verifyFaces(
File image1,
File image2, {
double? customThreshold,
})
// Example
final result = await kycEngine.verifyFaces(
File('id.jpg'),
File('selfie.jpg'),
customThreshold: 0.6, // Optional: override default threshold
);
areSimilar()
Quick boolean check if two faces match.
Future<bool> areSimilar(File image1, File image2)
// Example
if (await kycEngine.areSimilar(photo1, photo2)) {
print('Same person!');
}
getSimilarityScore()
Get raw similarity score without threshold comparison.
Future<double> getSimilarityScore(File image1, File image2)
// Example
final score = await kycEngine.getSimilarityScore(photo1, photo2);
print('Similarity: ${(score * 100).toStringAsFixed(1)}%');
Configuration Presets #
Fast Mode
Optimized for speed with minimal accuracy trade-off.
FaceDetectionConfig.fast()
Accurate Mode (Default)
Balanced accuracy and speed.
FaceDetectionConfig.accurate()
Strict Mode
Higher threshold, fewer false positives.
FaceDetectionConfig.strict()
Lenient Mode
Lower threshold, fewer false negatives.
FaceDetectionConfig.lenient()
Custom Configuration
FaceDetectionConfig(
similarityThreshold: 0.65,
performanceMode: FaceDetectorMode.accurate,
enableLandmarks: true,
enableClassification: true,
firebaseModelName: 'custom_model_name',
)
VerificationResult #
Result object containing verification details.
Properties
class VerificationResult {
final double similarityScore; // 0.0 to 1.0
final bool isSamePerson; // Match based on threshold
final double confidencePercentage; // Similarity as percentage
final double threshold; // Threshold used
final int? processingTimeMs; // Processing time in milliseconds
}
Example Usage
final result = await kycEngine.verifyFaces(img1, img2);
print('Score: ${result.similarityScore}'); // 0.8542
print('Match: ${result.isSamePerson}'); // true
print('Confidence: ${result.confidencePercentage}'); // 85.42%
print('Time: ${result.processingTimeMs}ms'); // 245ms
π― Threshold Guidelines #
Choose the right threshold for your use case:
| Threshold | Use Case | Description |
|---|---|---|
| 0.7 - 0.8 | High Security | Banking, government ID verification |
| 0.5 - 0.7 | KYC/Standard | General identity verification |
| 0.4 - 0.5 | Social Apps | Friend tagging, duplicate detection |
| 0.3 - 0.4 | Lenient | Finding similar faces in large datasets |
Interpreting Scores #
- 0.85 - 1.0: Very high confidence - definitely same person
- 0.7 - 0.85: High confidence - likely same person
- 0.5 - 0.7: Moderate confidence - probably same person
- 0.3 - 0.5: Low confidence - uncertain
- 0.0 - 0.3: Very low - different persons
π‘οΈ Error Handling #
try {
final result = await kycEngine.verifyFaces(image1, image2);
if (result.isSamePerson) {
// Handle successful match
} else {
// Handle no match
}
} on ServiceNotInitializedException {
// Engine not initialized - call initialize() first
print('Please initialize the engine before use');
} on NoFaceDetectedException catch (e) {
// No face found in one or both images
print('No face detected: ${e.message}');
} on MultipleFacesDetectedException catch (e) {
// Multiple faces detected (only single face supported)
print('Found ${e.faceCount} faces. Please use single-face images.');
} on InvalidImageException catch (e) {
// Image file is corrupted or unreadable
print('Invalid image: ${e.message}');
} on ModelInitializationException catch (e) {
// Failed to download or load ML model
print('Model error: ${e.message}');
} on KYCException catch (e) {
// General KYC engine error
print('Error: ${e.message}');
}
π± Complete Example #
import 'package:flutter/material.dart';
import 'package:kyc_engine/kyc_engine.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
class FaceVerificationPage extends StatefulWidget {
@override
_FaceVerificationPageState createState() => _FaceVerificationPageState();
}
class _FaceVerificationPageState extends State<FaceVerificationPage> {
final KYCEngine _kycEngine = KYCEngine();
final ImagePicker _picker = ImagePicker();
File? _idPhoto;
File? _selfie;
VerificationResult? _result;
bool _isInitialized = false;
bool _isProcessing = false;
@override
void initState() {
super.initState();
_initializeEngine();
}
Future<void> _initializeEngine() async {
try {
await _kycEngine.initialize(FaceDetectionConfig.accurate());
setState(() => _isInitialized = true);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to initialize: $e')),
);
}
}
Future<void> _pickImage(bool isIdPhoto) async {
final XFile? image = await _picker.pickImage(
source: ImageSource.gallery,
maxWidth: 1024,
maxHeight: 1024,
);
if (image != null) {
setState(() {
if (isIdPhoto) {
_idPhoto = File(image.path);
} else {
_selfie = File(image.path);
}
_result = null;
});
}
}
Future<void> _verify() async {
if (_idPhoto == null || _selfie == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Please select both images')),
);
return;
}
setState(() => _isProcessing = true);
try {
final result = await _kycEngine.verifyFaces(_idPhoto!, _selfie!);
setState(() {
_result = result;
_isProcessing = false;
});
} on KYCException catch (e) {
setState(() => _isProcessing = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.message}')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Face Verification')),
body: Column(
children: [
// Image selection UI
Row(
children: [
Expanded(
child: GestureDetector(
onTap: () => _pickImage(true),
child: Container(
height: 200,
child: _idPhoto != null
? Image.file(_idPhoto!, fit: BoxFit.cover)
: Center(child: Text('Select ID Photo')),
),
),
),
Expanded(
child: GestureDetector(
onTap: () => _pickImage(false),
child: Container(
height: 200,
child: _selfie != null
? Image.file(_selfie!, fit: BoxFit.cover)
: Center(child: Text('Select Selfie')),
),
),
),
],
),
// Verify button
ElevatedButton(
onPressed: _isInitialized && !_isProcessing ? _verify : null,
child: Text(_isProcessing ? 'Processing...' : 'Verify'),
),
// Result display
if (_result != null) ...[
Text(
_result!.isSamePerson ? 'MATCH β
' : 'NO MATCH β',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: _result!.isSamePerson ? Colors.green : Colors.red,
),
),
Text('Confidence: ${_result!.confidencePercentage.toStringAsFixed(1)}%'),
],
],
),
);
}
@override
void dispose() {
_kycEngine.dispose();
super.dispose();
}
}
π Performance #
| Metric | Value |
|---|---|
| Model Size | ~27.5 MB (unquantized) |
| Inference Time | 100-300ms per comparison |
| Accuracy | 97%+ on same-person verification |
| Memory Usage | ~50-100 MB during inference |
| Supported Image Formats | JPG, PNG |
| Recommended Image Size | 512x512 to 1024x1024 pixels |
π§ Requirements #
- Flutter: β₯ 3.0.0
- Dart: β₯ 3.0.0
- iOS: β₯ 16.0
- Android: minSdk β₯ 24
- Firebase Project: Required for model distribution
- Internet: Required for initial model download
π Troubleshooting #
Model Download Fails #
Problem: Model won't download from Firebase. Solution:
- Check internet connection
- Verify Firebase project is set up correctly
- Ensure model is published in Firebase Console
- Check Firebase model name matches (default:
face_model)
No Face Detected #
Problem: Getting NoFaceDetectedException.
Solution:
- Ensure image has clear, frontal face
- Check lighting conditions
- Face should be at least 100x100 pixels
- Avoid sunglasses, masks, or heavy occlusions
Low Accuracy #
Problem: Getting incorrect matches. Solution:
- Use
FaceDetectionConfig.accurate()or.strict() - Increase similarity threshold
- Use higher quality images
- Ensure good lighting in photos
iOS Build Fails #
Problem: Platform version error. Solution:
# In ios/Podfile
platform :ios, '15.0'
Android Build Fails #
Problem: MinSdk error. Solution:
// In android/app/build.gradle
defaultConfig {
minSdk 24
}
π Example App #
A complete example app is included in the /example folder demonstrating:
- Firebase initialization
- Camera integration
- Gallery image selection
- Real-time face verification
- Error handling
- Result visualization
- Loading states
Run the example:
cd example
flutter pub get
flutter run
π€ Contributing #
Contributions are welcome! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Areas for Contribution #
- Additional face quality checks
- Liveness detection
- Support for quantized models
- Web platform support
- Additional configuration options
- Performance optimizations
- Documentation improvements
π License #
This project is licensed under the MIT License - see the LICENSE file for details.
π Acknowledgments #
Built with amazing open-source technologies:
- TensorFlow Lite - On-device ML inference
- Google ML Kit - Face detection
- Firebase ML - Model distribution
- Flutter - Cross-platform framework
π Support & Contact #
- π§ Email: ericatsu29@gmail.com
- π Issues: GitHub Issues
- π¬ Discussions: GitHub Discussions
- π Documentation: API Reference
πΊοΈ Roadmap #
v0.1.0 (Next Release) #
- β Quantized model support (reduce size to ~7MB)
- β Batch verification for multiple pairs
- β Face quality assessment
- β Custom training documentation
v0.2.0 #
- β Liveness detection
- β Face landmark visualization
- β Video frame processing
- β Web platform support
v0.3.0 #
- β Offline model bundling
- β Multi-face detection
- β Face clustering
- β Performance analytics dashboard
Built with β€οΈ by Eric Atsu
If you find this package helpful, please give it a β on GitHub!