Yomitokuで写真やレシートを解析してみる

YomitokuというAI-OCRライブラリが話題になっていたので、さっそくさわってみました。

https://github.com/kotaro-kinoshita/yomitoku

# ライセンス
個人利用および研究目的のみ無償利用可能です。この記事は個人的趣味で書いています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/c281b3f0-ac09-c63b-3b54-a73eac1fe8fa.png)

# 環境
Google colab
設定ミスってCPUで実行

# 前準備
```python
! pip install yomitoku
```
最後にsession restartしろといわれたので、ダイアログボックスに促されるままrestartしました。

# 実行方法
google colabなので、/content以下にimageフォルダを作成し、その中にJPGをいれます。
この前、NexTechWeekに行ったときに撮影した写真を使います。

実行方法は以下。フォルダをまるっと指定すると、その中の画像ファイルをすべて解析してくれます。
```python
! yomitoku /content/image/ -f md -o results -v --figure
```
妙に時間がかかるなと思ったら、ランタイムがCPUのままでした。
途中経過がログででます。何にどのくらいかかるかまで見られるのはよいですね。

実行結果をみていきます。

# ポスター写真
NexTechWeek2024で撮影させていただいた画像をYomitokuしました。レザバー関連のプロジェクトの概要で大学による出展です。良い感じにレイアウトされつつ絵もあり、ちょっと表っぽい格子などもあり、なかなか試す素材としてはよさそうなのでチョイスしました。
![20241121_102448.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/c7998af9-dfdc-3c47-521c-8818c699316d.jpeg)


以下、ログの一部です。
最初にレイアウト分割、テーブル構造の把握、テキスト検出、テキスト認識、出力ファイルの生成といった流れで処理が進むようです。この画像の分析に127秒かかっています。

```log
2024-11-27 13:15:21,658 - yomitoku.base - INFO - LayoutParser __call__ elapsed_time: 5.494288444519043
2024-11-27 13:15:21,686 - yomitoku.base - INFO - TableStructureRecognizer __call__ elapsed_time: 0.027859210968017578
2024-11-27 13:15:36,098 - yomitoku.base - INFO - TextDetector __call__ elapsed_time: 19.93536949157715
2024-11-27 13:17:23,289 - yomitoku.base - INFO - TextRecognizer __call__ elapsed_time: 107.19037675857544
2024-11-27 13:17:23,390 - yomitoku.cli.main - INFO - Output file: results/image_20241121_102448_p1_ocr.jpg
2024-11-27 13:17:23,450 - yomitoku.cli.main - INFO - Output file: results/image_20241121_102448_p1_layout.jpg
2024-11-27 13:17:23,611 - yomitoku.cli.main - INFO - Output file: results/image_20241121_102448_p1.md
2024-11-27 13:17:23,612 - yomitoku.cli.main - INFO - Total Processing time: 127.70 sec
```

レイアウトの認識結果です。画像や文字のまとまりが矩形で切り出されています。斜めの線は、画像や文字の取得順序のようです。mdファイルと見比べるとわかるのですが、斜めの赤線の順番にmdファイルに文字や画像が記載されています。
![image_20241121_102448_p1_layout.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/4ba62605-5dcb-3cb0-134e-37cdfd12adc3.jpeg)

こちらがOCR結果。どこにどの文字が書かれているか、識別できています。

![image_20241121_102448_p1_ocr.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/0a4b4426-6a59-c0d5-c0a7-4355b7e3980a.jpeg)

md形式ではきだされた結果は以下となっています。濁点などが一文字扱いになっていますね。
別途figuresフォルダが作成され、そこにきりだされた画像が格納されています。そこへのリンクを記述する形で、画像との位置関係も表現しています。
```md
フ゜ロシ゛ェクト概要

<img src="figures/image_20241121_102448_p1_figure_0.png" width="200px"><br>
本フ゛ースて゛展示する成果物は,<br>国立研究開発法人新エネルキ゛ー・産業技術総合開発機構\(NEDO\) の委託業務\(JPNP16007<br>『高効率・高速処理を可能とする AIチッフ゜・次世代コンヒ゜ューティンク゛の技術開発/<br>ニューロモルフィックタ゛イナミクスに基つ゛く超低電力エッシ゛AIチッフ゜の研究開発とその応用展開\!<br>にて得られた成果て゛す\.

# ATモテ゛ル<br>レサ゛ハ゛ー計算モテ゛ル

次世代AIの基盤として期待される,<br>少テ゛ータ・短時間て゛学習可能な<br>レサ゛ハ゛ー計算モテ゛ルを開発\. 単純<br>なネットワーク構造により高効率<br>なハート゛ウェア化に最適\.

<img src="figures/image_20241121_102448_p1_figure_1.png" width="200px"><br>
<img src="figures/image_20241121_102448_p1_figure_2.png" width="200px"><br>
# 高効率AI向け集積回路方式<br>インメモリ計算

テ゛ィシ゛タル方式により応用展開を先<br>導し,並行して超高効率演算を実現<br>て゛きる時間領域アナロク゛方式による<br>インメモリ計算\(Computing in<br>Memory; CiM\) 方式専用チッフ゜を<br>開発\.

<img src="figures/image_20241121_102448_p1_figure_3.png" width="200px"><br>
Dnt<br>128レヘ゛ル×2の<br>アナロク゛量を記憶

# 各種応用<br>異常検知・サーヒ゛スロホ゛ット等

# 記憶テ゛ハ゛イス<br>SONOS型フラッシュメモリ

超高効率演算を実現て゛きるCiM方<br>式て゛キーとなるアナロク゛メモリ素<br>子を、SONOS型フラッシュメモ<br>リ素子を用いて開発\.

<img src="figures/image_20241121_102448_p1_figure_4.png" width="200px"><br>
\(ap\(8>\)喜幸\(i±x

開発したAIフ゜ロセッサ/チッフ゜を社会実装へ繋け゛るために、ソフトウェア開発と連携する<br>ためのキット\(SDK\) を開発\.

各種設備モニタリンク゛システム,移動台車ロホ゛ット,ソフトロホ゛ット技術を組み合わせ<br>た日常生活支援ロホ゛ットなと゛の社会実装に取り組む

<img src="figures/image_20241121_102448_p1_figure_5.png" width="200px"><br>
<img src="figures/image_20241121_102448_p1_figure_6.png" width="200px"><br>
<img src="figures/image_20241121_102448_p1_figure_7.png" width="200px"><br>
```

## 切り出された画像を抜粋
以下にきりだされた画像の一部を示します。多少ななめにはなっていますが、だいたいとれている形になります。ななめっているのは、私がとった写真がななめっているせいですね。
一番上の枠線は柄が大きいせいか図と認識されたようです。
image_20241121_102448_p1_figure_0.png
![image_20241121_102448_p1_figure_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/02532382-8829-7a00-5a25-c6c5fa8af89e.png)

image_20241121_102448_p1_figure_3.png
![image_20241121_102448_p1_figure_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/83593e74-b12d-48b5-30df-befb26ceb5cd.png)

image_20241121_102448_p1_figure_5.png
![image_20241121_102448_p1_figure_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/828ef0a6-bd07-4d06-cad5-41f48fdd209e.png)


# レシート
活字ならいけるとのことなので、レシート読み込んでみます。
以下サイトからレシート画像をお借りしました。
https://dailyportalz.jp/kiji/160930197541

![0003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/ef5a6d94-a9d0-0ca7-8991-98a77c47f554.jpeg)

今回は、json形式で出力させてみます。
```
! yomitoku 0003.jpg -f json -o results -v --figure
```

warningでました。画像サイズが小さすぎるようです。気にせずすすめます。
```
2024-11-27 14:05:39,116 - yomitoku.data.functions - WARNING - 
            The image size is small, which may result in reduced OCR accuracy. 
            The process will continue, but it is recommended to input images with a minimum size of 720 pixels on the shorter side.
```

ログは以下。大枠の流れは変わらないようです。
```
2024-11-27 14:05:45,144 - yomitoku.base - INFO - LayoutParser __call__ elapsed_time: 6.025963306427002
2024-11-27 14:05:45,144 - yomitoku.base - INFO - TableStructureRecognizer __call__ elapsed_time: 0.00014925003051757812
2024-11-27 14:06:03,905 - yomitoku.base - INFO - TextDetector __call__ elapsed_time: 24.788093090057373
2024-11-27 14:06:41,284 - yomitoku.base - INFO - TextRecognizer __call__ elapsed_time: 37.37813758850098
```

レイアウトは以下。
ちゃんとまとまりを取得できています。サンクスのロゴは、画像とみなしてくれなかった模様。
![_0003_p1_layout.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/a8ef5d4b-a979-41ee-74e5-ece91d4baba0.jpeg)

OCR結果は以下。サンクスがサンクロになっている。結構、数字とか正確に読み取れている感じがします。
![_0003_p1_ocr.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106215/3524aad6-4234-881a-c166-b61f1abeec7c.jpeg)

以下、JSON情報です。文字情報だけでなく、レイアウトごとに配置場所や配置方向といった細かい情報も記載されています。画像がきっちりまっすぐできれいというのもありますが、文字や数字、住所電話番号など、かなり正確です。
```json
{
    "figures": [
        {
            "box": [
                57,
                12,
                250,
                64
            ],
            "direction": "horizontal",
            "order": 0,
            "paragraphs": [
                {
                    "box": [
                        57,
                        15,
                        250,
                        61
                    ],
                    "contents": "サンクロ",
                    "direction": "horizontal",
                    "order": 0,
                    "role": "section_headings"
                }
            ]
        }
    ],
    "paragraphs": [
        {
            "box": [
                20,
                71,
                273,
                146
            ],
            "contents": "麻布十番商店街通り店\n電話 03-5765-5600\n東京都港区麻布十番2丁目2-4\n2016年 9月29日(木) 12時37分",
            "direction": "horizontal",
            "order": 1,
            "role": null
        },
        {
            "box": [
                20,
                166,
                290,
                409
            ],
            "contents": "領収書\nセ゛リーdet'Dふ゛と゛う味\n\194\n\173\nタラミ 0kcal濃いリンコ゛セ゛リー\n\113\nク゛リコ カフェオーレ 180ml\n-\8\nセール値引\n\480\n(商品合計\n-\8 )\n(値引合計\n\472\n合計\n\34)\n(うち消費税等\n8.0%\n\1,002\nお 類 釣\n\530\nお買上け゛明細は上記のとおりて゛す。\n費78\nNo. 111041",
            "direction": "horizontal",
            "order": 2,
            "role": null
        }
    ],
    "tables": [],
    "words": [
        {
            "content": "No. 111041",
            "det_score": 0.8758549556459441,
            "direction": "horizontal",
            "points": [
                [
                    20,
                    392
                ],
                [
                    94,
                    391
                ],
                [
                    94,
                    406
                ],
                [
                    21,
                    407
                ]
            ],
            "rec_score": 0.9949248433113098
        },
        {
            "content": "費78",
            "det_score": 0.8804522691144848,
            "direction": "horizontal",
            "points": [
                [
                    248,
                    390
                ],
                [
                    282,
                    390
                ],
                [
                    282,
                    407
                ],
                [
                    248,
                    407
                ]
            ],
            "rec_score": 0.45288586616516113
        },
        {
            "content": "お買上け゛明細は上記のとおりて゛す。",
            "det_score": 0.8720497261230967,
            "direction": "horizontal",
            "points": [
                [
                    21,
                    371
                ],
                [
                    281,
                    372
                ],
                [
                    281,
                    389
                ],
                [
                    21,
                    388
                ]
            ],
            "rec_score": 0.9941951632499695
        },
        {
            "content": "\530",
            "det_score": 0.8219539643514924,
            "direction": "horizontal",
            "points": [
                [
                    223,
                    354
                ],
                [
                    288,
                    354
                ],
                [
                    288,
                    369
                ],
                [
                    223,
                    369
                ]
            ],
            "rec_score": 0.9989928007125854
        },
        {
            "content": "\1,002",
            "det_score": 0.8318259769243506,
            "direction": "horizontal",
            "points": [
                [
                    189,
                    335
                ],
                [
                    289,
                    335
                ],
                [
                    289,
                    351
                ],
                [
                    189,
                    351
                ]
            ],
            "rec_score": 0.711143970489502
        },
        {
            "content": "お 類 釣",
            "det_score": 0.6796634121848107,
            "direction": "horizontal",
            "points": [
                [
                    17,
                    332
                ],
                [
                    106,
                    329
                ],
                [
                    108,
                    372
                ],
                [
                    19,
                    375
                ]
            ],
            "rec_score": 0.30929943919181824
        },
        {
            "content": "(うち消費税等",
            "det_score": 0.8216504395685965,
            "direction": "horizontal",
            "points": [
                [
                    24,
                    316
                ],
                [
                    139,
                    315
                ],
                [
                    139,
                    331
                ],
                [
                    24,
                    333
                ]
            ],
            "rec_score": 0.9992212653160095
        },
        {
            "content": "8.0%",
            "det_score": 0.7108129620833669,
            "direction": "horizontal",
            "points": [
                [
                    134,
                    315
                ],
                [
                    198,
                    315
                ],
                [
                    198,
                    333
                ],
                [
                    134,
                    333
                ]
            ],
            "rec_score": 0.994272768497467
        },
        {
            "content": "\34)",
            "det_score": 0.8392330284031482,
            "direction": "horizontal",
            "points": [
                [
                    255,
                    315
                ],
                [
                    288,
                    315
                ],
                [
                    288,
                    332
                ],
                [
                    255,
                    332
                ]
            ],
            "rec_score": 0.9798897504806519
        },
        {
            "content": "合計",
            "det_score": 0.7973054917385075,
            "direction": "horizontal",
            "points": [
                [
                    25,
                    299
                ],
                [
                    103,
                    297
                ],
                [
                    104,
                    313
                ],
                [
                    25,
                    314
                ]
            ],
            "rec_score": 0.6281023025512695
        },
        {
            "content": "\472",
            "det_score": 0.8339690526443425,
            "direction": "horizontal",
            "points": [
                [
                    224,
                    297
                ],
                [
                    289,
                    297
                ],
                [
                    289,
                    314
                ],
                [
                    224,
                    314
                ]
            ],
            "rec_score": 0.9996665716171265
        },
        {
            "content": "(値引合計",
            "det_score": 0.8427165464241112,
            "direction": "horizontal",
            "points": [
                [
                    31,
                    278
                ],
                [
                    104,
                    278
                ],
                [
                    104,
                    295
                ],
                [
                    31,
                    295
                ]
            ],
            "rec_score": 0.9989968538284302
        },
        {
            "content": "-\8 )",
            "det_score": 0.5820983533109533,
            "direction": "horizontal",
            "points": [
                [
                    229,
                    274
                ],
                [
                    285,
                    275
                ],
                [
                    284,
                    296
                ],
                [
                    229,
                    295
                ]
            ],
            "rec_score": 0.8109473586082458
        },
        {
            "content": "(商品合計",
            "det_score": 0.8480653348868673,
            "direction": "horizontal",
            "points": [
                [
                    32,
                    260
                ],
                [
                    105,
                    260
                ],
                [
                    105,
                    277
                ],
                [
                    32,
                    277
                ]
            ],
            "rec_score": 0.9994435906410217
        },
        {
            "content": "\480",
            "det_score": 0.8743235539549437,
            "direction": "horizontal",
            "points": [
                [
                    223,
                    260
                ],
                [
                    257,
                    260
                ],
                [
                    257,
                    276
                ],
                [
                    223,
                    276
                ]
            ],
            "rec_score": 0.9993225932121277
        },
        {
            "content": "セール値引",
            "det_score": 0.8904321944845446,
            "direction": "horizontal",
            "points": [
                [
                    37,
                    242
                ],
                [
                    95,
                    242
                ],
                [
                    95,
                    257
                ],
                [
                    37,
                    257
                ]
            ],
            "rec_score": 0.7357009649276733
        },
        {
            "content": "-\8",
            "det_score": 0.8107688245518627,
            "direction": "horizontal",
            "points": [
                [
                    247,
                    241
                ],
                [
                    274,
                    241
                ],
                [
                    274,
                    257
                ],
                [
                    247,
                    257
                ]
            ],
            "rec_score": 0.9905100464820862
        },
        {
            "content": "ク゛リコ カフェオーレ 180ml",
            "det_score": 0.8664426081171958,
            "direction": "horizontal",
            "points": [
                [
                    30,
                    223
                ],
                [
                    170,
                    224
                ],
                [
                    170,
                    238
                ],
                [
                    29,
                    238
                ]
            ],
            "rec_score": 0.5264366269111633
        },
        {
            "content": "\113",
            "det_score": 0.8874214381146186,
            "direction": "horizontal",
            "points": [
                [
                    240,
                    222
                ],
                [
                    274,
                    222
                ],
                [
                    274,
                    239
                ],
                [
                    240,
                    239
                ]
            ],
            "rec_score": 0.9967212080955505
        },
        {
            "content": "タラミ 0kcal濃いリンコ゛セ゛リー",
            "det_score": 0.8691312865165296,
            "direction": "horizontal",
            "points": [
                [
                    29,
                    205
                ],
                [
                    205,
                    205
                ],
                [
                    205,
                    219
                ],
                [
                    29,
                    220
                ]
            ],
            "rec_score": 0.22857968509197235
        },
        {
            "content": "\173",
            "det_score": 0.8751724123834974,
            "direction": "horizontal",
            "points": [
                [
                    239,
                    204
                ],
                [
                    274,
                    204
                ],
                [
                    274,
                    220
                ],
                [
                    239,
                    220
                ]
            ],
            "rec_score": 0.9981789588928223
        },
        {
            "content": "セ゛リーdet'Dふ゛と゛う味",
            "det_score": 0.8555895687768326,
            "direction": "horizontal",
            "points": [
                [
                    30,
                    185
                ],
                [
                    190,
                    185
                ],
                [
                    190,
                    201
                ],
                [
                    30,
                    201
                ]
            ],
            "rec_score": 0.7772231101989746
        },
        {
            "content": "\194",
            "det_score": 0.8885384467497309,
            "direction": "horizontal",
            "points": [
                [
                    240,
                    185
                ],
                [
                    273,
                    185
                ],
                [
                    273,
                    201
                ],
                [
                    240,
                    201
                ]
            ],
            "rec_score": 0.9992437958717346
        },
        {
            "content": "領収書",
            "det_score": 0.8332461856915996,
            "direction": "horizontal",
            "points": [
                [
                    89,
                    167
                ],
                [
                    223,
                    167
                ],
                [
                    223,
                    183
                ],
                [
                    89,
                    183
                ]
            ],
            "rec_score": 0.9028484225273132
        },
        {
            "content": "2016年 9月29日(木) 12時37分",
            "det_score": 0.86702999606025,
            "direction": "horizontal",
            "points": [
                [
                    37,
                    129
                ],
                [
                    272,
                    129
                ],
                [
                    272,
                    145
                ],
                [
                    37,
                    145
                ]
            ],
            "rec_score": 0.9826998114585876
        },
        {
            "content": "東京都港区麻布十番2丁目2-4",
            "det_score": 0.8895397053076025,
            "direction": "horizontal",
            "points": [
                [
                    22,
                    112
                ],
                [
                    271,
                    111
                ],
                [
                    271,
                    126
                ],
                [
                    22,
                    126
                ]
            ],
            "rec_score": 0.9983033537864685
        },
        {
            "content": "電話 03-5765-5600",
            "det_score": 0.870918528897612,
            "direction": "horizontal",
            "points": [
                [
                    81,
                    92
                ],
                [
                    232,
                    92
                ],
                [
                    232,
                    108
                ],
                [
                    81,
                    108
                ]
            ],
            "rec_score": 0.9984465837478638
        },
        {
            "content": "麻布十番商店街通り店",
            "det_score": 0.8839409100423237,
            "direction": "horizontal",
            "points": [
                [
                    72,
                    74
                ],
                [
                    239,
                    73
                ],
                [
                    239,
                    89
                ],
                [
                    72,
                    89
                ]
            ],
            "rec_score": 0.9990543723106384
        },
        {
            "content": "サンクロ",
            "det_score": 0.835889508850292,
            "direction": "horizontal",
            "points": [
                [
                    122,
                    16
                ],
                [
                    249,
                    16
                ],
                [
                    249,
                    52
                ],
                [
                    122,
                    53
                ]
            ],
            "rec_score": 0.6875899434089661
        }
    ]
}
```

# まとめ
- 完全に興味本位でYomitokuライブラリを使ってみました。
- 濁点などの認識部分は整える必要がありますが、文字や数字などはかなり正確に取得できていると思います。
- ポスター画像よりは、レシートのような構造がシンプルなもののほうが確実です。
- 出力形式によって得られる情報が異なるので、目的によってつかいわけるのがよさそう。

以上