MLKitのQuickstart-iOSでリアルタイムテキスト認識を動かしてみる

先日のGoogle I/O 2018で[MLKit for Firebase](https://firebase.googleblog.com/2018/05/whats-new-in-firebase-at-io-2018.html)のPublic betaが発表されました。

MLKitでは機械学習関連のAPIが提供され、iOS/Android問わずFirebaseプロジェクトをアプリに紐付ける事で利用できます。  

今のところ、テキスト認識、顔認識、バーコードスキャン、イメージのラベル付け、ランドマーク認識などのAPIが含まれていて、機能によってはオンデバイスでオフラインで処理を完結させることができます。[^1]。クラウドAPIをコールする場合はGoogle Cloud Platformのリソースを使い精度の高い結果が得られます。また高度なユースケースには独自の[TensorFlow Lite](https://www.tensorflow.org/mobile/tflite/)モデルを適用することもできます。

尚、5機能は序の口で今後も機能は追加される予定みたいです、新機能を試したい場合は[waiting list](https://docs.google.com/forms/d/1uVm49ondYFOAYniI-6FEogJDW14B5dhnrUoZ2Rjg-kA/viewform?edit_requested=true)に申請が必要です。[^2]

<img width="470" alt="スクリーンショット 2018-05-09 21.52.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/9628/ea6920b7-1dfd-0f35-c33d-0cf484b3d835.png">

今回、実際に[Quickstart-iOS](https://github.com/firebase/quickstart-ios)を動かしてみたので、その記録もしておきます。

まずはリポジトリをクローンします。

```shell
$ git clone https://github.com/firebase/quickstart-ios.git
```

mlkitのあるディレクトリまで移動して`pod install`します。

```shell
$ cd quickstart-ios/mlkit/
$ pod install
```

が下記エラーになってしまいました。

```shell

[!] CocoaPods could not find compatible versions for pod "Firebase/MLVision":
  In Podfile:
    Firebase/MLVision

None of your spec sources contain a spec satisfying the dependency: `Firebase/MLVision`.

You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * mistyped the name or version.
 * not added the source repo that hosts the Podspec to your Podfile.

Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.
```


podのリポジトリが古いようなので更新します。20分位かかった.. 

```shell

pod repo update
```
改めて`pod install`

```shell
$ pod install
```

完了したらプロジェクトをひらきます

```shell

$ open MLKitExample.xcworkspace
```

今度は、GoogleService-Info.plistがないのでエラーになってしまいました。

```
2018-05-09 20:45:02.607376+0900 MLKitExample[1444:550004] 5.0.0 - [Firebase/Core][I-COR000012] Could not locate configuration file: 'GoogleService-Info.plist'.
2018-05-09 20:45:02.607516+0900 MLKitExample[1444:550004] 5.0.0 - [Firebase/Core][I-COR000005] No app has been configured yet.
2018-05-09 20:45:02.667802+0900 MLKitExample[1444:549863] *** Terminating app due to uncaught exception 'com.firebase.core', reason: '`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find a valid GoogleService-Info.plist in your project. Please download one from https://console.firebase.google.com/.'
*** First throw call stack:
(0x1817bed8c 0x1809785ec 0x1817bec6c 0x102f4b280 0x102aa9784 0x102aa9884 0x18b38ee38 0x18b38e240 0x18b35b65c 0x18b98ba0c 0x18b35ae4c 0x18b35ace8 0x18b359b78 0x18bfef72c 0x18b359268 0x18bdd49b8 0x18bf22ae8 0x18b358c88 0x18b358624 0x18b35565c 0x18b3553ac 0x183fbc470 0x183fc4d6c 0x105381220 0x10538d850 0x183ff0878 0x183ff051c 0x183ff0ab8 0x181767404 0x181766c2c 0x18176479c 0x181684da8 0x183667020 0x18b66578c 0x102aaa11c 0x181115fc0)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 
```

GoogleService-Info.plistをダウンロードするには、Firebaseプロジェクトの追加が必要となるので、[Firebase Console](https://console.firebase.google.com)で追加します。

追加を選択して
<img width="560" alt="スクリーンショット 2018-05-09 20.57.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/9628/9286e0c9-4f6c-c696-fcce-f761118ef06c.png">

ここではMLKitSampleという名前で作成しました。 （リポジトリと合わせるとExampleの方がいいかも）
<img width="510" alt="スクリーンショット 2018-05-09 20.58.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/9628/310b4d1b-d34b-6cf6-ecf4-95afc5102fff.png">

作成したあとはiOSアプリにFirebaseを追加を選びます
<img width="1026" alt="スクリーンショット 2018-05-09 21.01.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/9628/0ffba333-78da-6410-4ff5-33697bfbacd5.png">

先程開いたMLKitExampleのXcodeプロジェクトからBundle Identifierを調べてフォームの入力を進めます。
<img width="870" alt="スクリーンショット 2018-05-09 21.04.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/9628/38cd4bbf-ed55-f026-438a-17ce2ce46365.png">

<img width="777" alt="スクリーンショット 2018-05-09 21.01.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/9628/6094e76f-41f2-1190-6373-31919f4db692.png">

終わったらGoogleService-Info.plistをダウンロードして、Xcodeにドラッグアンドドロップで追加します。そして再度Runするとサンプルが試せます。

Google AIブログをリアルタイムでテキスト認識させてみましたが。かなり高い精度かつ高速に認識できています。他にも顔認識やラベリングなど色々なサンプルが入っています。（ちなみに日本語はまだ上手く認識できませんでした）
![タイトルなし.gif](https://qiita-image-store.s3.amazonaws.com/0/9628/42de7076-d0d5-bda4-3b54-d74a57bceeaf.gif)

コードをみると数行でこれらの機能が実現できことがわかります。すごすぎる。

```
  // Detect text in a CMSampleBuffer by converting to a UIImage to determine orientation
  func detectText(in buffer: CMSampleBuffer, completion: @escaping (_ text: String, _ image: UIImage) -> Void) {
    if let image = buffer.toUIImage() {
      let viImage = image.toVisionImage()
      textDetector.detect(in: viImage) { (visionText, error) in
        completion(self.flattenVisionText(visionText: visionText), image)
      }
    }
  }
```

個人的に気になるのはCore MLとの機能の比較ですが、多くのアプリはiOS/Android両方対応する必要がある点と、精度の高さやFirebaseとシームレスに統合されている点などからMLKitに大きく優位性があると思います。

[^1]: 2018/05/09時点ではLandmark recognitionはクラウドベースのAPIしかありません。
[^2]: MLKitの機能だけでなくiOS用の[Firebase Test Lab](https://firebase.google.com/docs/test-lab/)のプレビューも提供しているようです。