OCR を軽く触ってみた

# 初めに

とある案件で財務諸表(ざいむしょひょう)を OCR で解析する必要が出てきたので OCR について調べたり簡単にサンプルを動かしてみました。
- いくつかの OCR サービスの比較(主にランニングコスト面)
- Microsoft Azure Computer Vision で動かしてみた感想

についてまとめています。

## 財務諸表(ざいむしょひょう)とは

https://biz.moneyforward.com/accounting/basic/21688/ より
> 財務諸表とは、一般的に決算書といわれる書類のうち、金融商品取引法で上場企業などに作成が義務付けられている書類のことです。その中でも、貸借対照表、損益計算書、キャッシュフロー計算書の3つを特に「財務三表」といいます。

# OCR(光学文字認識 Optical Character Recognition) とは

[wiki](https://ja.wikipedia.org/wiki/%E5%85%89%E5%AD%A6%E6%96%87%E5%AD%97%E8%AA%8D%E8%AD%98) より

> 光学文字認識（こうがくもじにんしき、英:Optical character recognition）は、活字、手書きテキストの画像を文字コードの列に変換するソフトウェアである。画像はイメージスキャナーや写真で取り込まれた文書、風景写真 (風景内の看板の文字など)、画像内の字幕 (テレビ放送画像内など)が使われる[1]。一般にOCRと略記される。

# OCR サービス

国内、国外でいくつか候補が見つかりました。

大前提として

- 日本語文字を扱える
- API 経由で実行できる

の条件を満たすものの中で、

- ランニングコスト
- API の使いやすさ
- PHP で実装する際の手間

を比較してみました。


## 比較表

詳細は後述していますが、かんたんに全体を表にまとめます。
1ヶ月あたり 5 ページで構成される PDF を 8500 件処理すると仮定して料金の比較を行っています。

|サービス名|運営元|料金体系|毎月 8500 件の PDF を処理するとなると|PHP での実装の手間|
|--|--|--|--|--|
|AWS Amazon Textract|Amazon|--|--|--|
|Google Cloud Vision API|Google|基本料金なしの従量課金制|63 ドル|・PHP ライブラリが公開されている<br>・ファイルの URL をパラメータに指定するので、ストレージサービスの併用が必要|
|Google Drive 上での変換|Google|--|--|・精度は低い|
|Microsoft Azure Computer Vision|Microsoft|基本料金なしの従量課金制と一定量利用できる基本料金 + 超過分の追加請求の 2 通りの契約方法|42.5 ドル|・PHP ライブラリが公開されていない<br>・バイナリファイルをパラメータに指定できるので、ストレージサービスの併用が不要|
|ABBYY Cloud OCR SDK|ABBYY|一定量利用できる基本料金 + 超過分の追加請求|839.99 ドル以上(要問い合わせ)|・料金は高め<br>画像送信、タスク作成、タスク実行、結果取得と複数の API を組み合わせる必要あり|
|DX Suite|AI inside|初期費用と一定量の無料枠付きの従量課金制の組み合わせ|約 900,000 円|・料金は高め<br>・読み取り精度はだいぶ高そう|
|LAQOOT|ユニメディア|初期費用がかかる + 一定量利用できる基本料金 + 超過分の追加請求|2,500,000 円超|・料金は高め<br>・読み取り精度はだいぶ高そう|

料金や文字認識率、気軽に動作確認できそうか？あたりで考えると

`Microsoft Azure Computer Vision` > `Google Cloud Vision API` >>>>>> `ABBYY Cloud OCR SDK` = `DX Suite` = `LAQOOT`

の順序で比較検討するのが良さそうな感じでした。

## AWS Amazon Textract

https://aws.amazon.com/jp/textract/faqs/
> A: Amazon Textract は、標準的な英語のアルファベットと ASCII 記号を使用している、印刷されたテキストもしくは手書きの文字を検出できます。また Textract では、スペイン語、イタリア語、フランス語、ポルトガル語、ドイツ語で印刷された、テキストの抽出にも対応しています。

現時点では日本語に対応していませんが、有名どころなので一応記載しておきました。

## Google Cloud Vision API

### 概要・参考サイト

[画像分析サービスで、OCR もできる](https://qiita.com/shoku-pan/items/f0aeca881f7183651a7b)

[画像ファイルを読み込んだ例だけど、結構精度高い様子](https://dev.classmethod.jp/articles/google-cloud_vision-api/)

### 料金

[基本料金なしの従量課金制](https://cloud.google.com/vision/pricing)

OCR 関連の機能は 2 つあり、どちらも画像 1 枚あたりに料金が発生します。
- TEXT_DETECTION
画像ファイル全般で利用できる
- DOCUMENT_TEXT_DETECTION
PDF, TIFF での利用に適している

画像 1 枚あたりに料金が発生し、PDF の場合は 1 ページが 1 画像とみなされます。
1 画像に適用する機能を「ユニット」と呼ばれる単位で計算します。
例えば、ある画像に顔検出と OCR を実施した場合はそれぞれに 1 ユニットずつ使用したとして料金が計算されることとなります。

また、機能ごとに 1000 ユニットまでは無料で使用できるので、PDF の OCR を実施した場合、1000 ページまでは無料となります。
1000 ユニット以降は、5,000,000 ユニットまでは 1000 ユニットごとに 1.5 ドルとなるので、
例えば 8500 PDF ファイルで、5 ページ平均とすると 42500 ユニットとなります。
|区分|ユニット数|料金|
|--|--|--|
|0|   0 ~ 1000|無料|
|1|1001 ~ 2000|1.5 ドル|
|2|2001 ~ 3000|1.5 ドル|
|...|...|
|42|42001 ~ 43000|1.5 ドル|

合計 63 ドル となる計算です。


### 実装面での比較

https://cloud.google.com/vision/docs/pdf

- PHP 用のライブラリ
公開されているので実装は楽です。
- 1 ファイルあたりのサイズ上限
2000 ページまで対応しています。
- リクエストパラメータにバイナリを指定できるか？
できません。
Goocle Clound Storage に PDF を保存して、そちらのパスをリクエストパラメータに指定します。
	> ドキュメント テキスト検出リクエスト
	> 現在のところ、PDF や TIFF ドキュメントの検出は Cloud Storage バケットに保存されているファイルに対してのみ実行できます。レスポンスの JSON ファイルも Cloud Storage バケットに保存されます。
- ストレージサービスの併用
OCR 結果は Cloud Storage に JSON で保存されるので、単純に Cloud Vision API を使うだけでなく、いくつかの Google の API を利用することになります。
	1. Cloud Storage に PDF ファイルを保存
	2. Cloud Vision API 実行
	3. OCR 結果 JSON を Cloud Storage から取得
	4. Cloud Storage 内の使用済みの PDF, OCR 結果 JSON を一定間隔で破棄
- 同期 / 非同期処理
原則同期処理だが、キューに詰めて非同期で処理させることも可能です。

## Google Drive 上での変換

PDF をアップロードし、Google Document で開く(変換)してその中からテキストを抽出するやり方です。
API 経由で実行できるかはさておき、精度がきになるところなので先に確認してみます。

適当な

- 損益計算書
- 貸借対照表

で実験してみましたが、全然読み取れませんでした。
1 文字ごとに改行されたりして、どの見出しと数値がペアになるのか全くわかりません。

## Microsoft Azure Computer Vision

### 概要・参考サイト

[Computer Vision の中の Read API](https://docs.microsoft.com/ja-jp/azure/cognitive-services/computer-vision/vision-api-how-to-topics/call-read-api) を使う

### 料金

[基本料金なしの従量課金制と一定量利用できる基本料金 + 超過分の追加請求の 2 通りの契約方法](https://azure.microsoft.com/ja-jp/services/cognitive-services/computer-vision/#pricing)

時間あたりの API 実行数と、毎月どれだけ API を実行したかで計算されます。
1 分あたり 20 回の実行と、毎月 5000 回までなら無料ですが、それを超える場合は有料になります。
自動的に有料に切り替わるのではなく、無料と有料でそもそもコンテナと呼ばれる契約単位が異なるので、事前に使用量を予想して適切なコンテナで契約する必要があります。
無料コンテナで利用回数の上限に達した場合にどうなるかは不明ですが、おそらくはそれ以上は API の実行が行えないと思います。

PDF についての OCR の場合は、ファイルではなくページに対してトランザクションという単位で料金が発生します。
例えば 8500 PDF ファイルで、5 ページ平均の場合は 42500 トランザクションとなります。
[料金シミュレーション](https://azure.microsoft.com/ja-jp/pricing/calculator/?service=cognitive-services)で計算してみると
- 基本料金のなしの従量課金制
42.5 ドル
- 一定量利用できる基本料金 + 超過分の追加請求
一番安いプランで、毎月 500000 回利用できるプランなのでそちらを選択。超過はまず無いと考ると
338 ドル

毎月の使用量が少ないのであれば基本料金なしの従量課金制のほうがお得になります。

### 実装面での比較

- PHP 用のライブラリ
[公開されていない](https://docs.microsoft.com/ja-jp/azure/cognitive-services/computer-vision/quickstarts-sdk/client-library?tabs=visual-studio&pivots=programming-language-rest-api)
- 1 ファイルあたりのサイズ上限
[2000 ページまで対応している。ファイルサイズは 50MB 以下](https://docs.microsoft.com/ja-jp/azure/cognitive-services/computer-vision/overview-ocr)
- リクエストパラメータにバイナリを指定できるか？
[できる](https://westus.dev.cognitive.microsoft.com/docs/services/computer-vision-v3-2/operations/5d986960601faab4bf452005)
  > Input passed within the POST body. Supported input methods: raw image binary or image URL.
- 48 時間で画像というか結果確認用 URL が無効になるようなのでロールバックや定期的な破棄も不要
- ストレージサービスの併用
原則不要。リクエストパラメータに画像 URL を指定することも可能で、その場合は Azure Storage も必要になる。
- [レスポンスのオブジェクトの詳細](https://docs.microsoft.com/ja-jp/rest/api/computervision/3.1/get-read-result/get-read-result#readresult)

## ABBYY Cloud OCR SDK

### 概要・参考サイト

[ABBYY FineReader](https://www.abbyy.com/ja/finereader-server/features/) というのもあるけど、そっちは PC にインストールして使うタイプです。

[API 利用する場合は](https://www.abbyy.com/ja/flexicapture/features/)
API 名は [ABBYY Cloud OCR SDK](https://ocrsdk.abbyy.com/jp/documentation/)

### 料金

公式ページからのリンクは見当たらなかったが、[実際に利用してみたというブログ](https://a244.hateblo.jp/entry/2017/03/20/053000)からたどり着けました。

[一定量利用できる基本料金 + 超過分の追加請求](https://www.abbyy.com/cloud-ocr-sdk/licensing-and-pricing/)
8500 PDF ファイルで、5 ページ平均で 42500 ページの場合は要問い合わせとなります。
料金表に表示されている中で最大量なのは 30000 ページまでで、その場合は 839.99 ドルで少し高めの印象です。

一応無料プランもあるので、事前に文字認識率を確認することはできそうです。

### 実装面での比較

- PHP 用のライブラリ
[公開されていない](https://ocrsdk.abbyy.com/jp/documentation/code-samples/)
- 1 ファイルあたりのサイズ上限
見当たりませんでした。
- リクエストパラメータにバイナリを指定できるか？
[できる](https://ocrsdk.abbyy.com/jp/documentation/api-reference/submit-image-method/)
  > 画像ファイルはリクエスト本文で送信されます。 対応している入力形式のリストをご覧ください。
- API 数が多い
1 API で終わるのではなく、画像送信、タスク作成、タスク実行、結果取得と何回か API を実行しなければいけないので、万が一エラーが発生した場合のロールバックが大変そうです。

## DX Suite

### 概要・参考サイト

[OCR に特化したサービスの様子](https://dx-suite.com/)

### 料金

https://dx-suite.com/price/

初期費用と一定量の無料枠付きの従量課金制の組み合わせです。

- 1 リクエストあたりに料金がかかる
API のリクエストではなく、リクエストというのはサービス独自の単位です。
ファイル内の文字が入力されているかたまりを 1 リクエストとしてカウントします。
- 速度優先の読み取りと精度優先の読み取りの 2 種類があり、後者のほうが高い
- プランの違いは以下
  - 公式サポートが付くか？
  - 月額費用が高いものにすれば、1 リクエストあたりの単価が安くなるのでたくさん使う人は月額費用が高いプランのほうがお得

使用するのは精度優先のみとして、1 ページあたりの平均リクエストが予想できないですが、仮に 100 としてみます。
8500 PDF ファイルで、5 ページ平均で 42500 ページで計算してみます。

選択できるプランは 3 種類あり、シミュレーション結果は以下の通りです。
- 1 リクエストあたりの単価 * 1 ページあたりの仮定リクエスト数(100) * 想定ページ数(8500 * 5)
- 1 ページあたりの単価 * 想定ページ数
- そこから無料枠分を割引
```
DX Suite Lite       ¥15,282,000
DX Suite Standard   ¥ 6,750,000
DX Suite Pro        ¥ 6,600,000
```
計算ミスかもしれないですが、かなり高めです。
更に上記とは別に初期費用もかかってきます。

### 実装面での比較

[PDF のドキュメントがダウンロード可能](https://docs.microsoft.com/ja-jp/azure/cognitive-services/computer-vision/quickstarts-sdk/client-library?tabs=visual-studio&pivots=programming-language-rest-api)
- PHP 用のライブラリ
公開されていない
- 1 ファイルあたりのサイズ上限
100 ページまで対応していて、ファイルサイズは 20MB 以下です。
- リクエストパラメータにバイナリを指定できるか？
できます。
- ストレージサービスの併用
不要です。
- 処理時間が結構掛かる
精度優先だと 140パーツ(リクエストのこと？)で 15 秒前後かかるようです。

## LAQOOT

### 概要・参考サイト

https://laqoot.com/
> 活字だけでなく、手書き文字でも理論上100％のデータ化精度を実現。

読み取り精度はかなり高そうです。

### 料金

よくある質問を見ると料金表はなく、個別に問い合わせなければいけないようです。
が、[ニュースサイトに料金表と思われるものが掲載されていました](https://prtimes.jp/main/html/rd/p/000000042.000029291.html)

初期費用がかかる + 一定量利用できる基本料金 + 超過分の追加請求
の形式です。

8500 PDF ファイルで、5 ページ平均で 42500 ページで計算してみます。

- 1 ページあたりの単価 * 想定ページ数(8500 * 5)
- そこから無料枠分を割引

```
ミニ            ¥4,250,000
ライト          ¥3,212,500
スタンダード    ¥2,550,000
```
計算ミスかもしれないですが、かなり高めです。

### 実装面での比較

公開されている資料が見当たりませんでした。


# 実際に Microsoft Azure Computer Vision で OCR を行ってみて

いくつか財務諸表のサンプルを用意して、それらを OCR にかけてみました。
感想は以下のとおりです。

## 思ったより正確に文字が読み取れる

全角文字も結構正確に読み取れていました。

## 読み取るファイルについてきっちりとしたファーマットがない場合は扱いが難しい

今回取り扱う財務諸表についてはきっちりとしたフォーマットがなく、会計ソフトから出力されたり完全自作のフォーマットで作成されていたりします。
例えば、会計ソフトA では 2 列で出力されるのに、会計ソフトB では 3 列で出力されるといったフォーマットの違いがあります。
文字や数値自体は抽出できるのですが、こういったフォーマットの違いがあると、
これは金額だからシステムに取り込む、これは見出し部分だからシステムに取り込まない
という振り分けが出来ません。

### 文字や数値は抜き出せても、それらをどう取り込むか？という部分が難しい

PDF 内のセル(枠線)は無視されて、左上から右下に順に文字の固まりを探して抽出していきます。
例えば
```
    2022年度の予算　　　　　　　　　2022/04/01
    　　　　　　　　　　　　　　単位：百万円
        XXXX費　　　10,000
    　　YYYY費　　　10,000
```
という内容だった場合
```php
[
    '2022年度の予算',
    '2022/04/01',
    '単位：百万円',
    'XXXX費',
    '10,000',
    'YYYY費',
    '10,000'
]
```
と抽出されます。

```
予　　算
```

の様に全角スペースなどでレイアウトが調整されている場合、

```php
[
    '予',
    '算',
]
```

と別の固まりで抽出されたり、

```
xxx    kkkkkkk
```

の様に文字の高さが異なるとより高い位置にあるものが先に抽出されるので、

```
[
    'kkkkkkk',
    'xxx',
]
```

と人間の目には後に登場しているようにみえる `kkkkkkk` が先に抽出されてしまいます。

# まとめ

OCR 自体はいろんなサービスもあり、無料で始められるものもあるのでどれくらいの精度で読み取れるのかは簡単に試すことが出来ましたが、
読み取った文字や数値を使ってどんなサービスを提供するか？という部分には
- 読み取った結果を手動で修正できるようにする
- 読み取り対象となる PDF について、対応しているフォーマット、出力元となるサービスを限定する

などの工夫が必要そうです。