やりたかったこと
- 領収書の画像をアップロード → OCRでテキスト抽出
- 店舗名・日付・合計金額・明細を正規表現でパース
- 前回の同一店舗レシートとの差分検知(価格変動アラート)
- 家計簿(LedgerEntry)への自動記帳
運用しているWebアプリに、領収書の画像をアップロードするとOCR(光学文字認識)で自動的にテキストを読み取り、家計簿に自動記帳する機能を実装しました。今回はその導入過程で経験した成功と失敗、改善の試みについて記録します。
第1段階:Tesseract OCR(失敗)
最初に選んだのは、オープンソースOCRエンジンの定番であるTesseract OCRです。pytesseractをPythonラッパーとして使用し、日本語の学習データ(tessdata)をインストールしました。
結果は散々でした。印刷された日本語テキストですら、ほぼ読み取れないレベルの精度。英数字はある程度認識できるものの、日本語の漢字・ひらがな・カタカナはほぼ壊滅的な状態でした。
第2段階:Tesseract改善の試み
Tesseractの精度向上のため、以下の対策を順番に実施しました。
tessdata_bestへの切り替え
デフォルトのtessdata_fast(約2.4MB)から、高精度版のtessdata_best(約14MB)に切り替えました。学習データの質が大幅に向上するはずでしたが、体感的な改善は限定的でした。
PSMモード(ページセグメンテーション)の最適化
Tesseractには複数のPSMモードがあり、画像のレイアウトに応じて最適なモードを選択する必要があります。PSM 3(自動)、4(単一カラム)、6(テキストブロック)、11(疎テキスト)、12(OSD付き疎テキスト)の5モードを試し、最も認識文字数が多いものを採用する方式にしました。
OpenCV前処理パイプライン
画像の前処理として、OpenCVを使った本格的なパイプラインを構築しました:
- 傾き補正(Deskew) — minAreaRectで回転角を検出し、画像を水平に補正
- CLAHE — コントラスト制限付き適応ヒストグラム均等化でコントラスト向上
- 適応的二値化 — adaptiveThresholdで照明ムラに対応した二値化
- モルフォロジー演算 — ノイズ除去と文字の連結改善
- ノイズ除去 — fastNlMeansDenoisingで最終クリーンアップ
この前処理により、認識される日本語文字数は47文字から172文字に増加しました。しかし、領収書として実用的なレベルには程遠い状態でした。
第3段階:EasyOCR導入(成功)
Tesseractでの改善に限界を感じ、ディープラーニングベースのOCRエンジンであるEasyOCRに切り替えました。
EasyOCRはCRNN(Convolutional Recurrent Neural Network)アーキテクチャをベースとしたPyTorch製のOCRライブラリで、日本語を含む80以上の言語に対応しています。
結果は劇的でした。同じ領収書画像に対して96行のテキストを検出し、日付、金額、薬品名、店舗名などが実際に読み取れるレベルの精度を達成しました。
EasyOCR実装のポイント
- シングルトンパターン — モデル読み込みは初回のみ(約1GB)で、以降はキャッシュを使用
- 信頼度フィルタ — 信頼度0.1以上の結果のみ採用(低すぎるノイズを除外)
- 位置ソート — バウンディングボックスのY座標でソートし、上から下への読み順を再現
- GPU不要 — CPU推論でも実用的な速度(1枚あたり数秒〜十数秒)
OCRエンジン比較
| 項目 | Tesseract(fast) | Tesseract(best+前処理) | EasyOCR |
|---|---|---|---|
| 日本語精度 | ほぼ不可 | 低い(172文字) | 実用レベル(96行) |
| 前処理の必要性 | 必須 | 必須 | 不要 |
| モデルサイズ | 2.4MB | 14MB | 約1GB |
| 処理速度 | 高速 | 中速 | 低速(CPU) |
| 導入の容易さ | 簡単 | やや複雑 | pip installのみ |
PaddleOCRも試してみた(断念)
EasyOCRの前に、Baidu製のPaddleOCRも試みました。インストール自体は成功したものの、PaddleOCR v3.4とPaddlePaddle v3.3の間でAPI互換性の問題が発生し、実行時にNotImplementedErrorが出て断念しました。バージョン間の互換性問題は中国発のライブラリでは珍しくないようです。
今後の展望
- GPU対応 — 将来的にGPUを利用可能になれば、処理速度が大幅に向上する見込み
- 前処理の追加 — EasyOCRでも前処理を組み合わせることで、さらなる精度向上の余地あり
- テンプレートマッチング — よく利用する店舗のレシートフォーマットを学習し、抽出精度を向上
- 差分検知の実用化 — 同一店舗での価格変動トラッキングを活用した家計管理
まとめ・学んだこと
日本語OCRの世界では、従来型のTesseractとディープラーニングベースのEasyOCRの間に大きな精度差があることを実感しました。特に領収書のような多様なフォントや複雑なレイアウトを含む文書では、ディープラーニングベースのアプローチが圧倒的に有利です。
「まず動くものを作り、段階的に改善する」というアプローチは正しかったと思います。Tesseractで基盤を作り、精度問題に直面してからEasyOCRに切り替えるという判断ができたのは、先に全体のパイプライン(OCR → パース → 差分検知 → 自動記帳)を構築していたからこそです。
OCRエンジンの選定は、精度・速度・リソース消費のトレードオフです。今回のユースケース(個人の領収書管理、リアルタイム性不要)ではEasyOCRが最適解でしたが、大量処理が必要な場合はまた別の選択肢があるでしょう。
コメント (0)
まだコメントはありません。最初のコメントを投稿してください!