本文へスキップ
BecomeCoder

Python画像認識コース · 第6章 実践とその先 · レッスン21

認識結果の後処理 ― 正規表現でクレンジング

ブラウザで完結

導入

OCR の出力は、たいてい少し“汚れて”います。余計な空白、O(オー)と 0(ゼロ)の混同、想定外の記号——。これらをルールで整える 後処理 まで含めて、はじめて使えるデータになります。ここは Python 標準の re(正規表現)だけで書け、ブラウザでも実行できます。

説明

import re

# OCRが返したと想定した“生の”文字列(ノイズ入り)
raw = """
  合計   1,280 円
電話: O3-1234-5678
  

日付 2026/07/29
"""

# 1) 前後の空白を整え、空行を除く
lines = [ln.strip() for ln in raw.splitlines() if ln.strip()]

# 2) 全角数字を半角へ、桁区切りカンマを除去
def to_number(s):
    s = s.translate(str.maketrans("0123456789", "0123456789"))
    return s.replace(",", "")

# 3) 各行から欲しい情報を正規表現で抜き出す
for ln in lines:
    ln = to_number(ln)
    if "合計" in ln:
        m = re.search(r"(\d+)\s*円", ln)
        if m:
            print("金額:", int(m.group(1)))
    if "電話" in ln:
        # OCRが 0 を O と誤読しがち → 数字の文脈で O を 0 に直す
        fixed = re.sub(r"(?<=\D)O(?=\d)|(?<=\d)O", "0", ln)
        m = re.search(r"[\d\-]{9,}", fixed)
        if m:
            print("電話:", m.group(0))
    m = re.search(r"(\d{4})/(\d{2})/(\d{2})", ln)
    if m:
        print("日付:", m.group(0))
  • str.strip() と空行除去で、まず行を整えます。
  • str.maketrans全角数字→半角へ一括変換。OCR は全角・半角を取り違えることがあります。
  • re.search(r"(\d+)\s*円", ln) … 「数字+円」を探し、金額だけを取り出します。
  • re.sub(...) で、数字の並びに紛れた O(オー)を 0(ゼロ)へ補正。誤読の癖をルールで吸収するのが後処理の勘所です。

「エンジンの精度を上げる」だけでなく「出力を賢く直す」——両輪で実用精度に近づけます。

やってみよう

raw の中身を書き換えて(別のレシート風テキストにして)、抜き出される金額・電話・日付が変わることを確かめましょう。正規表現 r"(\d+)\s*円" を調整すると、拾える形式を増やせます。

演習

raw郵便 〒150-0002 のような行を足し、そこから 郵便番号(150-0002 の形) を正規表現で抜き出して print してください。

ヒント1を見る

m = re.search(r"\d{3}-\d{4}", ln) で「3桁-4桁」を探せます。

ヒント2を見る

ループ内に if m: print("郵便:", m.group(0)) を足します。全角の場合は to_number の対象を広げるか、先に半角化します。

実際に動かしてみよう

下のエディタにPythonを書いて「実行」を押すと、本物の Pillow・OpenCV(Pyodide)で画像処理をその場で試せます。処理した画像は図として下に表示されます。初回や OpenCV を使う回は読み込みに時間がかかります(数十秒かかることがあります)。しきい値やフィルタの数値を書き換えて、画像の変化を確かめましょう(画像に描く文字は表示が崩れるため英字で書きます。Tesseract などOCRエンジン本体は第5章の読み物で解説します)。

Python — ライブラリ付きで実行(Pyodide)

numpy / pandas / matplotlib が使える本物のPython(Pyodide)を読み込みます。初回のみ読み込みに少し時間がかかります(以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。