GOT-OCR2でローカルAI OCRシステムを構築する:クラウド不要、サブスク不要、Pythonだけで完結

AI tutorial - IT technology blog
AI tutorial - IT technology blog

従来のOCRにおける不満

解像度の高い綺麗なPDFからのテキスト抽出は、すでに解決済みの課題です。しかし、ぼやけたスマートフォンの写真や、セルが入れ子になった表、複雑な化学式などを読み込ませた途端、Tesseractのようなツールは途端に機能しなくなります。正規表現のスクリプトやOpenCVのプリプロセッシング・パイプラインを組み合わせて、なんとか70%の精度を出そうと何時間も費やした経験は数え切れません。しかし、プロダクションレベルのアプリには、その程度の精度では不十分です。

多くの開発者は、この問題を解決するためにGoogle VisionやAWS TextractなどのクラウドAPIに頼りがちです。これらのサービスは正確ですが、毎月の利用料が発生し、プライバシー面でも大きなトレードオフがあります。機密性の高い財務記録や社内の人事書類をサードパーティのサーバーに送信することは、多くの企業プロジェクトにおいて許容されません。最近まで、私たちは「無料だが不完全」か「正確だが高価」かの二択を迫られてきました。

なぜ従来のOCRは複雑な処理に弱いのか

旧来のOCRシステムの多くは、テキストの検出と認識を、2つの別個の、かつ硬直したステップとして扱います。まずバウンディングボックス(境界線)を探し、その中の文字を推測しようとします。このアプローチは、テキストが回転していたり、チャートに埋め込まれていたり、多段組みのレイアウトに押し込まれていたりすると失敗します。これらのモデルには「視覚的コンテキスト」が欠けています。つまり、線やピクセルは見えていても、表がひとつの構造化された実体であることを理解できないのです。

GOT-OCR2 (General OCR Theory) は、OCRを「視覚と言語のタスク(vision-language task)」として扱うことで、この状況を一変させました。単にボックスを探すのではなく、統合されたトランスフォーマー・アーキテクチャを使用して、画像全体のコンテキストを「読み取り」ます。テキストが歪んだ表の中にあろうと、暗い場所で撮影された写真であろうと関係ありません。モデルは視覚入力を処理し、構造化されたテキスト出力を一度に生成します。

クイックスタート:5分でGOT-OCR2を動かす

十分なパフォーマンスを得るには、GPUを搭載したマシンが必要です。少なくとも8GBのVRAMを搭載したNVIDIAカード(RTX 3060や4060など)が最適です。CPUでも実行可能ですが、推論時間は1ページあたり1〜2秒から30秒以上に跳ね上がることを覚悟してください。

1. 環境のセットアップ

まずは依存関係を分離することから始めましょう。これにより、インストール済みの他のAIライブラリとのバージョン競合を防ぐことができます。

# 仮想環境の作成
python -m venv got_ocr_env
source got_ocr_env/bin/activate  # Windowsの場合: got_ocr_env\Scripts\activate

# コア依存関係のインストール
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install transformers tiktoken verovio accelerate

2. 実装スクリプト

これを ocr_engine.py として保存してください。このスクリプトは、Hugging Faceから直接学習済みウェイトを取得して、重い処理を実行します。

from transformers import AutoModel, AutoTokenizer
import torch

# モデルとトークナイザーの初期化
model_name = "ucasyzx/GOT-OCR2_0"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModel.from_pretrained(model_name, trust_remote_code=True, low_cpu_mem_usage=True, device_map='cuda', use_safetensors=True, pad_token_id=tokenizer.eos_token_id).eval().cuda()

def extract_text(image_path):
    # 'ocr' タイプは標準的なテキスト抽出モードです
    res = model.chat(tokenizer, image_path, ocr_type='ocr')
    return res

if __name__ == "__main__":
    image_path = "test_screenshot.png"
    print("--- 抽出されたテキスト ---")
    print(extract_text(image_path))

真の実力:構造化データのハンドリング

GOT-OCR2の汎用性は最大のセールスポイントです。単なる基本的なテキストスクレイパーではなく、構造の「解釈者」なのです。私のテストでは、特にレイアウトが非線形な場合に、このモデルは標準的なエンジンを凌駕しました。

スキャン文書のフォーマット維持

標準的なOCRでは、隣接する列のテキストを結合してしまい、支離滅裂な内容になることがよくあります。ocr_type を ‘format’ に設定することで、モデルは元のページのフローを尊重します。これは、学術論文や多段組みのニュースレターを処理する際の救世主となります。

表をMarkdownに変換する

これこそが、このモデルが真に輝く場面です。単なる単語の羅列ではなく、モデルにMarkdown形式で出力させることができます。私はこれを利用して、複雑な財務スプレッドシートを、LLMが行と列の関係性を損なうことなく理解できる構造化データに変換しています。

# きれいなMarkdown形式の表を出力します
res = model.chat(tokenizer, "table_image.png", ocr_type='format', render=True)

高度なテクニック:高精度なクロップ

巨大な設計図や高密度のフォームなど、特殊なケースに遭遇することもあるでしょう。全体スキャンで細かいディテールが欠落する場合、GOT-OCR2は「クロップOCR」が可能です。高解像度画像の特定の座標をターゲットにすることで、ほぼ完璧な精度を維持できます。

# 特定の領域をターゲットにする (x1, y1, x2, y2)
res = model.chat(tokenizer, image_path, ocr_type='ocr', ocr_box=[150, 150, 600, 600])

4K画像を論理的なゾーンに分割することで、標準的な全ページ縮小では判読不能なテキストに対しても、99%の精度を達成できます。

本番環境デプロイ時のチェックリスト

ローカルスクリプトからライブAPIに移行するには、安定性を維持するためにいくつかのハードウェアおよびソフトウェアの最適化が必要です。

  • VRAMの効率化: モデルは推論中に約5GBのVRAMを消費します。メモリが不足している場合は、大きなバッチ処理の間に torch.cuda.empty_cache() を使用して、恐ろしい「Out of Memory」エラーを防ぎましょう。
  • シングルトン・ローディング: リクエストごとにモデルをリロードしてはいけません。FastAPIのようなフレームワークを使用してメモリに一度だけロードし、リクエストに対して常に準備が整った状態を保ちます。
  • スマートな前処理: モデルは堅牢ですが、基本的な傾き補正(デスクイニング)を行うだけで、推論時間を約15%短縮できます。これは、トランスフォーマーがテキストの整列に「苦労」しなくて済むようになるためです。
  • 量子化: 古いハードウェアで実行する場合は、bitsandbytes ライブラリを介して4ビット量子化を使用してください。これにより、精度をほとんど落とすことなく、VRAMの使用量をほぼ半分に削減できます。

結論として、ローカルOCRシステムを構築することは、単なるコスト削減ではありません。それは「完全なデータ主権」を手に入れることです。自前のハードウェアでGOT-OCR2を実行することで、レイテンシを排除し、データのプライバシーを保ち、従来のツールでは太刀打ちできなかったドキュメントを処理できるようになります。これは、RAG(検索拡張生成)パイプラインや自動化されたドキュメントワークフローを構築する開発者にとって、大きなアップグレードとなるでしょう。

Share: