Intelligent Technology's Technical Blog

株式会社インテリジェントテクノロジーの技術情報ブログです。

Flutter と Firebase と Google ML Kit

こんにちは。中山です。
前回の「 こんなときどうする?Flutter でモバイルアプリ開発 」に続きまして、今回は、Flutter と Firebase を連携して、Flutter アプリから、Google の機械学習ライブラリである「 Google ML Kit 」の機能を利用してみたいと思います。


目次:

 

準備

 
Flutter と Firebase を連携して利用するための手順については、公式の Codelab にある「 Firebase for Flutter 」を参考にしました。(この Codelab では、Firebase のデータベース機能を使うための手順を説明していますが、今回のような ML Kit を利用するパターンでも、同様に参考となるでしょう。)

Flutter の開発環境の構築と、Firebase のアカウント作成までは実施済み、という前提で、以下の 4つの操作を進めます。(以降の各準備操作についても、詳細は、上記 Codelab もご参考になさってください。)
 

準備1 Flutter アプリプロジェクトの作成

まずは Flutter アプリのプロジェクトを作成します。今回は Android Studio を使って、「 ml_kit_lesson 」という名前でプロジェクトを作成しました。

 f:id:IntelligentTechnology:20180926144829p:plain:w540
 

準備2 Firebase プロジェクトの作成

Firebase のコンソールページを開いて、Firebase に新しくプロジェクトを登録します。今回は「 ml kit lesson 」という名前で作成しました。

 f:id:IntelligentTechnology:20180926153119p:plain:w320

なお今回は、ML Kit のうちの「 Cloud Vision APIs 」を利用する、という想定で、Firebase の利用プランは、従量課金制の「 Blaze 」プランを選択しています。

 f:id:IntelligentTechnology:20180926150407p:plain:w540

ただし、この「 Blaze 」プランであっても、ある程度の利用までは無料枠として用意されているようですので、お試しで触る程度でしたら、無料の範囲内で利用できるでしょう。
 

準備3 Firebase を iOS アプリから利用するための設定

Firebase のコンソールページを開いて、まず iOS アプリの情報を設定します。

 f:id:IntelligentTechnology:20180926151248p:plain:w360

アプリの登録後、生成された「 GoogleService-info.plist 」をダウンロードし、Xcode のビュー上にドラッグ&ドロップします。( 「 Runner/Runner/ 」ディレクトリ内にドラッグ&ドロップします。)

 f:id:IntelligentTechnology:20180926154630p:plain:w400

Firebase コンソールに表示される、以降の手順( Firebase SDK のインストールなど)は、ここではすべてスキップします。
 

準備4 Firebase を Android アプリから利用するための設定

Firebase のコンソールページを開いて、同様に Android アプリの情報を設定します。

 f:id:IntelligentTechnology:20180926155548p:plain:w360

アプリの登録後、生成された「 google-service.json 」をダウンロードし、Android 用のプロジェクトディレクトリ内の「 app 」ディレクトリに配置します。

 f:id:IntelligentTechnology:20180926155815p:plain:w400

Firebase コンソールに表示される、以降の手順( Firebase SDK のインストールなど)は、ここではすべてスキップします。

また、Android プラットフォーム固有の設定として、Flutter アプリプロジェクトディレクトリ内の
android/build.gradle 」ファイルに
classpath 'com.google.gms:google-services:3.2.1' 」の設定を追加し、

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
        classpath 'com.google.gms:google-services:3.2.1'
    }
}

android/app/build.gradle 」ファイルの末尾に、
apply plugin: 'com.google.gms.google-services' 」を追記します。

apply plugin: 'com.google.gms.google-services'

 

以上で、Flutter アプリと Firebase を連携するための準備が整いました。
 

プラグインを使う

 
Flutter アプリから Firebase の ML Kit の機能を利用するために、専用のプラグイン「 firebase_ml_vision 」が用意されていました。これを用いて、ML Kit の機能を試すことにします。
 

pubspec.yaml の設定

まずは、Flutter アプリプロジェクトディレクトリ内の「 pubspec.yaml 」ファイルの「 dependencies 」ブロックの部分に、以下のように「 firebase_ml_vision 」の記述を追加します。
またあわせて「 image_picker 」の設定も追記します。

dependencies:
  flutter:
    sdk: flutter
  firebase_ml_vision: ^0.1.2
  image_picker: ^0.4.5

 

Flutter アプリ側のコードは、今回は「 firebase_ml_vision 」プラグインの「 Example 」ページにあるコードをそのまま使うことにします。
こちらのコードで、Flutter アプリのプロジェクト内の、「 lib/main.dart 」ファイルのコードをそのまま置き換えます。

 f:id:IntelligentTechnology:20180926172935p:plain:w520
 

さらに、同じく example にある、「 detector_painters.dart 」ファイルを取得して、main.dart と同じ「 lib 」ディレクトリに配置します。

 f:id:IntelligentTechnology:20180926173405p:plain:w520
 

Anroid プラットフォーム固有の設定

Flutter アプリプロジェクトディレクトリ内の
android/app/src/main/AndroidManifest.xml 」ファイルに、
以下のように「 <meta-data> 」のブロックを追加します。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ・・・
    <application
        ・・・
        <meta-data
            android:name="com.google.firebase.ml.vision.DEPENDENCIES"
            android:value="ocr,label,barcode,face" />
    </application>
</manifest>

 

実行

ここまでできたところで、Android 実機でアプリを実行しようとしたのですが、今回試した環境では以下のようなビルドエラーが出ました。

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:preDebugBuild'.
> Android dependency 'com.android.support:support-v4' 
    has different version for the compile (26.1.0) 
    and runtime (27.1.1) classpath. 
    You should manually set the same version via DependencyResolution

このため、以下を参考にして、
firebase - Android dependency 'com.android.support:support-v4' has different version - Stack Overflow

Flutter アプリプロジェクトディレクトリ内の「 android/build.gradle 」ファイルに以下のように追記しました。

subprojects {
    project.evaluationDependsOn(':app')

    project.configurations.all {
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.android.support'
                    && !details.requested.name.contains('multidex')) {
                details.useVersion "27.1.1"
            }
        }
    }
}

 

Android 実機で実行した結果がこちら:

 f:id:IntelligentTechnology:20180927154630p:plain:w320
 

右上のメニューから「Detect Label 」を選択して、右下のボタンから写真を選んで指定すると、

 f:id:IntelligentTechnology:20180927154946p:plain:w320
 
このように、「 Dog 」または「 Pet 」と認識されました。
 

実際に画像認識の処理を呼び出しているのは、「 lib/main.dart 」ファイルのこのあたり。

  Future<void> _scanImage(File imageFile) async {
    setState(() {
      _scanResults = null;
    });

    final FirebaseVisionImage visionImage =
    FirebaseVisionImage.fromFile(imageFile);

    FirebaseVisionDetector detector;
    switch (_currentDetector) {
      case Detector.barcode:
        detector = FirebaseVision.instance.barcodeDetector();
        break;
      case Detector.face:
        detector = FirebaseVision.instance.faceDetector();
        break;
      case Detector.label:
        detector = FirebaseVision.instance.labelDetector();
        break;
      case Detector.text:
        detector = FirebaseVision.instance.textDetector();
        break;
      default:
        return;
    }

    final List<dynamic> results =
        await detector.detectInImage(visionImage) ?? <dynamic>[];

    setState(() {
      _scanResults = results;
    });
  }
  1. FirebaseVisionImage.fromFile 」で画像の情報を取得して、
  2. FirebaseVision.instance.labelDetector 」で、画像認識処理用のオブジェクトを取得して、
  3. detector.detectInImage 」で、実際に画像認識・解析処理を実行する、

という流れのようです。
 

しかしながら、この「 firebase_ml_vision 」プラグインの元のソースの、このあたりを見てみますと、
plugins/label_detector.dart at master · flutter/plugins · GitHub

実は上記の実装のように「 labelDetector 」を用いている場合は、画像認識の処理自体はローカル側で完結する、「 On Device 」ML Kit API を利用している、ということのようでした。
一方、Firebase のクラウド環境にアクセスして画像認識処理を行う「 Cloud 」ML Kit API は、より精度の高い解析が行える、とのことです。(参考

すでに最新のプラグインのソースでは、「 CloudLabelDetector 」という、「 Cloud 」API を用いて画像認識する(であろう)クラスが用意されていたのですが、これはまだ正式なプラグインの機能としては提供されていないようでした。

近日中に、この「 firebase_ml_vision 」プラグイン自体もアップデートされると思われますので、その際にはあらためて、ML Kit の「 Cloud 」API を利用するパターンも試してみたいと思います。
 

まとめ

 
結局のところは、今回は Firebase の機能を間接的に利用した、という形ではありましたが、用意されているプラグインを用いることで、最小限のコードで、複雑な処理が実装できることがわかりました。
Flutter 自体が、まだまだ発展途上の部分もありそうですが、これによってもたらされる開発のスピード感は、非常に魅力的なものになっていくのだろう、と感じました。