Tesseract OCR で画像から文字を取り出す（Macでの導入方法あり）

# 初めに

OCR（光学文字認識）を試してみたかったので、無料で使える Tesseract OCR を触ってみました
Mac での導入方法に加えて、ちょっと解説も挟んでます

# 実行環境

- Mac OS：Ventura 13.6
- Python：3.11.7
- Tesseract：5.3.4

# Tesseractのインストール

Homebrew でインストールする

```bash
$ brew install tesseract
```

インストールできたことを確認しておく

```bash
$ tesseract --version 
tesseract 5.3.4
 leptonica-1.84.1
  libgif 5.2.1 : libjpeg 8d (libjpeg-turbo 3.0.0) : libpng 1.6.40 : libtiff 4.6.0 : zlib 1.2.11 : libwebp 1.3.2 : libopenjp2 2.5.0
 Found NEON
 Found libarchive 3.7.2 zlib/1.2.11 liblzma/5.4.4 bz2lib/1.0.8 liblz4/1.9.4 libzstd/1.5.5
 Found libcurl/8.1.2 SecureTransport (LibreSSL/3.3.6) zlib/1.2.11 nghttp2/1.51.0
```

# 学習済みモデルのインストール

## 扱える言語の確認

下記のコマンドで Tesseract OCR エンジンがサポートしている[言語のリスト](https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html)を確認できる

```bash
$ tesseract --list-langs 
List of available languages in "/opt/homebrew/share/tessdata/" (3):
eng
osd
snum
```

- `eng`：英語のテキスト認識
- `osd`：テキストの方向とスクリプトの検出
- `snum`：サードパーティのシリアルナンバー識別？
    - これは Tesseract が提供するモデルではなく Homebrew で提供されるツールにだけ存在するよう
    - 参考 : https://github.com/tesseract-ocr/tesseract/issues/2415

## 日本語を扱えるようにする

公式が提供する学習済みモデルには下記の3種類があり、速度と精度のどちらを重視するかで選択する

|  | 速度 | 精度 |
| --- | --- | --- |
| [tessdata](https://github.com/tesseract-ocr/tessdata) | 普通 | 普通 |
| [tessdata-best](https://github.com/tesseract-ocr/tessdata_best) | 遅い | 高い |
| [tessdata-fast](https://github.com/tesseract-ocr/tessdata_fast) | 速い | 低い |

詳細は公式ドキュメントを参照 https://tesseract-ocr.github.io/tessdoc/Data-Files.html
今回は精度を重視したいので `tessdata-best` を使用する

まずはモデルを配置するディレクトリに移動

```bash
# tesseract --list-langs の実行時に表示されたパスを指定する
$ cd /opt/homebrew/share/tessdata/
```

次に`jpn.traineddata` と `jpn_vert.traineddata` をダウンロードする
後者は縦書きのテキスト用らしい

```bash
$ curl -LO https://github.com/tesseract-ocr/tessdata_best/raw/main/jpn.traineddata
$ curl -LO https://github.com/tesseract-ocr/tessdata_best/raw/main/jpn_vert.traineddata
```

`jpn` と `jpn_vert` が追加されたことを確認する

```bash
$ tesseract --list-langs
List of available languages in "/opt/homebrew/share/tessdata/" (5):
eng
jpn
jpn_vert
osd
snum
```

# 文字認識を実行する

## コマンドの使い方

```bash
$ tesseract <input_image> <output_text_file> -l lang_code
```

第1引数：文字認識させる画像ファイルのパス
第2引数：結果を出力するファイル名。`-`を指定すると標準出力される
第3引数：言語の指定

## 横書き

この画像で文字認識させてみる（[Wikipedia](https://ja.wikipedia.org/wiki/Python)より）

![python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/c9fa58e6-1e16-5719-1042-88cde677e2a7.png)


```bash
$ tesseract python.png - -l jpn

Estimating resolution as 170
概要 [編集 ]

Python は 1991 年 に グイ ド ・ ヴ ァ ン ・ ロ ッ サ ム に より 開発 され た プロ グラ

最初 に リリース され た Python の 設計 哲学 は 、 ホ ワイ トス ペー ス ( オ フサ イ
ドル ー ル ) の 顕著 な 使用 に よっ て コー ド の 可読性 を 重視 し て いる 。 そ の 言語
構成 と オブ ジェ クト 指向 の アプ ロー チ は 、 プ ログ ラマ が 小 規模 な プロ ジェ
クト か ら 大 規模 な プロ ジェ クト まで 、 明 確 で 論理 的 な コー ド を 書く の を 支
援 す る こと を 目的 と し て いる 。
```

2行目の「ミング言語である」が抜けていたり、所々に半角スペースが入っているが文字は正しく認識できている

## 縦書き

今度はこの画像で文字認識させてみる

![akeome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/876c3574-4706-d6c0-a14b-7c3eb0e2c022.png)


```bash
$ tesseract akeome.png - -l jpn_vert    

Estimating resolution as 233
あけまして
おめでとう
ございます
```

綺麗に文字認識している

## 英語

英語の文字認識精度も確かめてみる

![python_eng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/90a22d4b-6e2e-1c0d-09c6-eab3f8771ae1.png)

```bash
$ tesseract python_eng.png - -l eng
Estimating resolution as 140
Python is a high-level, general-purpose programming language. Its design
philosophy emphasizes code readability with the use of significant
indentation.21)
```

さすがに精度良く認識できている

# イレギュラーなパターンを試してみる

## 崩れた字体

![akeome_pop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/dfd71df0-e929-5f74-38ba-5f235754f7b6.png)

```bash
$ tesseract akeome_pop.png - -l jpn_vert
```

何も出力されなかった
やはり字体が崩れていると文字として認識されないらしい

## 間違った言語指定

日本語の文字を英語として文字認識させてみる

![python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/c9fa58e6-1e16-5719-1042-88cde677e2a7.png)

```bash
$ tesseract python.png - -l eng
Estimating resolution as 170
BZ we
Pythonig 99IFICY1 Ks Sry Dy balck MSN ZOTS
SVPEBCHS.

BMC V—AehiePythonoMatasr ls, MIT KAN-A(A TUL
RIL J) ORR EBC E> TI KOM RMEEHRULTWIS. EO
MREAT ILI MBMOPFO—-Fld, TAF SV AUS TOYT
DRDSARMUETOL II HEC AMER I—KEBK DEK
MISTLEBWELTHS,
```

まるでデタラメな文字列になった。英語で指定しているので当然か

では、逆ならどうか

![python_eng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/90a22d4b-6e2e-1c0d-09c6-eab3f8771ae1.png)

```bash
$ tesseract python_eng.png - -l jpn
Estimating resolution as 140
Python is a high-level, generalpurpose programming language. its design
philosophy emphasizes code readability with the use of significant
indentation.B1
```

きちんと英語を認識できている

## 言語指定をしなかった場合

![python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/c9fa58e6-1e16-5719-1042-88cde677e2a7.png)

```bash
$ tesseract python.png -    
Estimating resolution as 170
BZ we
Pythonig 99IFICY1 Ks Sry Dy balck MSN ZOTS
SVPEBCHS.

BMC V—AehiePythonoMatasr ls, MIT KAN-A(A TUL
RIL J) ORR EBC E> TI KOM RMEEHRULTWIS. EO
MREAT ILI MBMOPFO—-Fld, TAF SV AUS TOYT
DRDSARMUETOL II HEC AMER I—KEBK DEK
MISTLEBWELTHS,
```

![python_eng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/90a22d4b-6e2e-1c0d-09c6-eab3f8771ae1.png)

```bash
$ tesseract python_eng.png -       
Estimating resolution as 140
Python is a high-level, general-purpose programming language. Its design
philosophy emphasizes code readability with the use of significant
indentation.21)
```

英語に指定した時と同じ結果になった
おそらくデフォルトの言語が英語になっているからだろう

以上から、日本語と英語が混在している画像で文字認識するなら、日本語のモデルを選んだ方がいいと思われる

# 終わりに

英語ならば綺麗に文字認識ができるが、日本語はやや難あり
[tessdata-best](https://github.com/tesseract-ocr/tessdata_best) はモデルの再トレーニングも可能らしいので、もっと精度の良い学習モデルにできれば活用の幅は広がりそう

ただ、今のままでも所々に入ってしまう半角スペースを自動で消す処理を挟めば違和感なく読める文章になるはず
今度アプリ化してみたい

# 参考記事

https://codenote.net/tool/6060.html

https://rooter.jp/ml/tesseract-with-mac/