python:tkinterで範囲を選択し、その範囲内の文字をpyocrで文字認識


・画像の好きな範囲を指定して、文字認識したい。

理由
①紙資料のデジタル化促進の手段の1つとして、知りたい
 見積書とか、FAXとか紙ベースの資料は多い。(主観ですが、主に地方)
②無料で行いたい。
 いきなり有料の製品を使う度胸はありませんので、まず有用性を無料で知る。

参考 Qiita記事

tkinterで画像の範囲指定する方法
https://qiita.com/hisakichi95/items/47f6d37e6f425f29c8a8
pyocr,tesseractの使い方
https://qiita.com/nabechi6011/items/3a367ca94dbd208efcc7

・内容

1.OCRを行いたい画像を読み込む
2.その画像の中でさらに読み込みたい文字の範囲を指定する(下画像の赤枠)
3.赤枠の範囲を切り取り、新たな名前をつけて保存する
4.保存したデータを1つずつ順にOCRを実行する

範囲を指定したときの画像

・コード

①内容の1.~3.の内容

tkinter,画像の処理
import tkinter
import glob
from PIL import Image
import shutil
import os

#範囲を指定して切り取った画像の保存場所:"ocr_images"
#古い画像を削除するため、毎回フォルダ毎削除し、再度フォルダを作成
shutil.rmtree("ocr_images")
os.makedirs("ocr_images")

#OCRを行いたい、未処理の画像の保存場所:"images"
pngs = glob.glob("images/*.png")
img1 = Image.open(pngs[0])
W,H = img1.size

#指定範囲した画像に名前をつける番号:cnt
cnt = 1

#コールバック関数:タッチパッドを押した時
def Push(event):
    global x_start,y_start
    x_start = event.x
    y_start = event.y
    canvas.create_rectangle(x_start,y_start,x_start+1,y_start+1,outline="red",tag="rect")

#コールバック関数:タッチパッドから指を離したとき
def Release(event):
    global x_end,y_end,cnt
    x_end = event.x
    y_end = event.y
    canvas.create_rectangle(x_start,y_start,x_end,y_end,outline="red")
    img = Image.open(pngs[0])
    img.crop((x_start,y_start,x_end,y_end)).save(f"ocr_images/{cnt}.png")
    cnt = cnt + 1

#コールバック関数:タッチパッド上で指を動かしている時
def Motion(event):
    x_end = event.x
    y_end = event.y
    canvas.coords("rect",x_start,y_start,x_end,y_end)

#tkinterで画像の表示を行う
root = tkinter.Tk()
root.attributes("-topmost",True)
root.title("image select")

canvas = tkinter.Canvas(root,width=W,height=H,bg="black")
gazou = tkinter.PhotoImage(file=pngs[0])

canvas.create_image(int(W/2),int(H/2),image=gazou)
canvas.pack()

#コールバック関数の設定
root.bind("<ButtonPress-1>",Push)
root.bind("<ButtonRelease-1>",Release)
root.bind("<Button1-Motion>",Motion)
root.mainloop()

#OCR・tesseractを実行するpyファイルの呼び出し
import ocr

②.4の内容 上記の「import ocr」で呼び出す「ocr.py」データ

pyocr,tesseract
import sys
import pyocr
import pyocr.builders
from PIL import Image
import glob

pngs = sorted(glob.glob("ocr_images/*.png"),reverse=False)

tools = pyocr.get_available_tools()
if len(tools) == 0:
    print("No Ocr Tools")
    sys.exit(1)
tool = tools[0]
print("Will use tool")

langs = tool.get_available_languages()

#tkinterで切り取った画像を順々にOCRを実行していく
for i in pngs:
    txt = tool.image_to_string(Image.open(i),lang="eng+jpn",builder=pyocr.builders.TextBuilder())
    print(txt)

・所感

膨大な紙資料を目で見て、Excelに手入力して、、、というのを経験している身として、OCRは非常に魅力的です。
紙資料に対しての精度はわかりませんが、OCRの勉強の第一歩としては満足です。