目標
本章では、手書きデータ・セットを再認識し、代わりにSVM k最近傍を使用します。
手書きの番号を認識
k最近傍では、我々は、直接特徴ベクトルとしてピクセル強度を使用します。今回は、特徴ベクトルとして、勾配方向ヒストグラム(HOG)を使用します。
ここでは、HOGを見つける前に、我々は、画像スキュー補正の二次モーメントを使用します。我々は最初の関数を定義するため、傾き補正() 、関数は、デジタル画像を取得し、修正しました。以下は、傾き補正()関数です。
def deskew(img):
m = cv.moments(img)
if abs(m['mu02']) < 1e-2:
return img.copy()
skew = m['mu11']/m['mu02']
M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
img = cv.warpAffine(img,M,(SZ, SZ),flags=affine_flags)
return img
図に示す次のゼロは、画像オフセット補正関数に適用されます。左の画像は、右シフトなど、元の画像は、画像を補正しています。
次に、我々は、各セルのHOG記述子を見つけなければなりません。この目的のために、我々は、XおよびY方向における各ユニットのソーベルパイロットの数を発見しました。その後、それらのサイズと各画素における勾配の方向を見つけます。勾配は、16個の整数値に量子化されます。この画像は、4つのサブ正方形に分割されています。各サブ正方形の計算のために右方向の主要な小ヒストグラム(16ビン)。したがって、各サブ正方形はあなたのための16の値を含むベクターを提供します。(4平方サブ)が一緒に私たちのために特徴値64のベクターを含む4つのこのようなベクターを提供します。これは、トレーニングデータのための私達の特徴ベクトルです。
def hog(img):
gx = cv.Sobel(img, cv.CV_32F, 1, 0)
gy = cv.Sobel(img, cv.CV_32F, 0, 1)
mag, ang = cv.cartToPolar(gx, gy)
bins = np.int32(bin_n*ang/(2*np.pi)) # quantizing binvalues in (0...16)
bin_cells = bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists) # hist is a 64 bit vector
return hist
最後に、以前の場合のように、我々は、単一の大きなセルとして第一のデータセットを分割します。各番号のために、トレーニング・データ・ユニット250、テスト用に予約250個の残りのデータのために予約。あなたはここからダウンロードすることができ、以下のコードを実行します。
#!/usr/bin/env python
import cv2 as cv
import numpy as np
SZ=20
bin_n = 16 # Number of bins
affine_flags = cv.WARP_INVERSE_MAP|cv.INTER_LINEAR
def deskew(img):
m = cv.moments(img)
if abs(m['mu02']) < 1e-2:
return img.copy()
skew = m['mu11']/m['mu02']
M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
img = cv.warpAffine(img,M,(SZ, SZ),flags=affine_flags)
return img
def hog(img):
gx = cv.Sobel(img, cv.CV_32F, 1, 0)
gy = cv.Sobel(img, cv.CV_32F, 0, 1)
mag, ang = cv.cartToPolar(gx, gy)
bins = np.int32(bin_n*ang/(2*np.pi)) # quantizing binvalues in (0...16)
bin_cells = bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists) # hist is a 64 bit vector
return hist
img = cv.imread('digits.png',0)
if img is None:
raise Exception("we need the digits.png image from samples/data here !")
cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]
# First half is trainData, remaining is testData
train_cells = [ i[:50] for i in cells ]
test_cells = [ i[50:] for i in cells]
deskewed = [list(map(deskew,row)) for row in train_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
trainData = np.float32(hogdata).reshape(-1,64)
responses = np.repeat(np.arange(10),250)[:,np.newaxis]
svm = cv.ml.SVM_create()
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
svm.save('svm_data.dat')
deskewed = [list(map(deskew,row)) for row in test_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
testData = np.float32(hogdata).reshape(-1,bin_n*4)
result = svm.predict(testData)[1]
mask = result==responses
correct = np.count_nonzero(mask)
print(correct*100.0/result.size)
この特殊な方法は、私たちにほぼ94パーセントの精度を提供します。あなたがより高い精度を達成できるかどうかをチェックするためにSVMの様々なパラメータに異なる値を試すことができます。それとも、あなたがこの領域に技術的な論文を読み、それらを実装しようとすることができます。
その他のリソース
- 勾配方向ビデオのヒストグラム:https://www.youtube.com/watch?v=0Zib1YEE4LU
練習
- digits.pyを含むOpenCVのサンプルは、この方法は、改善された結果を与えるためにその上に多くの改良が記載されています。また、参考資料が含まれています。それを確認し、理解しています。
AIは注意パンチョン・ステーションのブログを歓迎:http://panchuang.net/
OpenCVの中国の公式文書:http://woshicver.com/
ようこそ注意パンチョンのブログのリソースの概要駅:http://docs.panchuang.net/