ここでは、OpenCVを用いた文字認識方法について解説しています。
行ったこと
下記の画像に含まれる文字を認識させてみました。
プログラム
import sys
import numpy as np
import cv2
#1---画像読込み
im = cv2.imread('moji.png')
#2---グレイスケールに変換して二値化
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.adaptiveThreshold(blur, 255, 1, 1, 11, 2)
#3---輪郭抽出
contours = cv2.findContours(
thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]
#4---抽出した数分処理
for moji in contours:
x, y, w, h = cv2.boundingRect(moji)
if h < 20: continue
red = (0, 0, 255)
cv2.rectangle(im, (x, y), (x+w, y+h), red, 2)
#5---保存
cv2.imwrite('re-moji.png', im)
上記がプログラムになります。
それでは解説していきます。
#1---画像読込み
im = cv2.imread('moji.png')
1の部分では、画像を読み込んでいます。
#2---グレイスケールに変換
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.adaptiveThreshold(blur, 255, 1, 1, 11, 2)
2の部分では、画像をグレイスケールにして白黒の二値化しています。「cvtColor()」でグレイスケールを行い、「GaussianBlur()」ではガウシアンフィルタを用いて画像の平滑化を行っています。「adaptiveThreshold()」では配列に対して,適応的な閾値処理を行っています。
#3---輪郭抽出
contours = cv2.findContours(
thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]
3の部分では、「findContours()」を用いて2値画像中の輪郭を検出しています。「thresh」が入力画像、「RETR_LIST」が輪郭抽出モードですべての輪郭を抽出しますが,一切の階層構造を保持しないようにしています。「CHAIN_APPROX_SIMPLE」は輪郭の近似手法になります。水平・垂直・斜めの線分を圧縮し,それらの端点のみを残しています。
#4---抽出した数分処理
for moji in contours:
x, y, w, h = cv2.boundingRect(moji)
if h < 20: continue
red = (0, 0, 255)
cv2.rectangle(im, (x, y), (x+w, y+h), red, 2)
4の部分では、抽出した数だけ処理を繰り返して赤枠で囲っています。「boundingRect()」は矩形を取得しています。条件式ではサイズが小さい値を飛ばしています。
#5---保存
cv2.imwrite('re-moji.png', im)
最後に保存して終了です。
結果
上記が結果になります。
結論から言うと、余計なアイコンまで文字として抽出してしまっています。これは検出方法ですべての輪郭を抽出してしまっていることが原因だと考えられるので「CV_RETR_EXTERNAL」と変更してみました。
しかし、上手くいきませんでした。
検出方法に問題がありそうなのは分かるのですが、まだまだ勉強不足です。
また勉強してから挑戦してみようと思います。