Flutter Face Detection App with Firebase ML Kit

Amal Khairin
6 min readDec 20, 2019

--

Apa itu Firebase ML Kit ?

ML Kit merupakan SDK yang menghadirkan Machine Learning Google untuk aplikasi Android dan iOS. ML Kit ini dapat diimplementasikan oleh orang-orang yang masih pemula maupun sudah berpengalaman dalam Machine Learning.

Untuk menggunakannya tidak perlu pengetahuan mendalam tentang Neural Network, karena ML Kit sudah menyediakan API yang membantu kita agar mudah digunakan. Jika kita sudah berpengalaman dalam Machine Learning, kita bisa menggunakan model TensorFlow Lite kita dengan custom.

Aplikasi Sederhana Pendeteksi Wajah Menggunakan Futter + ML Kit

Sebenarnya ini mirip dengan fitur yang ada dikamera smartphone sekarang ini. Fitur tersebut dapat mendeteksi wajah dari orang-orang dikamera.

Tetapi bagaimana kalau kita mencoba membuatnya sendiri? Menarik, bukan?

Oke langsung aja kita ngoding!

Alat dan bahan:

  • Visual Studio Code / Android Studio
  • Akun Firebase
  • Emulator / Smartphone (Debug Mode on)
  • Koneksi Internet lancar

Pertama, kita buat project baru di Visual Studio Code atau Android Studio, atau bisa juga menggunakan CMD.

Setelah membuat projek baru, kita tambahkan dulu aplikasi kita ke Firebase.

Buka https://firebase.google.com , kemudian login dengan akun google anda

klik Go to console, maka tampilannya akan seperti dibawah.

Klik Tambahkan project

kemudian masukkan nama project, klik lanjutkan, kemudian buat project

setelah berhasil, maka akan diarahkan ke Project overview

klik tambahkan aplikasi

pilih android

kemudian anda akan diminta untuk mengisi nama package, nama aplikasi (optional), dan sertifikat SHA-1

untuk package name, bisa ditemukan di file AndroidManifest.xml di project anda

android > app > src > main
nama package nya : com.example.mlkit_test untuk yang diatas

untuk mendapatkan sertifikat SHA-1, klik tanda tanya tersebut dan ikuti langkah-langkah yang diberikan

setelah itu, klik daftarkan aplikasi

kemudian anda akan disuruh untuk mendownload file google-services.json

setelah anda mendownload, simpan file tersebut pada android > app

android > app

kemudian tambahkan Firebase SDK (ikuti cara-cara yang ditunjukkan)

android/buld.gradle

note : ubah versi google services diatas menjadi 4.2.0

Android/app/build.gradle

setelah itu, klik berikutnya dan selesai

setelah menambahkan aplikasi anda ke Firebase, buka Main.dart

Main.dart

Kemudian Hapus semua kode tersebut, dan Ketik kode dibawah (Jangan copy paste, biasakan ngoding sendiri baris demi baris)

import ‘package:flutter/material.dart’;import ‘package:mlkit_test/ml.dart’;void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MaterialApp(      home: FaceDetectWidget()    );  }}

untuk mengatasi error tersebut, buka file pubspec.yaml

tambahkan package berikut

tambahkan dibawah cupertino_icons

kemudian tekan ctrl+s untuk melakukan get package.

setelah itu, buat file baru dengan nama ml.dart

ml.dart

kemudian didalam ml.dart, import library-library berikut

import ‘dart:async’;import ‘dart:io’;import ‘package:flutter/material.dart’;import ‘package:image_picker/image_picker.dart’;import ‘package:mlkit/mlkit.dart’;

setelah itu, buat Statefull Widget dengan cara ketik STF kemudian tekan Enter pada keyboard maka akan langsung muncul class Statefull Widget.

Beri nama Kelas tersebut FaceDetectWidget, maka akan seperti dibawah ini

ml.dart

Kemudian tambahkan variable berikut

File _file;List<VisionFace> _currentLabels = <VisionFace>[];FirebaseVisionFaceDetector detector = FirebaseVisionFaceDetector.instance;@overrideinitState() {   super.initState();}

tambahkan pada

import ‘dart:async’;...class FaceDetectWidget extends StatefulWidget {...class _FaceDetectWidgetState extends State<FaceDetectWidget> {   File _file;   List<VisionFace> _currentLabels = <VisionFace>[];FirebaseVisionFaceDetector detector = FirebaseVisionFaceDetector.instance;   @override   initState() {      super.initState();   }   @override   Widget build(BuildContext context) {      return new Container();   }}

Kemudian, ubah Widget Container tersebut menjadi MaterialApp. Ketik kode Dibawah

@overrideWidget build(BuildContext context) {
//add this line
return new MaterialApp( home: new Scaffold( appBar: new AppBar( title: new Text(‘face detect’), ), body: _buildBody(), floatingActionButton: new FloatingActionButton( onPressed: () async { try {
//image from camera
//var file = await ImagePicker.pickImage(source: ImageSource.camera);
//image from gallery
var file = await ImagePicker.pickImage(source: ImageSource.gallery); setState(() { _file = file; }); try { var currentLabels = await detector.detectFromPath(_file?.path); setState(() { _currentLabels = currentLabels; }); } catch (e) { print(e.toString()); } } catch (e) { print(e.toString()); } }, child: new Icon(Icons.camera), ), ), );}

masih dalam kelas yang sama, yaitu _FaceDetectWidget. buat method baru yang mengembalikan sebuah widget dengan nama _buildBody, dan masukkan kode dibawah

Widget _buildBody() {    return Container(        child: Column(            children: <Widget>[               _buildImage(),            ],        ),    );}

setelah itu tambahkan method baru lagi dengan nama _buildImage, dan tambahkan kode dibawah

Widget _buildImage() {    return SizedBox(        height: 500.0,        child: new Center(            child: _file == null            ? Text(‘No Image’)            : new FutureBuilder<Size>(                 future: _getImageSize(Image.file(_file, fit: BoxFit.fitWidth)),                 builder: (BuildContext context, AsyncSnapshot<Size> snapshot) {                        if (snapshot.hasData) {                            return Container(                                 foregroundDecoration: FaceDetectDecoration(_currentLabels, snapshot.data),                                 child: _imageCard());                       } else {                            return new Text(‘Detecting…’);                       }                  },            ),       ),   );}

buat lagi method dengan nama _imageCard dan tambahkan kode berikut

Widget _imageCard(){    return Card(        elevation: 5.0,        color: Colors.blue,        child: Padding(            padding: const EdgeInsets.all(5.0),            child: Container(child: Image.file(_file, fit: BoxFit.fitWidth)),        ),        shape: RoundedRectangleBorder(borderRadius:          BorderRadius.circular(20.0)),    );}

kemudian masih dalam kelas tersebut, tambahkan method berikut

Future<Size> _getImageSize(Image image) {    Completer<Size> completer = new Completer<Size>();    image.image.resolve(new ImageConfiguration()).addListener(    ImageStreamListener((ImageInfo info, bool _) => completer.complete(        Size(info.image.width.toDouble(), info.image.height.toDouble()))));    return completer.future;}

Kemudian buat class baru dibawah class tadi dengan nama FaceDetectDecoration dan extends dari Decoration, dan tambahkan kode berikut

class FaceDetectDecoration extends Decoration {    final Size _originalImageSize;    final List<VisionFace> _faces;    FaceDetectDecoration(List<VisionFace> texts, Size originalImageSize)    : _faces = texts,    _originalImageSize = originalImageSize;    @override    BoxPainter createBoxPainter([VoidCallback onChanged]) {        return new _FaceDetectPainter(_faces, _originalImageSize);    }}

setelah itu, buat lagi class baru dibawah kelas diatas dengan nama _FaceDetectPainter yang mengekstends dari BoxPainter, tambahkan kode dibawah

class _FaceDetectPainter extends BoxPainter {     final List<VisionFace> _faces;     final Size _originalImageSize;     _FaceDetectPainter(texts, originalImageSize)    : _faces = texts,    _originalImageSize = originalImageSize;    @override    void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {         final paint = new Paint()         ..strokeWidth = 2.0         ..color = Colors.red         ..style = PaintingStyle.stroke;         print(“original Image Size : ${_originalImageSize}”);         final _heightRatio = _originalImageSize.height / configuration.size.height;         final _widthRatio = _originalImageSize.width / configuration.size.width;         for (var text in _faces) {             print(“rect : ${text.rect}”);             final _rect = Rect.fromLTRB(                  offset.dx + text.rect.left / _widthRatio,                  offset.dy + text.rect.top / _heightRatio,                  offset.dx + text.rect.right / _widthRatio,                  offset.dy + text.rect.bottom / _heightRatio);                  //final _rect = Rect.fromLTRB(24.0, 115.0, 75.0, 131.2);                  print(“_rect : ${_rect}”);                  canvas.drawRect(_rect, paint);           }    print(“offset : ${offset}”);    print(“configuration : ${configuration}”);    final rect = offset & configuration.size;    print(“rect container : ${rect}”);    //canvas.drawRect(rect, paint);    canvas.restore();  }}

nah setelah itu, run project anda (jika menggunakan vscode, tekan F5 untuk debug dan pastikan sudah terkoneksi dengan emulator atau device anda)

Dan… Jadilah Aplikasinya!!

Cukup sampai disini dulu tutorialnya, next masih bakalan update tentang ML Kit dan bakalan membahas Object Labeling dengan ML Kit.

Untuk Repository project ini dapat anda download disini

Thanks 😄

--

--

Amal Khairin
Amal Khairin

No responses yet