Tesseract4Android でOCR ~ tess-twoの後継

以前、AndroidでOCRをtess-twoライブラリで行いました。

しかしながら、tess-twoライブラリによるOCRは、成績が今一つなことと、更新がしばらく止まっている状態のため、こちらも休止状態でした。それにしても、OCR需要の方は多いようなので、後継のTesseract4Androidライブラリ(以下、Tesseract4Android)も使ってみることにしました。

言語はjavaを使用しますので、kotlinを使う場合は適度修正してください。

1.Tesseract4Androidのある場所

Tesseract4Androidは、上記のURLにあります。そこには、実際のプロジェクトへの組み込み方法も書かれていますが、Android Studioのバージョンによっては、方法が異なります。私のAndrod StudioのバージョンはHedgehogなので、「settings.gradle」で

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' } // 追加する
    }
}

で「https://jitpack.io」を追加しました。

2.カメラアプリへ組み込んでみる

以前、CameraXをテストしたプロジェクトに、Tesseract4Androidのコードを組み込んでみます。テストプログラムにはシャッターボタンが用意されており、押された時に保存される写真画像をOCR読み取りします。

※画面レイアウトが以前と少し変わっていますが、カメラビューとボタンだけの構成は変わりありません。

Activityクラスメンバ変数

private TessBaseAPI tess ;

TessBaseAPIクラスを宣言します。

コンストラクタ

// インスタンスの作成
tess = new TessBaseAPI();

// OCR言語データのあるフォルダを指定
String dataPath = new File(getFilesDir(), "tesseract").getAbsolutePath(); 

// 初期化
if (!tess.init(dataPath, "jpn")) { 
    tess.recycle();
    return;
}

TessBaseAPIのインスタンスを作成します。

OCR言語データを、アプリケーションのファイルフォルダに保存しておきます。これを手作業するには面倒なので、assetフォルダにOCR言語データを保持しておき、アプリケーションを実行したときにファイルフォルダにOCR言語データがなければ、assetフォルダのOCR言語データをファイルフォルダにコピーするというやり方をします。(Tesseract4Androidサンプルなどを参照してください)

ボタンが押された

shutterButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        // 写真画像名
        ocrFilename = new SimpleDateFormat(FILENAME_FORMAT, Locale.JAPAN)
                        .format(System.currentTimeMillis()) + ".jpg" ;

        // 撮影した写真の画像ファイル作成
	File photoFile = new File(getOutputDirectory(),
                        ocrFilename) ;

        ImageCapture.OutputFileOptions outputFileOptions =
                        new ImageCapture.OutputFileOptions.Builder(photoFile).build();

	imageCapture.takePicture(outputFileOptions, cameraExecutor,
                        new ImageCapture.OnImageSavedCallback() {
        
            @Override
            public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
                                 // 撮影した画像からBitmapを得る
				String ocrFileReadName = getOutputDirectory() + "/" + ocrFilename ;
                                Bitmap ocrBitmap = BitmapFactory.decodeFile(ocrFileReadName) ;

                                tess.setImage(ocrBitmap);

                                // OCR実行
				String text = tess.getUTF8Text();

                                // 解放する
				tess.recycle();

            }

ソースを抜粋して載せているので、不十分な部分があることをご了承ください。

シャッターボタンが押されて、写真画像を保存するロジック部分にTesseract4Androidのコードを追加します。

コールバックのonImageSaved関数で写真画像ファイルからBitmapを作成し、OCR処理をしています。そして、getUTF8Text関数の復帰値に、OCRの結果文字列が入ります。

テストプログラムでは、textを表示/保存するロジックは入れておらず、デバッガを使って中身を確認しています。

3. OCR精度は?

上画像に書かれている文字列を読み込みます。以前の投稿を切り取ってテストデータを作成しました。テストデータはJPEG画像で、ディスプレイに表示して、テストアプリケーションで撮影し、OCR処理をします。

OCR結果は以下のとおりです。(投稿時点では数件しかやっていないため、最適な方法を見つけていません)

コ ュ 自 |
北 海 道 で コ マ ク サ を 見 る 場 所 と し て 、 真 っ 先 に 挙 げ る と し た ら ` 騒
草 平 」 で す 。 銀 泉 台 か ら 赤 城 へ 向 か う 途 中 に あ る 騒 草 平 は 、 一 面 に
コ マ ク サ が 嵌 く 災 所 で す 。 一 時 期 、 盛 掘 に よ う て 港 少 し て し ま い ま
し た が 、 手 厚 い 悦 難 に よ り 従 浩 し ま し た 。
赤 坪 登 山 は 、 高 度 こ そ ②,000m 級 で す が 、 鍋 泉 台 で ①,⑤00m の 標 高
が あ る お か げ で 初 編 レ ベ ル の 登 山 で 済 み ま す 。 ぜ ひ 、 華 麗 な コ マ ク
~ サ を 報 罷 し て く だ さ い 。 〕
大 雪 山 報 命 台 一 車 で 行 け る 北 浪 道 冊 所 で 。。 a ・
す ` ッ デ シ ン ②
無 口 ①.⑤00m に あ る 大 雪 山 銀 命 台 。 そ の 銀 命 台 ま で は 車 逢 國國 論 論 論 談
が 逢 っ て お り 、 車 で 行 く こ と が で き る 海 道 昌 高 所 … 閻 國 談 談 談 談 談
[ ょ NHITIVSEuf n ^〕,`:ョ〟_二`〟`〝 "璽 。 `j_`__~`璽二 | : g〟二"z}・ h
ド | `【二コ  ー ・
璽」二 s p 二〕 _〕〟 サ ヨ メ ⑤ 弓 .④KP
織 m
罵 q ④ 0 ⑧ "
mmaaa⑧ に J = 《 曲 ① マ 啓

ディスプレイに表示された文字列を読み取っているので、OCRの成績が良くありません。また、紙からの読み込みもやってみましたが、似たような成績で良くありません。この辺は、どうしたら良い読み込み結果になるのかを試行錯誤してみます。

4.撮影せずに画像を直接OCRしたら

テストデータ(画像)を直接Tesseract4Androidに渡してOCRすればどうでしょうか。カメラで撮影という劣化がないので、成績がずっと良くなるはずです。

北 海 道 で コ マ ク サ を 見 る 場 所 と し て 、 真 っ 先 に 挙 げ る と し た ら ` 駒
草 平 」 で す 。 銀 命 台 か ら 赤 垂 へ 向 か う 途 中 に あ る 駒 草 平 は 、 一 面 に
コ マ ク サ が 咲 く 名 所 で す 。 一 時 期 、 盗 掘 に よ っ て 減 少 し て し ま い ま
し た が 、 手 厚 い 保 護 に よ り 復 活 し ま し た 。
赤 垂 登 山 は 、 高 度 こ そ ②,000m 級 で す が 、 銀 命 台 で ①,⑤00m の 標 高
が あ る お か げ で 初 級 レ ベ ル の 登 山 で 済 み ま す 。 ぜ ひ 、 華 麗 な コ マ ク
サ を 堪 能 し て く だ さ い 。

大 雪 山 銀 命 台 ~ 車 で 行 け る 北 海 道 最 高 所 で り

す

標 高 ①.⑤00m に あ る 大 雪 山 銀 祓 台 。 そ の 銀 泉 台 ま で は 車 道 ・

が 通 っ て お り 、 車 で 行 く こ と が で き る 北 海 道 最 高 所 …

馨 https-/www_kunimiyasoft_com/sanpo_ginsendai)

予想通り成績が良くなりましたが、まだ誤読み取りが多いです。標高部分の読み込みがうまくいっていないことが、少し疑問に思えました。

5. OCRアプリケーションやgoogleレンズなどに比べると劣りますが。。

テスト結果から、tess-twoよりは成績が良いようですが、まだまだ改善の余地があるといった感じです。おそらく、読み取った文字列を、AIに校正させる必要があると思います。有名なOCRソフトウェアでは、きっと行われているのでしょう。

これからも、いろいろテストしてリライトする予定です。