日本語対応軽量OCR PaddleOCRを試してみた ※GPU未使用

この投稿はKDDIテクノロジーアドベントカレンダーの11日目の記事となります。
普段は自然言語処理担当ですが別分野にチャレンジしてみました。

今回はBaiduのPaddlePaddle上で動作する[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)をGPU未使用で試してみたいと思います。
本記事は環境構築〜検証までを１から丁寧に解説するよう心がけております。
※Baiduが公開している日本語OCRモデルを元にして実行しています。
※日本語OCRモデルのファインチューニングなどは行っておりません。

# 環境情報
Ubuntu 22.04.1 LTS
Intel Core i7-8750H 
※GPU未使用
PaddlePaddle　2.4.0 
PaddleOCR　2.6.1.1        


# 環境構築方法
今回はGPUを使用しない前提での環境構築を目的としています。
### □Dockerインストール
Dockerのインストール方法については下記を参考にしてください。
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04-ja


### □PaddlePaddleイメージコンテナの起動
PaddleOCRはPaddlePaddle上で動作するため先にPaddlePaddleをインストールしていきます。

```bash
docker pull paddlepaddle/paddle:2.4.0-cpu
docker run --name ocrtest -v /(※):/sample -it paddlepaddle/paddle:2.4.0-cpu  bash
```
--nameについては省略可能もしくは任意の名称で問題ありませんがここではocrtestとしています。
※画像が配置されている任意の絶対パス

### □PaddleOCRインストール
```bash
python3 -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
pip install "paddleocr>=2.0.1"
```
途中でrequirementsのバージョン不一致によるエラー
ERROR: pylint 2.14.5 has requirement astroid<=2.12.0-dev0,>=2.11.6, but you'll have astroid 2.12.2 which is incompatible.
が出る可能性がありますが問題ありません。

### □PaddleOCR実行
```bash
paddleocr --image_dir /sample/(※) --use_angle_cls true --lang japan --use_gpu false
```
※任意の画像ファイル名

実行までの手順はたったこれだけです！

### □参考
[PaddlePaddle](https://hub.docker.com/r/paddlepaddle/paddle)はDockerイメージが公開されてますのでGPUを利用されたい方はDockerHubより適切なイメージを選択してください。


# サンプルおよび結果

出力ログフォーマットは**バウンディングボックスの座標**、**テキスト**、および**認識信頼度**(注)の順に出力されます。
注：精度ではなく学習モデルの推論の「自信」を表すような数値のため注意

下記の実行時間はすべて1~3秒程度でした。
##### ①-1. 白地にテキストを貼り付けて画像サンプルとした例（横書き）
![hoso_yoko.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704655/efa240b8-dd5c-10ef-6ba1-6a4bed577bb0.png)
```bash
ppocr DEBUG: dt_boxes num : 6, elapse : 0.07370257377624512
ppocr DEBUG: cls num  : 6, elapse : 0.030840396881103516
ppocr DEBUG: rec_res num  : 6, elapse : 0.7166709899902344
ppocr INFO: [[[230.0, 16.0], [454.0, 17.0], [454.0, 34.0], [230.0, 33.0]], ('行きかふ年もまた旅人なり', 0.9934337139129639)]
ppocr INFO: [[[20.0, 17.0], [225.0, 17.0], [225.0, 34.0], [20.0, 34.0]], ('月日は百代の過客にして、', 0.9859694838523865)]
ppocr INFO: [[[20.0, 44.0], [205.0, 44.0], [205.0, 58.0], [20.0, 58.0]], ('向の上に生涯を浮力パ', 0.8449328541755676)]
ppocr INFO: [[[216.0, 43.0], [470.0, 43.0], [470.0, 57.0], [216.0, 57.0]], ('馬の口とらへて老を迎こる者は', 0.8923360109329224)]
ppocr INFO: [[[20.0, 69.0], [272.0, 69.0], [272.0, 86.0], [20.0, 86.0]], ('日々旅にして、旅をすみかとす', 0.9790313839912415)]
ppocr INFO: [[[20.0, 96.0], [239.0, 96.0], [239.0, 113.0], [20.0, 113.0]], ('古人も多く旅に死せるあり', 0.9961338043212891)]
```
精度的にはもうひと頑張り欲しかったところです。
一部間違ってしまっている箇所については信頼度が0.9を切るなどしていたため相関が見受けられました。

##### ①-2. 白地にテキストを貼り付けて画像サンプルとした例（縦書き）
![hoso_tate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704655/1b0d9926-531c-89f7-1576-4fc131721958.png)
```bash
ppocr DEBUG: dt_boxes num : 7, elapse : 0.08170223236083984
ppocr DEBUG: cls num  : 7, elapse : 0.03633451461791992
ppocr DEBUG: rec_res num  : 7, elapse : 0.5394885540008545
ppocr INFO: [[[64.0, 12.0], [86.0, 12.0], [86.0, 218.0], [64.0, 218.0]], ('月日は目代の理透にしで', 0.5689286589622498)]
ppocr INFO: [[[64.0, 226.0], [85.0, 226.0], [85.0, 456.0], [64.0, 456.0]], ('布さかみ中ちまた転人なり。', 0.5373471975326538)]
```
横書きじゃないと一気に認識精度が悪くなりますね・・・。

##### ②-1. フォントを変えた画像例
![sale1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704655/318ffce4-f1ad-ed56-40f5-dfbab8f2606d.png)
```bash
ppocr DEBUG: dt_boxes num : 1, elapse : 0.03696727752685547
ppocr DEBUG: cls num  : 1, elapse : 0.0065729618072509766
ppocr DEBUG: rec_res num  : 1, elapse : 0.05780816078186035
ppocr INFO: [[[16.0, 16.0], [198.0, 16.0], [198.0, 42.0], [16.0, 42.0]], ('SALE開催中!', 0.8850909471511841)]
```
信頼度が0.9切ってしまいましたが特に問題なく認識出来ておりますね。

##### ②-2. フォントを変えた画像例 その２
![sale2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704655/92d117a6-a609-59c0-517b-0036526c027c.png)
```bash
ppocr DEBUG: dt_boxes num : 1, elapse : 0.0354609489440918
ppocr DEBUG: cls num  : 1, elapse : 0.006449460983276367
ppocr DEBUG: rec_res num  : 1, elapse : 0.052172183990478516
ppocr INFO: [[[41.0, 12.0], [234.0, 12.0], [234.0, 52.0], [41.0, 52.0]], ('江E開催中', 0.746196985244751)]
```
斜めになると弱いですね…。

##### ③-1. 手書き画像例
あえてリラックマ
![tegaki2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704655/dba99e9c-575b-ddbf-0af9-8fc722d39a27.jpeg)
```bash
ppocr DEBUG: dt_boxes num : 3, elapse : 0.2896547317504883
ppocr DEBUG: cls num  : 3, elapse : 0.016295433044433594
ppocr DEBUG: rec_res num  : 3, elapse : 0.18599152565002441
ppocr INFO: [[[94.0, 248.0], [300.0, 251.0], [300.0, 289.0], [94.0, 286.0]], ('あいましこ', 0.5365026593208313)]
ppocr INFO: [[[90.0, 300.0], [326.0, 298.0], [326.0, 336.0], [90.0, 338.0]], ('おめとう', 0.8033647537231445)]
```
（もっとひどい精度になると考えてました）
画像下部のRilakkumaの文字が認識されていないのは残念でした…。

##### ③-2. 手書き画像例　その２

![tegaki3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704655/230b1aea-861d-7ab4-3740-ab263c12f93f.jpeg)
```bash
ppocr DEBUG: dt_boxes num : 10, elapse : 0.3454470634460449
ppocr DEBUG: cls num  : 10, elapse : 0.054414987564086914
ppocr DEBUG: rec_res num  : 10, elapse : 0.45490312576293945
ppocr INFO: [[[47.0, 38.0], [350.0, 45.0], [349.0, 88.0], [46.0, 81.0]], ('Pi0ahhuma', 0.6630345582962036)]
ppocr INFO: [[[88.0, 256.0], [303.0, 264.0], [302.0, 312.0], [86.0, 304.0]], ('しナまして', 0.6544278860092163)]
ppocr INFO: [[[90.0, 327.0], [305.0, 338.0], [302.0, 390.0], [87.0, 379.0]], ('おめでしう', 0.7687790393829346)]
ppocr INFO: [[[58.0, 776.0], [131.0, 776.0], [131.0, 797.0], [58.0, 797.0]], ('Sueet', 0.6932221055030823)]
ppocr INFO: [[[146.0, 773.0], [216.0, 777.0], [214.0, 801.0], [145.0, 797.0]], ('lovety', 0.9674060344696045)]
ppocr INFO: [[[228.0, 776.0], [357.0, 780.0], [357.0, 802.0], [228.0, 798.0]], ('Straレberr!', 0.6191608905792236)]
ppocr INFO: [[[26.0, 798.0], [49.0, 798.0], [49.0, 822.0], [26.0, 822.0]], ('ís', 0.7116761803627014)]
ppocr INFO: [[[108.0, 801.0], [209.0, 803.0], [209.0, 827.0], [107.0, 824.0]], ('Favorite.', 0.9165266752243042)]
```
「あけましておめでとう」が「しナましておめでしう」と認識されてしまいました…。
手書きは厳しい模様

### まとめ
縦書きは残念でしたが横書きできちんとした書体という条件ならば十分な認識精度を示してくれました。
PaddleOCRはGPU無しでも動く軽量なライブラリですのでご興味ある方は是非ご活用ください。

いつかファインチューニングの方法も紹介したいと思います。