気合いで画像から文字だけを抽出する
現在画像処理をやっているので,その辺の知識を置いていこうと思います
今回使うライブラリです.
import matplotlib.pyplot as plt from PIL import ImageFont, ImageDraw, Image, ImageOps, ImageFilter import numpy as np from skimage import measure import cv2 %matplotlib inline
今回使う画像は下のものです.
では早速やっていきます. RGBカラーでは処理しづらいので,グレーイスケールに変換します.
sign_board = Image.open("sign_board_maker.jpg") gsign_board = sign_board.convert('L')
この際私はPillowでやっていますがopenCVを使う場合だと以下のようです
image = cv2.imread('hoge.jpg')
gimage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
次に閾値を設定して, 2値に変換をします. この処理ではノイズの除去を目的としています.
gimg = np.asarray(gsign_board) threshold = cv2.threshold(gimg, 200, 255, cv2.THRESH_BINARY)[1]
この時点での結果がこちらです.
次に文字部分だけを抜き取ります.
labels = measure.label(threshold, neighbors=8, background=0) mask = np.zeros(threshold.shape, dtype='uint8') for (i, label) in enumerate(np.unique(labels)): if label ==0: continue labelMask = np.zeros(threshold.shape, dtype="uint8") labelMask[labels==label]=255 numpixels= cv2.countNonZero(labelMask) if numpixels > 200 and numpixels < 1000: mask = np.add(mask , labelMask) plt.imshow(mask)
結果が以下です.
measureで2値化下画像から繋がっている要素にラベリングをします.
そのラベルづけされた要素のpixel数が200より大きく1000より小さい場合のみmaskに追加しています.
古典的でダサいですが,これでも割と文字は抽出できます.
フォントサイズが固定であったりする場合などには有効な手法だと思います.
まとめ
計算リソースに制限がある場合や.実行時間を重視する場合はこのような手法が必要なのかなって思いました.