[解決済み] OpenCV-Pythonによる簡単な数字認識OCR
質問
OpenCV-Python(cv2)で、quot;Digit Recognition OCR"を実装しようと思っています。あくまで学習用です。OpenCVでKNearestとSVMの両方の特徴を学習したいと思います。
各桁のサンプル(=画像)が100枚ずつあります。それを使って学習したいのですが。
あるサンプル
letter_recog.py
OpenCVのサンプルに付属しているものです。しかし、その使い方がまだわからない。何がサンプルなのか、何がレスポンスなのか等、よくわかりません。また、最初にtxtファイルを読み込むのですが、これがまず理解できませんでした。
その後、少し探したところ、cppのサンプルにletter_recognition.dataが見つかりました。それを使ってletter_recog.pyのモデル内にcv2.KNearestのコードを作ってみた(テスト用)。
import numpy as np
import cv2
fn = 'letter-recognition.data'
a = np.loadtxt(fn, np.float32, delimiter=',', converters={ 0 : lambda ch : ord(ch)-ord('A') })
samples, responses = a[:,1:], a[:,0]
model = cv2.KNearest()
retval = model.train(samples,responses)
retval, results, neigh_resp, dists = model.find_nearest(samples, k = 10)
print results.ravel()
サイズ20000の配列が表示されましたが、何のことだかわかりません。
質問です。
1) letter_recognition.dataファイルとは何ですか?自分のデータセットからどのようにそのファイルを作るのですか?
2)
results.reval()
を表します。
3) letter_recognition.dataファイルを使った簡単な数字認識ツール(KNearestかSVMのどちらか)を書くにはどうしたらよいか?
どのように解決するのですか?
さて、私は上記の問題を解決するために、自分自身を鍛錬することにしました。私がしたかったのは、OpenCVでKNearestやSVMの特徴を使った単純なOCRを実装することです。そして、以下は私が行ったことと方法です。( これは、単純なOCRの目的のためにKNearestを使用する方法を学習するためのものです。).
1) 最初の質問は、OpenCVのサンプルに付属しているletter_recognition.dataファイルについてです。そのファイルの中に何があるのか知りたかったのです。
文字と、その文字の16の特徴量が入っています。
そして
this SOF
を見つけるのに役立ちました。これら16の機能については、論文で解説しています
Letter Recognition Using Holland-Style Adaptive Classifiers
.
( 最後にいくつかの機能を理解できませんでしたが)
2) やっぱり、その特徴を全部理解しないと、あのやり方は難しいですね。他の論文も試しましたが、どれも初心者には少し難しいものでした。
So I just decided to take all the pixel values as my features.
(精度や性能は気にせず、最低限動けばいいと思っていました)
学習用データとして、以下の画像を撮影しました。
(学習データ量が少ないことは承知しています。しかし、すべての文字が同じフォントとサイズであるため、これで試してみることにした)。
学習用のデータを準備するために、OpenCVで小さなコードを作りました。これは以下のようなことをする。
- 画像を読み込みます。
- 数字を選択する(明らかに輪郭抽出と、誤検出を避けるための文字の面積と高さの制約を適用している)。
-
一文字を囲む矩形を描画し、その上で
key press manually
. 今回は 自分で数字キーを押す ボックス内の文字に対応する - 対応する数字キーが押されると、このボックスを10x10にリサイズし、100ピクセル分の値を配列(ここではsamples)に、手動で入力した対応する数字を別の配列(ここではrespons)に保存します。
- 次に、両方の配列を別々のtxtファイルに保存します。
最後に、学習データ( train.png )に含まれる全ての数字を手動でラベル付けすると、以下のような画像になります。
以下は、上記の目的のために私が使用したコードです(もちろん、それほどきれいではありません)。
import sys
import numpy as np
import cv2
im = cv2.imread('pitrain.png')
im3 = im.copy()
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)
thresh = cv2.adaptiveThreshold(blur,255,1,1,11,2)
################# Now finding Contours ###################
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
samples = np.empty((0,100))
responses = []
keys = [i for i in range(48,58)]
for cnt in contours:
if cv2.contourArea(cnt)>50:
[x,y,w,h] = cv2.boundingRect(cnt)
if h>28:
cv2.rectangle(im,(x,y),(x+w,y+h),(0,0,255),2)
roi = thresh[y:y+h,x:x+w]
roismall = cv2.resize(roi,(10,10))
cv2.imshow('norm',im)
key = cv2.waitKey(0)
if key == 27: # (escape to quit)
sys.exit()
elif key in keys:
responses.append(int(chr(key)))
sample = roismall.reshape((1,100))
samples = np.append(samples,sample,0)
responses = np.array(responses,np.float32)
responses = responses.reshape((responses.size,1))
print "training complete"
np.savetxt('generalsamples.data',samples)
np.savetxt('generalresponses.data',responses)
ここからは、トレーニングとテストのパートに入ります。
テスト用の画像は、学習用と同じ種類の文字が描かれた以下の画像を使用しました。
<イグ
トレーニングは次のように行います。 :
- 先ほど保存したtxtファイルを読み込む
- 使用する分類器のインスタンスを作成します(ここでは KNearest とします)。
- そして、KNearest.train 関数を用いてデータを学習させる。
テスト用には、以下のようにします。
- テストに使用した画像を読み込みます
- 先程と同様に画像を処理し、輪郭法を用いて各桁を抽出する
- バウンディングボックスを描画し、10x10にリサイズして、そのピクセル値を先程と同様に配列に格納する。
- 次に、KNearest.find_nearest()関数を使って、指定したものに最も近いものを探します。( 運が良ければ、正しい数字を認識します。)
最後の2つのステップ(学習とテスト)は、以下の1つのコードに含まれています。
import cv2
import numpy as np
####### training part ###############
samples = np.loadtxt('generalsamples.data',np.float32)
responses = np.loadtxt('generalresponses.data',np.float32)
responses = responses.reshape((responses.size,1))
model = cv2.KNearest()
model.train(samples,responses)
############################# testing part #########################
im = cv2.imread('pi.png')
out = np.zeros(im.shape,np.uint8)
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,1,1,11,2)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt)>50:
[x,y,w,h] = cv2.boundingRect(cnt)
if h>28:
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
roi = thresh[y:y+h,x:x+w]
roismall = cv2.resize(roi,(10,10))
roismall = roismall.reshape((1,100))
roismall = np.float32(roismall)
retval, results, neigh_resp, dists = model.find_nearest(roismall, k = 1)
string = str(int((results[0][0])))
cv2.putText(out,string,(x,y+h),0,1,(0,255,0))
cv2.imshow('im',im)
cv2.imshow('out',out)
cv2.waitKey(0)
そして、うまくいきました。以下は、私が得た結果です。
ここでは、100%の精度で動作しました。これは、すべての桁が同じ種類で同じ大きさであるためだと思われます。
しかし、いずれにせよ、これは初心者が行くには良いきっかけになる(といいのだが)。
関連
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み】syntaxError: 'continue' がループ内で適切に使用されていない
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] Pythonで例外を手動で発生(スロー)させる
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python機械学習Githubが8.9Kstarsに達したモデルインタープリタLIME
-
PyQt5はユーザーログインGUIインターフェースとログイン後のジャンプを実装しています。
-
Pythonの画像ファイル処理用ライブラリ「Pillow」(グラフィックの詳細)
-
[解決済み】Python regex AttributeError: 'NoneType' オブジェクトに 'group' 属性がない。
-
[解決済み】pygame.error: ビデオシステムが初期化されていない
-
[解決済み】numpy: true_divide で無効な値に遭遇
-
[解決済み】TypeError: re.findall()でバイトのようなオブジェクトに文字列パターンを使用することはできません。)
-
[解決済み】NameError: 名前 'self' が定義されていません。
-
[解決済み】cアンダースコア式`c_`は、具体的に何をするのですか?
-
[解決済み】数独の正方形の凸凹の欠点を取り除くには?