2017-08-22 58 views
1

我一直在嘗試使用基於OpenCV庫上的代碼的SVM來訓練手寫數字。我訓練的一部分是如下:如何在Python中使用SVM實現用於手寫識別的.dat文件

import cv2 
import numpy as np 

SZ=20 
bin_n = 16 
svm_params = dict(kernel_type = cv2.SVM_LINEAR, 
        svm_type = cv2.SVM_C_SVC, 
       C=2.67, gamma=5.383) 
affine_flags = cv2.WARP_INVERSE_MAP|cv2.INTER_LINEAR 

def deskew(img): 
    m = cv2.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 = cv2.warpAffine(img,M,(SZ, SZ),flags=affine_flags) 
    return img 
def hog(img): 
    gx = cv2.Sobel(img, cv2.CV_32F, 1, 0) 
    gy = cv2.Sobel(img, cv2.CV_32F, 0, 1) 
    mag, ang = cv2.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 = cv2.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)] 

train_cells = [ i[:50] for i in cells ] 
test_cells = [ i[50:] for i in cells] 

deskewed = [map(deskew,row) for row in train_cells] 
hogdata = [map(hog,row) for row in deskewed] 
trainData = np.float32(hogdata).reshape(-1,64) 
responses = np.float32(np.repeat(np.arange(10),250)[:,np.newaxis]) 

svm = cv2.SVM() 
svm.train(trainData,responses, params=svm_params) 
svm.save('svm_data.dat') 

繼承人的digits.png enter image description here

其結果是,我得到了svm_data.dat文件。但是現在我不知道如何實現這個模型。可以說我想在這裏讀取這個號碼 enter image description here

任何人都可以幫我嗎?

回答

0

我打算假設「如何實現模型」的意思是「如何預測新圖像的標籤」。

首先,注意,這並沒有什麼關係保存svm_data.dat本身,除非你想這樣做在不同的腳本/會話,在這種情況下,你可以從重新加載您的培訓svm對象文件。

有了這樣的方式,使得對新數據的預測需要三個步驟:

  1. 如果新的數據是從訓練數據有些不同,預處理它,所以它的訓練數據一致(見反轉和調整大小)。

  2. 提取特徵的方式與對訓練數據所做的相同。

  3. 使用訓練好的分類器預測標籤。

    # Load the image 
    img_predict = cv2.imread('predict.png', 0) 
    
    # Preprocessing: this image is inverted compared to the training data 
    # Here it is inverted back 
    img_predict = np.invert(img_predict) 
    
    # Preprocessing: it also has a completely different size 
    # This resizes it to the same size as the training data 
    img_predict = cv2.resize(img_predict, (20, 20), interpolation=cv2.INTER_CUBIC) 
    
    # Extract the features 
    img_predict_ready = np.float32(hog(deskew(img_predict))) 
    
    # Reload the trained svm 
    # Not necessary if predicting is done in the same session as training 
    svm = cv2.SVM() 
    svm.load("svm_data.dat") 
    
    # Run the prediction 
    prediction = svm.predict(img_predict_ready) 
    print int(prediction) 
    

    輸出爲0,符合市場預期:

爲您上傳的示例圖像,這可以如下完成。

請注意,將要分類的數據與用於訓練的數據進行匹配非常重要。在這種情況下,跳過重新調整大小的步驟會導致圖像分類錯誤爲2

此外,仔細觀察圖像可以發現它與訓練數據(更多背景,不同平均值)有點不同,所以如果分類器最終在圖像上表現得更差,我不會感到驚訝這與使用的測試數據in the original tutorial(其僅僅是訓練數據的一半)相比較。但是,這取決於特徵提取對訓練圖像和預測圖像之間的差異有多敏感。