sprintfacedetection
Fast, native face detection for Flutter applications powered by Google ML Kit (Android) and Apple Vision (iOS).
Features
- ⚡ High Performance Native Stream Analysis: Directly processes
CameraImagevideo stream frames in Kotlin (Android) and Swift (iOS) with minimal bridge overhead. - 👤 Facial Attributes & Landmarks: Extracts head pose angles (Pitch, Yaw, Roll), eye openness (left/right), smile probability, and mouth openness.
- 💡 Luminance Detection: Calculates real-time ambient lighting levels directly from image buffers.
- 🖼️ File Face Detection: Analyzes static image files (
detectFaceInImageFile) using native platform ML Kit / Vision algorithms. - 🔒 Privacy-First On-Device AI: Zero network calls, 100% on-device processing.
Installation
Add sprintfacedetection to your pubspec.yaml:
dependencies:
sprintfacedetection: ^0.1.0
camera: ^0.12.1
Platform Setup
Android (android/app/src/main/AndroidManifest.xml)
Add camera permissions:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
iOS (ios/Runner/Info.plist)
Add camera usage description:
<key>NSCameraUsageDescription</key>
<string>Camera access is required for real-time face detection.</string>
Usage
1. Real-Time Camera Stream Analysis
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:sprintfacedetection/sprintfacedetection.dart';
class LiveFaceDetectionExample extends StatefulWidget {
const LiveFaceDetectionExample({super.key});
@override
State<LiveFaceDetectionExample> createState() => _LiveFaceDetectionExampleState();
}
class _LiveFaceDetectionExampleState extends State<LiveFaceDetectionExample> {
final FaceDetectionService _service = FaceDetectionService();
CameraController? _controller;
CustomFace? _detectedFace;
bool _isProcessing = false;
@override
void initState() {
super.initState();
_initCamera();
}
Future<void> _initCamera() async {
final cameras = await availableCameras();
if (cameras.isEmpty) return;
final frontCam = cameras.firstWhere(
(c) => c.lensDirection == CameraLensDirection.front,
orElse: () => cameras.first,
);
_controller = CameraController(
frontCam,
ResolutionPreset.medium,
enableAudio: false,
);
await _controller!.initialize();
_controller!.startImageStream((CameraImage image) async {
if (_isProcessing) return;
_isProcessing = true;
try {
final CustomFace? face = await _service.analyse(image, frontCam);
if (mounted) {
setState(() => _detectedFace = face);
}
} finally {
_isProcessing = false;
}
});
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_controller == null || !_controller!.value.isInitialized) {
return const Center(child: CircularProgressIndicator());
}
return Column(
children: [
Expanded(child: CameraPreview(_controller!)),
if (_detectedFace != null) ...[
Text('Face Detected! ID: ${_detectedFace!.trackingId}'),
Text('Pitch: ${_detectedFace!.headEulerAngleX?.toStringAsFixed(1)}°'),
Text('Yaw: ${_detectedFace!.headEulerAngleY?.toStringAsFixed(1)}°'),
Text('Left Eye Open: ${(_detectedFace!.leftEyeOpenProbability ?? 0) * 100}%'),
Text('Smile Probability: ${(_detectedFace!.smilingProbability ?? 0) * 100}%'),
],
],
);
}
}
2. Detect Face in Static Image File
import 'package:sprintfacedetection/sprintfacedetection.dart';
Future<void> analyzeImageFile(String filePath) async {
final service = FaceDetectionService();
final Rect? faceBoundingBox = await service.detectFaceInImageFile(filePath);
if (faceBoundingBox != null) {
print('Face detected at bounding box: $faceBoundingBox');
print('Width: ${faceBoundingBox.width}, Height: ${faceBoundingBox.height}');
} else {
print('No face found in image file.');
}
}
CustomFace Data Class
When a face is detected in a stream, analyse() returns a CustomFace object containing:
| Property | Type | Description |
|---|---|---|
trackingId |
int? |
Unique face tracking ID assigned by native ML Kit / Vision detector |
boundingBox |
Rect |
Bounding box rectangle of the detected face in image coordinates |
headEulerAngleX |
double? |
Head pitch angle (tilt up/down) in degrees |
headEulerAngleY |
double? |
Head yaw angle (turn left/right) in degrees |
headEulerAngleZ |
double? |
Head roll angle (tilt side) in degrees |
leftEyeOpenProbability |
double? |
Probability that the left eye is open ($0.0 \dots 1.0$) |
rightEyeOpenProbability |
double? |
Probability that the right eye is open ($0.0 \dots 1.0$) |
smilingProbability |
double? |
Probability that the face is smiling ($0.0 \dots 1.0$) |
mouthOpenProbability |
double? |
Probability that the mouth is open ($0.0 \dots 1.0$) |
luminance |
double? |
Average lighting level computed directly from frame buffer |
Example Project
A complete runnable example project is available in the example/ folder.