Python+tesseractでゲーム画面のOCRをしてみる

ゲームの金策をするためにエンジニアリング力をフル活用したいと思い、Python＋tesseractでゲーム画面の文字取得をするところから始めてみようと思いました。

Windows10で行います。

## 使うもの

- Python
- tesseract
    - OCRエンジンを含むパッケージ
- pytesseract
    - Python向けラッパー



## 環境構築

### 1. tesseractのインストール

forkしたこちら
[Home · UB-Mannheim/tesseract Wiki](https://github.com/UB-Mannheim/tesseract/wiki)
からのインストールを勧めている記事が多かったので信じてこちらから。

tesseract-ocr-w64-setup-v5.0.0-alpha.20210506.exe (64 bit) resp.をダウンロードします。

インストーラがダウンロードできたら実行しましょう。

インストールの過程で注意すべき点として。
今回は日本語をOCRする可能性もあるので、`Additional language data(download)`の中の`Japanese`と`Japanese(vertical)`もインストールします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/6fa2c7b4-2e7b-d1c2-ab0b-ed3a90b784a6.png)

もう１点、インストール先のディレクトリですが、ダウンロードページに気になる記述があります。

> WARNING: Tesseract should be either installed in the directory which is suggested during the installation or in a new directory. The uninstaller removes the whole installation directory. If you installed Tesseract in an existing directory, that directory will be removed with all its subdirectories and files.

念の為DeepLで翻訳すると以下です。

> 警告: Tesseractは、インストール時に指定されたディレクトリにインストールするか、新しいディレクトリにインストールする必要があります。アンインストーラーはインストールディレクトリ全体を削除します。既存のディレクトリにTesseractをインストールした場合、そのディレクトリはすべてのサブディレクトリとファイルとともに削除されます。

危険を避けるためには、新しくtesseractをインストールする用のディレクトリを新規に作成して、そこにインストールするのが無難ですね。

今回はデフォルトのTesseract-OCRを作成してそこに入れる形でいきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/1a678449-6a5d-cffb-9173-8c21195dd592.png)

NextとFinishで完了。

念の為インストールが正しくできているか確認するため、コマンドラインから以下コマンドで確かめてみましょう。

```
$ tesseract --list-langs
```

うまく行けば以下のように表示されます。

```
List of available languages (4):
eng
jpn
jpn_vert
osd
```

もしエラーがでる場合、環境変数Pathに`tesseract.exe`の場所が設定されていない可能性があります。確認してみましょう。

### 2. pytesseractのインストール

```
$ pip install pytesseract
```

だけ。

## 動かしてみる

試しに、事前にFF14で撮っておいた以下の画像をOCRしてみます。

![ff14marketboard.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/40513e1c-503f-e71e-1ccc-3c7c0b3a1f77.png)

コードは以下。上記画像を同ディレクトリに置いてOCRにかけ、printしただけです。

``` python
import pytesseract
from PIL import Image

result = pytesseract.image_to_string(Image.open('./ff14marketboard.png'), lang='jpn')
print(result)
```

結果は・・・

```
NTONY

jl)

単品価格

じじ01010】
ECW0100)】
ECW0010】
PA010(0】
EEAOIO10D】
EEAOI00)
Sア40010】
(70000)
YA)】
70,000ゎ
70,000?
70,.000ゎ
EIJI0D】
90,.000?
EUROIO(0】
EUROIO(0】
EIJI)】
UP)
105,000ゎ
100,.000ゎ

マーケットでの過去の取引履歴

個数 購入者名

1



II!邊DAII(eEI
Kikuzone Testarossa
な)!N公/人ET)
NUMhEIlite|
IMEIIMx(ejre)

IMliek人lilで|
[GIIIEWCEIIIE

Astrea Stella
EEIUtClnEYo)itelEI
Chifuyu Yuki

Rituka Uma

貞juEWNEL:II()
(6)iE【e|全たいた|

Aya Takenoko
Nemu Rineko
hinteel)【eldnllnntelell
tdl【dllい4
MEIMUIGIくII401i|
EinEEullnEte)

IMに委EIC)

BE

7/24 2:43
の21 1
7AE角EE】:)
7/12 0:40
AP4ECF)
んザル)
7をた】0妥にが|
74040R0<)
74050くい/
74じた)?4
74じ引じiP4
74E記CC!
7たに:ECO)
30) の)訓)
ルン 40)
5/22 16:23
ロタ4 影作た)
57Aじザル/
7ん-角MI【)
Ca計と!
```

これはひどい。

試しに言語設定をenにして実行してみると。

```
HISTORY scsi

HQ

Ban itits

94,000,
94,000>
94,000.
59,000,
59,000>
59,000>
62,000,
67,000,
67,000>
70,0009
70,0009
70,0009
90,000>
90,0009
90,000,
90,000,
90,000>
100,000p
105,000>
100,000>

Y—Ty bk COMBOEY | EE

(EX HABA

1



Mu Tyuinga
Kikuzone Testarossa
Abbey Williams
Neu Raind

Marl Roro

Mito Raruka

Chris Garua

Astrea Stella

EFL aviatclamsve)alelic}
Chifuyu Yuki

Rituka Uma

Leona Nakano
Ohagi Yaya

Aya Takenoko
Nemu Rineko
Yomogi Mochimochi
Melon Mellow
Maruten Koikuti
Shima Shimao
Mine Taro

FNS | BSA

7/24 2:43
Wl Wald
Ame)
7/12 0:40
7/11 21:43
7/4 3:29
6/30 19:41
6/20 20:06
6/20 0:49
6/14 23:37
6/14 14:17
6/13 5:44
5/31 18:45
By/sl0) 23}53)3)
5/24 21:05
5/22 16:23
EY PA eI)
5/14 3:29
5/8 1:16
4/21 3:34
```

少しだけマシになりましたが、思ったより精度が出ません。
ゲームのフォントだと特殊なのでしょうか。

### 類似画像を作って比較してみる

Excelを使って、似たような色味、同じ内容、だけど別フォント、の画像を用意してみました。

※ゲーム中の通貨単位のところだけ、該当する文字がないため、一旦類似の「ｐ」を使ってみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/2f953083-5dc3-fb5b-a211-0aa1cca1fbd0.png)

この画像に対して同様にOCRにかけるとどうなるでしょうか。

結果は・・・

```
HISTORY sles

HQ

anit s
94,000p
94,000p
94,000p
59,000p
59,000p
59,000p
62,000p
67,000p
67,000p
70,000p
70,000p
70,000p
90,000p
90,000p
90,000p
90,000p
90,000p
100,000p
sTe}=M010)0) 9)
100,000p

(HR ABA

1 Mu Tyuinga

1 Kikuzone Testarossa
1 Abbey Williams

1 Neu Raind

1 Marl Roro

1 Mito Raruka

1 Chris Garua

1 Astrea Stella

1 Bakutteh Songfa

1 Chifuyu Yuki

1 Rituka Uma

1 Leona Nakano

1 Ohagi Yaya
WY] <1 10) <o)

1 Nemu Rineko

1 Yomogi Mochimochi
1 Melon Mellow

1 Maruten Koikuti

1 Shima Shimao

1 Mine Taro

ERS |B!

7/24 2:43
7/21 1:13
7/15 1:36
7/12 0:40
7/11 21:43
7/4 3:29
6/30 19:41
6/20 20:06
6/20 0:49
6/14 23:37
6/14 14:17
6/13 5:44
5/31 18:45
5/30 23:33
5/24 21:05
5/22 16:23
5/21 2:38
5/14 3:29
5/8 1:16
4/21 3:34
```

だいぶ正確。元のゲームUIに比べると、Excelで作った類似画像のほうが内容を正しく取得できています。

となると、ゲーム画面のOCRをするには何らかもうひと工夫必要そうですね・・・。

試行錯誤してみようと思います。


## 参考

- [文字認識ソフトのTesseractを使ってみた - Qiita](https://qiita.com/uneyamauneko/items/0a84e9a1c18a0e30626f)


### おまけ：通貨単位をゲーム中のものにあわせたら

雑コラですが、「ｐ」でごまかさずにゲーム中の通貨単位を使った画像でもやってみました。

![ff14marketboard3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/2eb4350d-3708-3161-3905-c201350bc872.png)

```
HISTORY %le#

HQ

ots
94,000p
94,0009
94,000p
59,000p
59,000p
59,000p
62,000)
67,000)
67,000
70,000p
70,000)
70,000?
90,000p
90,000?
90,000?
90,000?
90,000p
100,000p
105,000)
100,000p

EX FABA

1 Mu Tyuinga

1 Kikuzone Testarossa
1 Abbey Williams

1 Neu Raind

lm Fela ce)ge)

1 Mito Raruka

1 Chris Garua

1 Astrea Stella

1 Bakutteh Songfa

1 Chifuyu Yuki

1 Rituka Uma

1 Leona Nakano

1 Ohagi Yaya

1 Aya Takenoko

1 Nemu Rineko

aly Co}nnteye im lelel alinalerelay|
1 Melon Mellow

1 Maruten Koikuti

1 Shima Shimao

1 Mine Taro

ENS BSH!

0 PA)
7/21 1:13
7/15 1:36
7/12 0:40
7/11 21:43
I LLMCEPAS)
6/30 19:41
6/20 20:06
oy PAO Orbe)
6/14 23:37
6/14 14:17
6/13 5:44
5/31 18:45
5/30 23:33
5/24 21:05
5/22 16:23
5/21 2:38
5/14 3:29
5/8 1:16
4/21 3:34
```

完全にExcelで作ったもの、に比べると精度が落ちていますが、それでもゲームのスクショそのままよりは正確になっています。通貨単位の文字が特徴的だから全体の精度が落ちている、というわけではなさそうです。