main.dart
void main() => runApp(DemoApp()); class DemoApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider<FaceProvider>( create: (_) => FaceProvider(), child: MaterialApp( home: Scaffold( appBar: AppBar( title: const Text("Face detection"), ), body: const DetectionWidget(), ), ), ); } }
face_provider.dart
class FaceProvider with ChangeNotifier { bool _showDetector = false; bool get isDetectorVisible => _showDetector; void setDetectorVisible(bool isVisible) { _showDetector = isVisible; notifyListeners(); } }
face_detector_data.dart
class FaceDetectorData { final List<Face> faces; final ui.Image image; const FaceDetectorData(this.faces, this.image); }
face_detector_model.dart
class FaceDetectorModel { const FaceDetectorModel(); Future<FaceDetectorData> detectFaces() async { // Choose the image final picker = ImagePicker(); final imageFile = await picker.getImage( source: ImageSource.gallery, maxWidth: 260, maxHeight: 250, ); // Detect faces final file = File(imageFile.path); final image = FirebaseVisionImage.fromFile(file); final detector = FirebaseVision.instance.faceDetector(); // Process data final faces = await detector.processImage(image); final canvasImage = await _decodeImage(file); return FaceDetectorData(faces, canvasImage); } Future<ui.Image> _decodeImage(File file) async { final rawFile = await file.readAsBytes(); final codec = await instantiateImageCodec(rawFile); final frameInfo = await codec.getNextFrame(); return frameInfo.image; } }
rectangle_painter.dart
class RectanglePainter extends CustomPainter { final List<Face> facesPositions; final ui.Image selectedImage; static final Paint _painter = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 3.0 ..color = Colors.redAccent; const RectanglePainter({ this.facesPositions, this.selectedImage }); @override void paint(Canvas canvas, Size size) { canvas.drawImage(selectedImage, Offset.zero, Paint()); for(final face in facesPositions) { final coords = face.boundingBox; final rect = Rect.fromLTRB( coords.left, coords.top, coords.right, coords.bottom ); canvas.drawRect(rect, _painter); } } @override bool shouldRepaint(RectanglePainter oldDelegate) => selectedImage != oldDelegate.selectedImage || facesPositions != oldDelegate.facesPositions;}
face_detector_widget.dart
class DetectFacesFromImage extends StatefulWidget { const DetectFacesFromImage(); @override _DetectFacesFromImageState createState() => _DetectFacesFromImageState(); } class _DetectFacesFromImageState extends State<DetectFacesFromImage> { Future<FaceDetectorData> _faces; final _model = FaceDetectorModel(); @override void initState() { super.initState(); _faces = _model.detectFaces(); } @override Widget build(BuildContext context) { return FutureBuilder<FaceDetectorData>( future: _faces, builder: (context, facesList) { if (facesList.hasData) { final data = facesList.data; if (data != null) { return Center( child: Wrap( spacing: 10, crossAxisAlignment: WrapCrossAlignment.center, direction: Axis.vertical, children: <Widget>[ SizedBox( width: 260, height: 250, child: CustomPaint( painter: RectanglePainter( facesPositions: data.faces, selectedImage: data.image ), ), ), Consumer<FaceProvider>( builder: (context, detector, _) { return RaisedButton( child: const Text("New detection"), onPressed: () => detector.setDetectorVisible(false), ); }, ), ], ), ); } else { return const Center( child: Text("Error while processing data :("), ); } } return const Center( child: CircularProgressIndicator(), ); }, ); } }
detection_img_picker.dart
class DetectionImgPicker extends StatelessWidget { const DetectionImgPicker(); @override Widget build(BuildContext context) { return Center( child: Wrap( direction: Axis.vertical, spacing: 30, crossAxisAlignment: WrapCrossAlignment.center, children: <Widget>[ Icon(Icons.tag_faces, size: 40, color: Colors.blueAccent, ), Consumer<FaceProvider>( builder: (context, faceDetector, _) { return RaisedButton( color: Colors.green, textColor: Colors.white, child: const Text("Detect faces"), onPressed: () => faceDetector.setDetectorVisible(true), ); }, ), ], ), ); } }
detection_widget.dart
class DetectionWidget extends StatelessWidget { const DetectionWidget(); @override Widget build(BuildContext context) { return Consumer<FaceProvider>( builder: (context, faceDetector, _) { if (faceDetector.isDetectorVisible) { return const DetectFacesFromImage(); } return const DetectionImgPicker(); }, ); } }
This website and the book are not official Google products. No affiliations are involved. Built with Java 14 and Vert.X
"Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC"