tesseract-OCRを使わずにPythonで画像から文字を認識させるソフトを作ってみた – 3

プログラミング

前回の記事

さて、2階調化された文字が手に入りました。
ここでは、例として「1」を取り扱いたいと思います。

2階調化された1はこれです。

この画像における1の、縦の長い線の太さは7ピクセルだとします。

私の文字の判定は全ての文字に対応できるわけではありませんが、数十文字程度なら対応できます。
この1の画像を1として認識する条件を、
・一番上の白の幅が7ピクセル以内
かつ
・一番下の白の部分が7ピクセル以内
とします。

まず、一番上のY座標の、一番左のX座標を取得します。
これを基点とします。
下画像の赤の部分です。(2階調にしたため白なのですが、わかりやすく赤に塗りました。)
また、それにともない黒に赤があってもみづらいため、黒の部分をグレーにしました。

次に、太さを計算します。
太さは、一番上のY座標の、一番右のXの座標を取得すればいいです。
上画像の青になります。

最後に、一番底辺のY座標の、左右の色を取得します。
下の画像の緑の部分です。
今回は、文字の太さが7ピクセルとわかっているため、左右5ピクセルの色を取得します。
わかりやすいように、ピンクのスケールをつけました。


この赤のX座標は上の赤のx座標と同じです。

これをコードにすると、下記のようになります。

def Sample():

…import cv2
…import numpy
…from PIL import Image as im
…from PIL import ImageGrab as ig

#ImageGrabを使ってスクリーンショットを取る。
#今回は、座標(100,100)から(200,200)の中に、「1」という文字が1つだけ入っているとします。
#これを、test.pngとして保存します。
…img = ig.grab((100,100,200,200)).save(“test.png”)

#保存されたtest.pngを読み込みます。
#cv2ではBGRとして読み込むので、グレースケール化します。
#その後、閾値128で2階調化します。
#そしてtest.pngとして上書き保存します。
…img = cv2.imread(“test.png”)
…img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
…_ ,img = cv2.threshold(img, 128 ,255,cv2.THRESH_BINARY)
…cv2.imwrite(“test.png”, img)

#今度は、PILのImageを使ってtest.pngを読み込みます。
#RGBに変換し、画像のサイズも取得します。
…img = im.open(“test.png”)
…rgb_im = img.convert(‘RGB’)
…size = rgb_im.size

#「1」という文字の、一番上のY座標の一番左のX座標を取得します。
#座標(0,0)から1行ごとに右へ、1ピクセルずつ順に白か黒か判定します。
#もしその行に白がなければ、次の行(Y)に移ります。
#白のピクセルがあれば、繰り返しの処理を抜け出します。
#なお、RGBにおける白の値は(255,255,255)なので、rが255か0かで白か黒かを判定します。
…for y in range(size[1]):
……for x in range(size[0]):
………r,g,b = rgb_im.getpixel((x,y))
………if r == 255 :
…………break
……if r == 255 :
………break

#このxが、一番左のx(前掲した画像の赤)になります。
….x_left = x

#今度は、同じY座標において、右から左に各ピクセルが白か黒か判定していきます。ピクセルが黒であり続ける限り、x座標をどんどん左に移動させていきます。
…x = size[0] – 1
…r,g,b = rgb_im.getpixel((x,y))
…while r == 0 :
……x = x – 1

#これが前掲画像の青になります。
…x_right = x

#一番底辺のY座標を取得します。
…y = size[1] – 1
…r,g,b = rgb_im.getpixel((x_left,y))
…while r == 0 :
……y = y – 1

…y_bottom = y

#一番底辺のY座表の、左右5ピクセルのカラーを取得します。
…r2 ,g,b = rgb_im.getpixel((x_left + 5 , y_bottom))
…r3 ,g,b = rgb_im.getpixel((x_left – 5 , y_bottom))

#太さ(x_right – x_leftの差)が7ピクセル以内で、底辺の5ピクセル左右が黒なら1と判定します。
…if x_right – x_left <= 7 and r2 == 0 and r3 == 0 :
……return 1

コメント

タイトルとURLをコピーしました