Face Detection In Flutter With MLKit And Firebase

This article is about face detection with Flutter where we use the mlkit package. First we must  import the mlkit package into the pubspec.yaml file as follows,
 
Face Detection In Flutter With MLKit And Firebase
 
After that, you must upgrade your package View-> Command Palette , type "flutter upgrade package", and this will display,:  
 
Face Detection In Flutter With MLKit And Firebase 
 
Now, create a new project in Firebase with the same name of your flutter app, you can see details in your project’s manifest.xml (if playing in android) and in the app-level build.gradle (if playing in android).
 
Face Detection In Flutter With MLKit And Firebase
 
Download file with name google-services.json in Firebase where you have created it, throw this file in path [projectname]/android/app/. We are using the selected images from the device in this program, but we can change it anytime to select from camera by altering the source in the following line.
 
And main.dart file like below,
  1. import 'package:flutter/material.dart';  
  2. import 'package:image_picker/image_picker.dart';  
  3. import 'dart:io';  
  4. import 'package:mlkit/mlkit.dart';  
  5. import 'dart:async';  
  6.   
  7. void main() => runApp(new MyApp());  
  8.   
  9. class MyApp extends StatefulWidget {  
  10.   @override  
  11.   _MyAppState createState() => new _MyAppState();  
  12. }  
  13.   
  14. class _MyAppState extends State<MyApp> {  
  15.   File _file;  
  16.   
  17.   List<VisionFace> _face = <VisionFace>[];    
  18.   
  19.   VisionFaceDetectorOptions options = new VisionFaceDetectorOptions(  
  20.       modeType: VisionFaceDetectorMode.Accurate,  
  21.       landmarkType: VisionFaceDetectorLandmark.All,  
  22.       classificationType: VisionFaceDetectorClassification.All,  
  23.       minFaceSize: 0.15,  
  24.       isTrackingEnabled: true);  
  25.   
  26.   FirebaseVisionFaceDetector detector = FirebaseVisionFaceDetector.instance;  
  27.   
  28.   @override  
  29.   initState() {  
  30.     super.initState();  
  31.   }  
  32.   
  33.   @override  
  34.   Widget build(BuildContext context) {  
  35.     return new MaterialApp(  
  36.       home: new Scaffold(  
  37.         appBar: new AppBar(  
  38.           title: new Text('Face Detection Firebase'),  
  39.         ),  
  40.         body: showBody(_file),  
  41.         floatingActionButton: new FloatingActionButton(  
  42.           onPressed: () async {  
  43.             var file = await ImagePicker.pickImage(source: ImageSource.gallery);  
  44.             setState(() {  
  45.               _file = file;  
  46.             });  
  47.   
  48.             var face =  
  49.                 await detector.detectFromBinary(_file?.readAsBytesSync(), options);  
  50.             setState(() {  
  51.               if (face == null) {  
  52.                 print('No face detected');  
  53.               } else {  
  54.                 _face = face;  
  55.               }  
  56.             });  
  57.           },  
  58.           child: new Icon(Icons.tag_faces),  
  59.         ),  
  60.       ),  
  61.     );  
  62.   }  
  63.   
  64.   Widget showBody(File file) {  
  65.     return new Container(  
  66.       child: new Stack(  
  67.         children: <Widget>[  
  68.           _buildImage(),  
  69.           _showDetails(_face),  
  70.         ],  
  71.       ),  
  72.     );  
  73.   }  
  74.   
  75.   Widget _buildImage() {  
  76.     return new SizedBox(  
  77.       height: 500.0,  
  78.       child: new Center(  
  79.         child: _file == null  
  80.             ? new Text('Select image using Floating Button...')  
  81.             : new FutureBuilder<Size>(  
  82.                 future: _getImageSize(Image.file(_file, fit: BoxFit.fitWidth)),  
  83.                 builder: (BuildContext context, AsyncSnapshot<Size> snapshot) {  
  84.                   if (snapshot.hasData) {  
  85.                     return Container(  
  86.                         foregroundDecoration:  
  87.                             TextDetectDecoration(_face, snapshot.data),  
  88.                         child: Image.file(_file, fit: BoxFit.fitWidth));  
  89.                   } else {  
  90.                     return new Text('Please wait...');  
  91.                   }  
  92.                 },  
  93.               ),  
  94.       ),  
  95.     );  
  96.   }  
  97. }  
  98.   
  99. class TextDetectDecoration extends Decoration {  
  100.   final Size _originalImageSize;  
  101.   final List<VisionFace> _texts;  
  102.   TextDetectDecoration(List<VisionFace> texts, Size originalImageSize)  
  103.       : _texts = texts,  
  104.         _originalImageSize = originalImageSize;  
  105.   
  106.   @override  
  107.   BoxPainter createBoxPainter([VoidCallback onChanged]) {  
  108.     return new _TextDetectPainter(_texts, _originalImageSize);  
  109.   }  
  110. }  
  111.   
  112. Future _getImageSize(Image image) {  
  113.   Completer<Size> completer = new Completer<Size>();  
  114.   image.image.resolve(new ImageConfiguration()).addListener(  
  115.       (ImageInfo info, bool _) => completer.complete(  
  116.           Size(info.image.width.toDouble(), info.image.height.toDouble())));  
  117.   return completer.future;  
  118. }  
  119.   
  120. Widget _showDetails(List<VisionFace> faceList) {  
  121.   if (faceList == null || faceList.length == 0) {  
  122.     return new Text('', textAlign: TextAlign.center);  
  123.   }  
  124.   return new Container(  
  125.     child: new ListView.builder(  
  126.       padding: const EdgeInsets.all(10.0),  
  127.       itemCount: faceList.length,  
  128.       itemBuilder: (context, i) {  
  129.         checkData(faceList);  
  130.         return _buildRow(  
  131.             faceList[0].hasLeftEyeOpenProbability,  
  132.             faceList[0].headEulerAngleY,  
  133.             faceList[0].headEulerAngleZ,  
  134.             faceList[0].leftEyeOpenProbability,  
  135.             faceList[0].rightEyeOpenProbability,  
  136.             faceList[0].smilingProbability,  
  137.             faceList[0].trackingID);  
  138.       },  
  139.     ),  
  140.   );  
  141. }  
  142.   
  143. //For checking and printing different variables from Firebase  
  144. void checkData(List<VisionFace> faceList) {  
  145.   final double uncomputedProb = -1.0;  
  146.   final int uncompProb = -1;  
  147.   
  148.   for (int i = 0; i < faceList.length; i++) {  
  149.     Rect bounds = faceList[i].rect;  
  150.     print('Rectangle : $bounds');  
  151.   
  152.     VisionFaceLandmark landmark =  
  153.         faceList[i].getLandmark(FaceLandmarkType.LeftEar);  
  154.   
  155.     if (landmark != null) {  
  156.       VisionPoint leftEarPos = landmark.position;  
  157.       print('Left Ear Pos : $leftEarPos');  
  158.     }  
  159.   
  160.     if (faceList[i].smilingProbability != uncomputedProb) {  
  161.       double smileProb = faceList[i].smilingProbability;  
  162.       print('Smile Prob : $smileProb');  
  163.     }  
  164.   
  165.     if (faceList[i].rightEyeOpenProbability != uncomputedProb) {  
  166.       double rightEyeOpenProb = faceList[i].rightEyeOpenProbability;  
  167.       print('RightEye Open Prob : $rightEyeOpenProb');  
  168.     }  
  169.   
  170.     if (faceList[i].trackingID != uncompProb) {  
  171.       int tID = faceList[i].trackingID;  
  172.       print('Tracking ID : $tID');  
  173.     }  
  174.   }  
  175. }  
  176.   
  177. /* 
  178.     HeadEulerY : Head is rotated to right by headEulerY degrees  
  179.     HeadEulerZ : Head is tilted sideways by headEulerZ degrees 
  180.     LeftEyeOpenProbability : left Eye Open Probability 
  181.     RightEyeOpenProbability : right Eye Open Probability 
  182.     SmilingProbability : Smiling probability 
  183.     Tracking ID : If face tracking is enabled 
  184.   */  
  185. Widget _buildRow(  
  186.     bool leftEyeProb,  
  187.     double headEulerY,  
  188.     double headEulerZ,  
  189.     double leftEyeOpenProbability,  
  190.     double rightEyeOpenProbability,  
  191.     double smileProb,  
  192.     int tID) {  
  193.   return ListTile(  
  194.     title: new Text(  
  195.       "\nLeftEyeProb: $leftEyeProb \nHeadEulerY : $headEulerY \nHeadEulerZ : $headEulerZ \nLeftEyeOpenProbability : $leftEyeOpenProbability \nRightEyeOpenProbability : $rightEyeOpenProbability \nSmileProb : $smileProb \nFaceTrackingEnabled : $tID",  
  196.     ),  
  197.     dense: true,  
  198.   );  
  199. }  
  200.   
  201. class _TextDetectPainter extends BoxPainter {  
  202.   final List<VisionFace> _faceLabels;  
  203.   final Size _originalImageSize;  
  204.   _TextDetectPainter(faceLabels, originalImageSize)  
  205.       : _faceLabels = faceLabels,  
  206.         _originalImageSize = originalImageSize;  
  207.   
  208.   @override  
  209.   void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {  
  210.     final paint = new Paint()  
  211.       ..strokeWidth = 2.0  
  212.       ..color = Colors.red  
  213.       ..style = PaintingStyle.stroke;  
  214.   
  215.     final _heightRatio = _originalImageSize.height / configuration.size.height;  
  216.     final _widthRatio = _originalImageSize.width / configuration.size.width;  
  217.     for (var faceLabel in _faceLabels) {  
  218.       final _rect = Rect.fromLTRB(  
  219.           offset.dx + faceLabel.rect.left / _widthRatio,  
  220.           offset.dy + faceLabel.rect.top / _heightRatio,  
  221.           offset.dx + faceLabel.rect.right / _widthRatio,  
  222.           offset.dy + faceLabel.rect.bottom / _heightRatio);  
  223.   
  224.       canvas.drawRect(_rect, paint);  
  225.     }  
  226.   }  

After you write the codes, run the source code which will be shown like below,
 
Face Detection In Flutter With MLKit And Firebase
 
For complete source code you can look Here.
 
Thank you for reading this article about Face Detection In Flutter With MLKit And Firebase. I hope this article is useful for you. You can visit My Github about Flutter in Here.