📑

OpenAI OCR × FastAPI × JavaScriptで作るスキャンレス読取 Web アプリを作ってみた

に公開

こんにちは、まめです。

最近「紙の伝票をスマホで撮ったら自動でOCRして綺麗な帳票にしてくれる仕組みほしいよね?」という相談を受けることが増えてきました。

そこで今回は OpenAI の Vision OCR を使って、FastAPI × JavaScript で“かざすだけで読み取れる Web アプリ” を作ってみます。

ポイントは以下の通り:

  • アプリ側でシャッター不要(ライブカメラ映像をそのまま送信)
  • OpenAI の高精度 OCR で手書き伝票もOK
  • 取得したテキストを PDF 帳票に埋め込んで出力
  • インストール不要の Web アプリで動作

本記事では 最小構成で動く実装 を紹介します。


🔧 1. 全体構成

ユーザーのスマホ / PC カメラ
        ↓(画像送信)
    FastAPI サーバ
        ↓(OCR)
    OpenAI Vision API
        ↓(解析結果)
    FastAPI → PDF 出力

     ブラウザへ返却

ポイント:

  • フロントは JavaScript のみ
  • バックは FastAPI (Python)
  • OCR は OpenAI Vision API
  • PDF整形は reportlab / fpdf など任意

📸 2. フロントエンド(ブラウザ)

カメラを起動して画像を送信するだけの最短コード

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OCR Web App</title>
</head>
<body>

<video id="camera" autoplay playsinline width="300"></video>
<button id="send">読み取り</button>

<script>
async function startCamera() {
  const stream = await navigator.mediaDevices.getUserMedia({ video: true });
  document.getElementById("camera").srcObject = stream;
}

async function captureAndSend() {
  const video = document.getElementById("camera");
  const canvas = document.createElement("canvas");
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  canvas.getContext("2d").drawImage(video, 0, 0);

  const blob = await new Promise(resolve => canvas.toBlob(resolve, "image/jpeg"));

  const formData = new FormData();
  formData.append("file", blob, "capture.jpg");

  const res = await fetch("http://localhost:8000/ocr", {
    method: "POST",
    body: formData
  });

  const data = await res.json();
  alert(data.text);
}

document.getElementById("send").onclick = captureAndSend;
startCamera();
</script>

</body>
</html>

これだけで “シャッターいらずの撮影 & OCR送信” が成立する。


🧠 3. FastAPI(バックエンド)

画像を受け取り → OpenAI OCR → テキスト返却

from fastapi import FastAPI, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from openai import OpenAI
import base64

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

client = OpenAI()

@app.post("/ocr")
async def ocr(file: UploadFile):
    img_bytes = await file.read()
    b64 = base64.b64encode(img_bytes).decode()

    prompt = [
        {
            "role": "user",
            "content": [
                {"type": "input_text", "text": "画像の文字を正確に読み取ってください"},
                {"type": "input_image", "image_url": f"data:image/jpeg;base64,{b64}"}
            ]
        }
    ]

    res = client.responses.create(
        model="gpt-4o-mini",
        input=prompt
    )

    text = res.output_text

    return {"text": text}

これで
フロント → FastAPI → OpenAI → テキスト返却 の流れが完了。


🧾 4. OCR結果を PDF 帳票にはめる(オプション)

伝票フォーマットをあらかじめ PDF として持っておき、
OCR結果だけ埋め込む構成も簡単に作れる。

例:fpdf を使った最小実装。

from fpdf import FPDF

def make_pdf(text: str, save_path="output.pdf"):
    pdf = FPDF()
    pdf.add_page()
    pdf.set_font("Helvetica", size=12)
    pdf.multi_cell(0, 10, txt=text)
    pdf.output(save_path)

OCR後に呼び出すだけ。


📐 5. "かざすだけで読み取る" を実現するポイント

Zenn 読者向けに技術的なポイントもまとめておく:

✔ 高FPSでキャプチャしすぎない

  • 1〜2秒間隔程度で撮影することで負荷を抑える
  • 読み取れたら API リクエスト停止する仕組みがベスト

✔ 視認性を上げるための補正

  • 明るさ調整
  • コントラスト補正
  • トリミング(紙部分のみ抽出)

※OpenAI OCRは補正なしでも強い。

✔ スマホブラウザで完結

インストール不要なので、現場で導入しやすい。


🚀 6. まとめ|業務で本当に使えるOCR Webアプリが作れる

今回紹介した構成で実現できること:

  • 手書き伝票でも高精度なOCR
  • カメラをかざすだけで読み取り
  • Webアプリのみで動作(スマホアプリ不要)
  • PDF帳票まで自動生成できる

実務で「紙 → デジタル化」のニーズは確実に増えています。
FastAPI と OpenAI を組み合わせるだけで、
企業レベルのOCRアプリが個人でも簡単に作れる時代 になりました。


✨ 次回書くならこのへんも深掘りできます

  • 文字位置(座標)も抽出して帳票にマッピング
  • 伝票レイアウト(枠線付き)を自動生成する
  • PDF をメール送信 or データベース保存
  • ストリーミングOCR(動画→リアルタイム認識)

Discussion