python pyocr 光学文字認識 応用

Python

前回の記事で、pyocrを使って光学文字認識で画像からテキストデータ抽出しました

ただ、画像をそのまま光学文字認識にかけても精度はあまり良くないので、様々な画像処理をしてから光学文字認識にかけたほうが良さそうです

・環境

Windows 11

・グレースケール変換

画像をグレースケール(モノクロ)に変えて、さらにコントラストを上げてみます

from PIL import Image, ImageEnhance
import pyocr
import pyocr.builders
import cv2

# 環境変数設定している人は不要
#pyocr.tesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

tools = pyocr.get_available_tools()
tool = tools[0]

img_path = r"C:\Users\user\Documents\license.jpg"
img = Image.open(img_path)

#グレースケールに変換
img_g = img.convert('L')
enhancer= ImageEnhance.Contrast(img_g) # enhancerオブジェクト生成
#img_con = enhancer.enhance(2.0) #コントラストを上げる

#img_L.show()  # 画像表示

builder = pyocr.builders.TextBuilder(tesseract_layout=6)
text = tool.image_to_string(img_box, lang="jpn", builder=builder)

text = text.replace(' ', '') #半角スペースを削除
print(text)

enhancer.enhance(2.0)の引数は、強調の度合いを表し1.0が元画像と同じ、1.0未満は強調を弱め1.0より大きい場合は強調を強める

これでも、認識制度はいまいちなことも多いです

・文字以外の背景を白にする

取得したい部分の文字の背景に色や柄がある場合など、文字が黒なら黒以外の背景を白くする方法があります

こんなマイナンバーカードの個人番号の部分を読み取りたいとします
数字の部分は背景がグレーで読み取りづらそうです
そんな時に以下のようなコードを使用します

import os
from PIL import Image
import pyocr

# 環境変数設定している人は不要
#pyocr.tesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

tools = pyocr.get_available_tools()
tool = tools[0]

img_path = r"C:\Users\user\Documents\license.jpg"
img = Image.open(img_path)

#画像を加工
img=img.convert('RGB') #RGB形式に変更
size=img.size #画像のサイズを取得
img_edit=Image.new('RGB',size) #RGB形式の同じサイズの新しい画像として変数img_editに格納

#RGBの上限値を設定
max=90

#各ピクセルの情報を取得し上限を超えると白にする
for x in range(size[0]):
    for y in range(size[1]):
        r,g,b=img.getpixel((x,y)) 
        if r > border or g > border or b > border:
            r = 255
            g = 255
            b = 255
        img_edit.putpixel((x,y),(r,g,b))


#ocr実行
builder = pyocr.builders.DigitBuilder(tesseract_layout=6)
text = tool.image_to_string(img_edit, lang="eng", builder=builder)

print(text)

途中の画像処理を解説します

#画像を加工
img=img.convert('RGB') #RGB形式に変更
size=img.size #画像のサイズを取得
img_edit=Image.new('RGB',size) #RGB形式の同じサイズの新しい画像として変数img_editに格納

まず画像をRGB形式に変換します
OpenCVでは、3つのチャネルは実はRGBの順番ではなくBGRの順番で読み込んでいます
次に画像サイズを取得し、sizeに格納します
さらに新しく編集後の画像として作るためにimg_editという同じサイズのRGB形式の画像を生成します

#RGBの上限値を設定
max=90

#各ピクセルの情報を取得し上限を超えると白にする
for x in range(size[0]):
    for y in range(size[1]):
        r,g,b=img.getpixel((x,y)) 
        if r > border or g > border or b > border:
            r = 255
            g = 255
            b = 255
        img_edit.putpixel((x,y),(r,g,b))

RGBの各数値の上限を90とします(0が黒、255が白)
元の画像の座標(1,1)から順番にRGBの値を取得しRGBのいずれかが上限値を超えると白(255,255,255)にして新しい画像img_editに書き込んでいきます

#ocr実行
builder = pyocr.builders.DigitBuilder(tesseract_layout=6)
text = tool.image_to_string(img_edit, lang="eng", builder=builder)

OCRを実行します
今回は数字だけを読み取りたいのでbuilderをDigitBuilderとしました
また、lang=”eng”として日本語としては認識しないようにしました
以下のような画像が生成できました

数字だけ読み取ることができました

print(text)

# 123456789012

以上のように、OCRによる文字認識を活用するときは読み込む画像の事前準備が重要です
文字のレイアウト、言語、周りの背景色などを見て、有効な加工をすると精度がより高まると思います

コメント