⚰️

PythonでOCRを実装してみた。そしてもうそんな時代じゃなかった💮

に公開3

はじめに

どうしてもデジタル化が難しい紙のアンケートがあった。
複数ページにわたる表形式で、手書きの数字を一つずつ書き込んでもらうのだ。
それを回収し、集計しなければならない。

手入力なんてやっていられない。
だから、スキャンしてPythonでOCR処理をしてみることにした。

PythonでOCRを実装する

使ったのは、オープンソースのOCRツールTesseract OCR。導入方法など詳しくはこちらの記事等を参考にして欲しい。

今回は書式が統一されており、読み込みたい位置も固定されているので、前処理を工夫することで精度を上げることに努めた。
具体的には、処理したい表部分だけを切り取り、セルごとに分割、色を調整しOCR処理をかけた。

mycode.py
import fitz
import pytesseract
import pandas as pd
from PIL import Image, ImageEnhance
import io

# Tesseractのパス
pytesseract.pytesseract.tesseract_cmd = r'C:\Users\Users001\AppData\Local\Programs\Tesseract-OCR\tesseract.exe'

pdf_path = 'input.pdf'
output_csv = 'output.csv'

# 表のクロップ範囲
table_left, table_top, table_right, table_bottom = 330, 265, 735, 490
n_rows = 5
n_cols = 6

cell_width = (table_right - table_left) // n_cols
cell_height = (table_bottom - table_top) // n_rows

doc = fitz.open(pdf_path)
all_data = []

for page_num in range(len(doc)):
    page = doc.load_page(page_num)
    pix = page.get_pixmap()
    img_bytes = pix.tobytes("png")
    image = Image.open(io.BytesIO(img_bytes))

    print(page) #進捗確認用

    # 各セルごとにOCRをかける
    page_table = []
    for row in range(n_rows):
        row_data = []
        for col in range(n_cols):
            x1 = table_left + col * cell_width
            y1 = table_top + row * cell_height
            x2 = x1 + cell_width
            y2 = y1 + cell_height
            cell_img = image.crop((x1, y1, x2, y2))

            # セル画像の周囲10%をトリミング(罫線を除去)
            w, h = cell_img.size
            trim_x = int(w * 0.1)
            trim_y = int(h * 0.1)
            cell_img = cell_img.crop((trim_x, trim_y, w - trim_x, h - trim_y))

            # 2倍に拡大(Tesseractは大きめの画像の方が精度が上がるため)
            cell_img = cell_img.resize((w*2, h*2))

            enhancer = ImageEnhance.Contrast(cell_img)
            cell_img = enhancer.enhance(2.0)  # コントラスト2倍

            cell_img = cell_img.convert('L')  # グレースケール
            # 2値化(閾値128)
            bw = cell_img.point(lambda x: 0 if x < 128 else 255, '1')

            # 数字のみOCR, PSM 7(単一行)
            custom_config = '--psm 7 -c tessedit_char_whitelist=0123456789'
            cell_text = pytesseract.image_to_string(bw, lang='eng', config=custom_config)
            cell_text = cell_text.strip()
            row_data.append(cell_text)
        page_table.append(row_data)
    # ページ番号を先頭に追加
    for row in page_table:
        all_data.append([page_num + 1] + row)

# データフレーム化
columns = ['ページ'] + [f'列{i+1}' for i in range(n_cols)]
df = pd.DataFrame(all_data, columns=columns)
df.to_csv(output_csv, index=False, encoding='utf-8-sig')
print(f'CSVファイルを出力しました: {output_csv}')

出力は出た。だが、読めない。

「7」が「1」になり、「3」が「8」になる。
ちゃんと画像処理が上手くいっているか、出力してみて確認までしたw

けど実務ではとても使えない、体感50%も上手くいってなくて、精度の壁にぶつかった。

Tesseractの限界だと感じた。
機械学習?、Google Cloud VisionやAzure Cognitive Servicesなどの有料APIを使う?

けれど、ちょっとしたアンケートの集計に毎回コストをかけるのは現実的じゃない。
この時点で「PythonでOCR」は、実用的な手段としては行き止まりだった。

ふと思いついた:AIにそのままPDFを投げてみる

諦めかけたその時、ふと頭をよぎった。

「あれ、もしかしてChatGPTにそのままPDFぶっこんだら読めるんちゃう?」

やってみた。
結果は、驚くほどの精度だった。

二重線で修正した数字や、小さな書き込みまで識別し、
なによりアンケートの構造を理解して回答者ごとに整理してくれた。

確かに、潰れた文字や集計の一部は間違っていた。
それでも、目的だった「紙アンケートのデータ化」は完全に達成された。

コードを書くという錯覚

おかしかったのは、最初にこのPythonコード自体もAIに書かせていたことだ。
私は「自分で実装している」と思い込みながら、
実際にはAIに段取りを聞き、構文を生成してもらっていた。

気づけば、私は“書く人”ではなく“設計を委ねる人”になっていた。
PythonでOCRを実装することよりも、どういう結果を得たいのかを伝えることの方が重要だった。

そして、もうそんな時代じゃなかった

簡単なアプリやOCRツールを作ることに価値はあるのか。
AIはもう、コードやAPIを超えて、タスクそのものを理解して実行してくれる。

Pythonでは読めなかった文字を、AIは読んだ。
コードでは理解できなかった構造を、AIは把握した。

目的を達成するために手段を設計する考えが古かった

これまでのエンジニアリングは、「目的を達成するために手段を設計する」という構造だった。

  • 何をしたいか? → Pythonでどうやって書こうか。
  • OCRしたい → どうやって前処理すれば認識精度が上がる?
  • 自動化したい → どのAPI使えば最適なのか

つまり、人が目的と手段の両方を握っていた。
ところが、手段の部分がどんどん自動化され、もはやどう実装するか?を考える時間がコストそのものになっている。

AIが手段を内包する

AIはすでにコードを理解し、画像を解析し、文章を要約し、数値を分析できる。
しかもそれを統合的に行える。

つまりAIに対して、「何をしたいか」さえ明確に伝われば、そのための具体的な手段は補完してくれるのだ。

この時、人はもはや手段を選ぶ存在ではなく、目的を提示する存在になっている。

おわりに

PythonでOCRを実装してみた。
そして気づいた。
もう、そんな時代じゃなかった。

Discussion

tuzumi minami (TM)tuzumi minami (TM)

記事拝見させていただきました。
ここでいう”AI”とは、モデルは何になるのでしょうか?
APIモデルではなく、Hugging FaceなどにあるLLMモデルでしょうか?
image-text-to-textモデルのことでしょうか?

け

コメントありがとうございます。
情報が不足しており申し訳ございませんでした。🙇‍♂️
ここで最後に頼ったAIはchatgptです。
簡単なものなら専用のAPIやモデルを使わずとも解決できてしまう。そんな衝撃と、自分のAIに対する認識・知識不足を戒める、そんなことを伝える目的の内容でした。