LESSON 30分

ストーリー

田中VPoE
Step 3で音声・動画を学んだ。次はDocument AI、つまり文書処理のAI活用だ。まずはOCR(光学文字認識)の基礎と最新技術を押さえよう
あなた
OCRって昔からある技術ですよね?最近は何が違うんですか?
田中VPoE
従来のOCRは「文字を認識する」だけだった。今はVLMの進化で、文書の「意味を理解する」レベルに達している。レイアウト解析、表の構造認識、手書き文字の読み取りまで高精度にできる
あなた
請求書や契約書の自動処理に直結しますね

OCR技術の進化

世代別の比較

世代技術特徴代表的なツール
第1世代テンプレートマッチング活字のみ、フォント依存従来のOCRソフト
第2世代機械学習ベース多フォント対応、精度向上Tesseract 4
第3世代ディープラーニング手書き対応、レイアウト解析Google Vision, Azure
第4世代VLM統合文書理解、文脈を考慮した認識Claude Vision, GPT-4o

処理パイプラインの変化

【従来のOCR】
画像 → [文字領域検出] → [文字認識] → テキスト(平文)

【最新のDocument AI】
画像 → [レイアウト解析] → [文字認識] → [構造理解] → 構造化データ
         │                              │
         ├─ 表の検出                     ├─ 表の行列構造
         ├─ 段組みの解析                  ├─ ヘッダー/フッター
         └─ 図表の分類                    └─ キーバリューペア

主要なOCRサービスとツール

サービス比較

サービス特徴日本語精度コスト目安
Google Cloud Vision OCR多言語対応、バッチ処理$1.50/1000ページ
Amazon Textract表・フォームの構造抽出中高$1.50/1000ページ
Azure AI Document Intelligenceカスタムモデル対応$1.00/1000ページ
Claude Vision文脈理解、柔軟な出力最高$3-10/1000ページ
GPT-4o文脈理解、マルチモーダル最高$3-10/1000ページ
Tesseract(OSS)無料、ローカル実行無料
PaddleOCR(OSS)高精度、多言語無料

選定基準

基準クラウドAPIVLMOSS
精度最高中〜高
構造認識高(専用機能)高(プロンプト依存)低〜中
カスタマイズ
コスト従量課金やや高い無料
セキュリティクラウド送信クラウド送信ローカル処理可
大量処理得意コスト課題得意

Tesseractによるローカル OCR

基本実装

import pytesseract
from PIL import Image

def ocr_basic(image_path: str, lang: str = "jpn") -> str:
    """Tesseractで基本的なOCR"""
    image = Image.open(image_path)
    text = pytesseract.image_to_string(image, lang=lang)
    return text


def ocr_with_details(image_path: str, lang: str = "jpn") -> list[dict]:
    """座標情報付きでOCR"""
    image = Image.open(image_path)
    data = pytesseract.image_to_data(
        image, lang=lang, output_type=pytesseract.Output.DICT
    )

    results = []
    for i in range(len(data["text"])):
        if data["text"][i].strip():
            results.append({
                "text": data["text"][i],
                "confidence": data["conf"][i],
                "x": data["left"][i],
                "y": data["top"][i],
                "width": data["width"][i],
                "height": data["height"][i]
            })
    return results

画像の前処理で精度を向上

import cv2
import numpy as np

def preprocess_for_ocr(image_path: str) -> np.ndarray:
    """OCR精度を向上させる前処理"""
    img = cv2.imread(image_path)

    # 1. グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 2. ノイズ除去
    denoised = cv2.fastNlMeansDenoising(gray, h=10)

    # 3. コントラスト強調(CLAHE)
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
    enhanced = clahe.apply(denoised)

    # 4. 二値化(適応的閾値処理)
    binary = cv2.adaptiveThreshold(
        enhanced, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
        cv2.THRESH_BINARY, 11, 2
    )

    # 5. 傾き補正
    corrected = deskew(binary)

    return corrected


def deskew(image: np.ndarray) -> np.ndarray:
    """画像の傾きを補正"""
    coords = np.column_stack(np.where(image > 0))
    angle = cv2.minAreaRect(coords)[-1]

    if angle < -45:
        angle = -(90 + angle)
    else:
        angle = -angle

    (h, w) = image.shape[:2]
    center = (w // 2, h // 2)
    matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
    rotated = cv2.warpAffine(
        image, matrix, (w, h),
        flags=cv2.INTER_CUBIC,
        borderMode=cv2.BORDER_REPLICATE
    )
    return rotated

VLMによる高度なOCR

Claude Visionでの文書読み取り

import anthropic
import base64

client = anthropic.Anthropic()

def ocr_with_vlm(
    image_path: str,
    instruction: str = "この文書の内容を正確にテキストとして書き起こしてください"
) -> str:
    """VLMで文書を読み取り"""
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode()

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": image_data
                    }
                },
                {"type": "text", "text": instruction}
            ]
        }]
    )

    return response.content[0].text


def ocr_structured(image_path: str, fields: list[str]) -> dict:
    """VLMで構造化データとして抽出"""
    fields_str = "\n".join(f"- {field}" for field in fields)

    instruction = f"""この文書から以下の情報を抽出し、JSON形式で返してください。
読み取れない項目はnullとしてください。

抽出項目:
{fields_str}

JSON形式で回答してください。"""

    result = ocr_with_vlm(image_path, instruction)
    import json
    return json.loads(result)


# 使用例: 名刺からの情報抽出
card_info = ocr_structured("business_card.jpg", [
    "氏名", "会社名", "部署", "役職",
    "電話番号", "メールアドレス", "住所"
])

OCR精度の評価

評価指標

指標説明計算式
CER文字誤り率編集距離 / 正解文字数
WER単語誤り率編集距離 / 正解単語数
正解率正しく認識された文字の割合正解数 / 全文字数
フィールド正解率構造化抽出の正解率正解フィールド / 全フィールド

精度向上のアプローチ

アプローチ説明効果
画像前処理傾き補正、ノイズ除去、二値化+5-15%
複数エンジン併用Tesseract + VLMの結果を統合+5-10%
カスタム辞書業界用語・社内用語の辞書追加+3-5%
後処理正規表現でパターン修正+2-5%
ファインチューニング自社文書でモデルを追加学習+10-20%

まとめ

技術概要推奨ツール
基本OCR文字の認識Tesseract, PaddleOCR
クラウドOCR高精度 + 構造認識Google Vision, Amazon Textract
VLM OCR文脈理解を含む高度な認識Claude Vision, GPT-4o
前処理画像品質の向上OpenCV, Pillow

チェックリスト

  • OCR技術の進化(テンプレートマッチング → VLM統合)を説明できる
  • 主要なOCRサービスの特徴とコストを比較できる
  • Tesseractを使った基本的なOCR処理を実装できる
  • VLMを使った構造化データ抽出を実装できる
  • OCR精度の評価指標(CER, WER)と精度向上手法を理解した

次のステップへ

次は文書理解(Document Understanding)の技術を学びます。


推定読了時間: 30分