ML Kitの Text Recognition を試してみた話

#概要 
無事終幕した今年のGoogleIO2018ですが、自分が個人的に欲しかった「文字認識」ライブラリである**Text Recognition**というものが発表されました。

これはGoogleがiOS/Android向けのSDKとして発表した[**ML Kit**](https://firebase.google.com/docs/ml-kit/?authuser=0)という機械学習がかんたんにできるライブラリ群の様なもので、他にも以下の様なものが含まれています。

* [**Text Recognition**](https://firebase.google.com/docs/ml-kit/recognize-text?authuser=0)　
* [**Face Detection**](https://firebase.google.com/docs/ml-kit/detect-faces?authuser=0) 
* [**Barcode Scanning**](https://firebase.google.com/docs/ml-kit/read-barcodes?authuser=0) 
* [**Image Labeling**](https://firebase.google.com/docs/ml-kit/label-images?authuser=0) 
* [**Landmark Recognition**](https://firebase.google.com/docs/ml-kit/recognize-landmarks?authuser=0) 

それぞれ今まで僕らただのエンジニアができなかった
機械学習をかんたんに実践できるようにするためのライブラリのようです。

これらすべてが**Firebase**のサービスに統合され、Firebaseのクラウド情報を使ったりして機械学習をしていくようです。

# [Text Recognition](https://firebase.google.com/docs/ml-kit/android/recognize-text?authuser=0)

静止画像・動画から、文字列情報を取得し、独自モデル形式で返却してくれるモジュール

オフラインモデルと、Firebaseのクラウドに接続してより精度の高い文字認識を行うものの２種類がありますが、
クラウドベースモデルは**Blaze plan**の利用が必須なのと、**Cloud Vision API**の利用登録が必要なので、今回はオフラインモデルで実施します。

また、本記事は公式のリファレンスをただなぞっただけになります。独自性のかけらもないのでリファレンス読める方はそちらを見たほうが絶対いい←

## How to USE

### 1. Firebaseアカウントの登録とサービスの利用

先述の通り、ML Kit自体が全てFirebaseの１サービスとなりました。
よって、Firebaseでのアカウントの作成、アプリの追加をする必要があります。

やり方は[公式](https://firebase.google.com/docs/android/setup?authuser=0)が一番わかりやすいのでこちらを参照

### 2. build.gradleへの追加

ML Kitの利用宣言をアプリ配下のbuild.gradleに追加します。

```groovy:app/build.gradle
dependencies {
  implementation 'com.google.firebase:firebase-ml-vision:15.0.0'
}
```

### 3. meta dataの追加

AndroidManifestに以下のテキストを貼り付けます。

```xml:AndroidManifest.xml
<meta-data
    android:name="com.google.firebase.ml.vision.DEPENDENCIES"
    android:value="text" />
<!-- To use multiple models: android:value="text,model2,model3" -->
```

### 4. text detectorの起動

何種類か画像・動画を読み込む方法がありますが、今回は端末に保存されている画像を使ってbitmap変換したものを利用します。

```java
val image = FirebaseVisionImage.fromBitmap(1bitmap)
```

### 5. FirebaseVisionTextDetectorの作成

```java
val detector = FirebaseVision.getInstance().visionTextDetector
```

### 6. 文字の解析

上で作った画像変換インスタンス、文字変換インスタンスを用いて実際に文字列情報に変換します。
また、変換に成功した場合、テキスト情報が配列のように格納された**FirebaseVisionText**というモデルで返却されます。

```java
detector.detectInImage(image)
    .addOnSuccessListener {

        // Task completed successfully
        // itがFirebaseVisionText
        Toast.makeText(applicationContext, "correct!!", Toast.LENGTH_SHORT).show()
    }
    .addOnFailureListener {

        // Task failed with an exception
        Toast.makeText(applicationContext, "failure...", Toast.LENGTH_SHORT).show()
    }
```

### 7. 必要な文字列の抽出

変換完了時のFirebaseVisionTextに含まれる**blocks**という箇所に解析された文字列情報が返却されます。

また、block::lines::elements と**チャンク** / **列** / **構成要素**

といった形で返却されるのである程度の文字の塊で情報を取得することができます。

```java
for (block in visionText.blocks) {
    val text = block.text

    for (line in block.lines) {
        // 列ごとに表示
        Log.d("▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲", line.text)
        for (element in line.elements) {
            // 構成要素ごとに表示
        }
    }
}
```

### 8. おわり

おわりました。あっけないですねしかももちろんものによると思いますが読み込みがめちゃくちゃ速い！

## 賞味期限を読み取ってみる

使い方はかんたんでも、実際のモデルが無いとイメージがつかないですよね。
我が家はいつも食材を大量に買ってきて長期保管、月に１，２度程度しか買い物に出かけないので、
食材が賞味期限切れになってしまう・・・なんてことがザラにあります←（ちゃんとして

そこで冷蔵庫に入れる前に写真を撮ってそこから自動入力できるようなアプリを作ってみました（今回は読み込みまで）

実際にこんな画像を読み込みました（電話番号はかくした）

![syoumikigen.png](https://qiita-image-store.s3.amazonaws.com/0/63740/4eec35d8-e17f-6c06-179a-3686019357ef.png)![error]()


これをlinesでそれぞれ読み込んでみた実行結果がこちら

```
2018-05-11 15:36:06.487 D/▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲: O 0120-XXXXXX
2018-05-11 15:36:06.488 D/▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲: 2019. 07/ACD
```

英数字は問題なく読み込まれていますね！



ちなみに、日本語の対応はまだのようです。（やってみたけどひどかった）

#　まとめ
それでもやっぱり無料で使える文字認識APIってのはやはり魅力的ですね！

<img width="875" alt="スクリーンショット 2018-05-11 15.43.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/63740/9ef41d50-a4f7-1a81-4235-829f463a8439.png">

使い方はたったこれだけ！？ってぐらいかんたんだし、
読み込みの実行速度もEcho dotのパッケージ程度なら1秒もかかりませんでしたし、

**最高かよGoogle**

今度はカメラプレビューでのキャプチャや**iOSにも同じSDKが提供されている**ので、
そちらでも試してみたいですね。

ゆくゆくは冷蔵庫のへりにカメラを常駐させて、そこで読み取ってFirebaseクラウドに保存するとかもやってみたいです。

それでは!!