ENGINEER BLOG

ENGINEER BLOG

FirebaseのML Kitで文字認識をいろいろ試してみた

こんにちは。コンサルティングサービス本部の野村です。

今回はGoogleのFirebaseで提供されているML Kitを使って、
いろいろな文字認識を試してみたいと思います。


ML Kitはトレーニング済みのモデルデータを使用し、より容易に機械学習をモバイル向けの開発に
組み込めるよう提供されているサービスで、BaseAPIとして次のような機能が提供されています。

  • 画像分類
  • 文字認識
  • 顔検出
  • バーコードスキャン
  • ランドマーク認識

また、クイックスタートのSampleアプリが提供されているため、
簡単にそれらの機能を試すことができます。

blog20190215_01
blog20190215_02

が、
文字認識の場合、なんとなく認識されてそうなことはわかりますが、
認識結果が元の文字に白字でオーバーレイされて表示されるため、文字数が多くなるとわかりづらくなってきます。

ということで、選択画像から認識結果をTextViewに表示するAndroidアプリを作ってみたいと思います。

デフォルトアプリの準備

まずはボタンを押したら画像データを選択し、Bitmapオブジェクトにセットするというだけのシンプルなアプリを準備します。

public class MainActivity extends AppCompatActivity {
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bt_sl = findViewById(R.id.button);
        textView = findViewById(R.id.textView);
        bt_sl.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent, 0);
            }
        });
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0) {
            if (resultCode == Activity.RESULT_OK) {
                ContentResolver contentResolver = getContentResolver();
                InputStream inputStream = null;
                try {
                    inputStream = contentResolver.openInputStream(data.getData());
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //ここからMLKitの処理を追記
            }
        }
    }
}

FirebaseのML Kitプロジェクトを作成

次に、FirebaseのML Kitプロジェクトを作成します。

Firebase consoleにGoogleアカウントでログイン(新規の人は作成)し、新規プロジェクトを追加します。


blog20190215_11

プロジェクト名を入力、地域を選択し、「プロジェクトを作成」をクリックします。


blog20190215_12

今回は、Android用のアプリを追加します。


blog20190215_13

適当なAndroidパッケージ名を入力し、アプリを登録します。


blog20190215_14

google-services.jsonをダウンロードし、指定の位置に配置します。


blog20190215_15

ここからは、リファレンスガイドに沿ってアプリを修正していきましょう。
今回は、文字認識にCloud APIおよびドキュメントテキスト認識APIを利用したいので、それらを満たすために必要最低限の変更のみ加えていきます。

Firebaseの準備

まずは、AndroidプロジェクトにFirebaseを追加するため、
ルートレベルのbuild.gradle(app_name/build.gradle)にビルドルールを追記します。

buildscript {
    // ...
    dependencies {
        // ...
        classpath 'com.google.gms:google-services:4.1.0' // google-services plugin
    }
}

次に、アプリレベルのbuild.gradle(app_name/app/build.gradle)にapply pluginを追加して、Gradleプラグインを有効化しつつ、MLKitの依存関係を追記します。

dependencies {
  // ...
  implementation 'com.google.firebase:firebase-core:16.0.4'
  implementation 'com.google.firebase:firebase-ml-vision:18.0.2'
}
// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'

Cloud Vision APIの有効化

今回はCloud APIを利用するので、Cloud Vision APIを有効化しましょう。

Firebase consoleにて、Firebaseの利用プランをSpark(無料)プランから、Blaze(従量制)プランへ変更します。


blog20190215_16

Google cloud consoleから
Cloud Vision APIを有効にします。


blog20190215_17

テキスト認識機能を実行する

ここからは最初に準備したデフォルトアプリを修正していきます。

画像選択で得たBitmapオブジェクトからFirebaseVisionImageオブジェクトを作成します。

FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

FirebaseVisionDocumentTextRecognizer のインスタンスを取得します。

FirebaseVisionDocumentTextRecognizer detector = FirebaseVision.getInstance()
        .getCloudDocumentTextRecognizer();

最後に、画像を processImage メソッドに渡します。

detector.processImage(image)
        .addOnSuccessListener(new OnSuccessListener<FirebaseVisionDocumentText>() {
            @Override
            public void onSuccess(FirebaseVisionDocumentText result) {
                // Task completed successfully
                // ...
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Task failed with an exception
                // ...
            }
        });

認識したテキストのブロックからテキストを抽出する

テキスト認識オペレーションが成功すると、FirebaseVisionDocumentText オブジェクトが返されます。
FirebaseVisionDocumentText オブジェクトにはいくつか種類がありますが、今回は認識された全テキストをそのままTextViewに表示させます。

String resultText = result.getText();
textView.setText(resultText);
Log.d("text", resultText);

ここまで出来たら、Buildしてみます。

下記Build errorになりました。。

More than one file was found with OS independent path ‘META-INF/proguard/androidx-annotations.pro’

アプリレベルのbuild.gradle(app_name/app/build.gradle)に
下記を追記し、

android {
  packagingOptions {
       exclude 'META-INF/proguard/androidx-annotations.pro'
    }
}

再度Buildしてみます。

Build: completed successfully

うまくいきました。

もし、

No matching client found for package name ‘~~’

のエラーが出た場合は、app_name/app/google-services.jsonの"package_name": をandroidのアプリ名に直してみてください。

いろいろな文字認識を試してみる

ではさっそく試してみましょう。

1.通常テキスト(横書き、日本語)

まずは、クイックスタートのSampleアプリで扱った画像2枚です。
blog20190215_21
blog20190215_22

ほぼ認識できてますが、1枚目の「IT」の「I」は文字と認識していなかったようです。

次に、もう少し長文にチャレンジというとで、前回の私のエンジニアブログの記事を認識させてみます。

blog20190215_23

日付の前の記号を「0」に、Twitterの小鳥マークを「メ」と認識してますが(たしかにメっぽい・・)
それ以外は完ぺきです。


2.通常テキスト(縦書き、日本語)

日本語の縦書きに挑戦してみます。


blog20190215_24

最初のフリガナを早々に見切ったのか、それ以降は縦書きでも問題ありません。
難しい漢字も正しく認識できています。


3.背表紙

次に、本の背表紙で試してみます。

blog20190215_27

シンプルなものであれば、だいたい認識できるようです。

ただやはり、特殊なフォントを使っているものはさすがに難しいようでした。

blog20190215_28


4.手書き(英語、日本語)

最後に手書きです。
子供が書いた英語と日本語で試してみます。

blog20190215_25

blog20190215_26

英語はほぼ完ぺきです。
日本語の方が少し苦手でしょうか。
ただもちろん文字の正確さや画像の精度にもよるので判断が難しいところです。

まとめ

今回、ML Kitの文字認識機能をいろいろと試してみましたが、
思った以上に精度が出ると感じました。

認識させる画像については、Googleから入力画像に関するガイドラインが出ていますので、利用する際には参考にするのが良いかと思います。

用途が合えば、とても手軽に機械学習の恩恵を受けることができるサービスだと思いますので、引き続きいろいろとチャレンジしてみたいと思います!