libsvm Minist Hog 手写体识别
統(tǒng)計手寫數(shù)字集的HOG特征
轉載請注明出處,樓燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/
這篇文章是模式識別的小作業(yè),利用svm實現(xiàn)Minist數(shù)據(jù)集手寫體識別,在這里我實現(xiàn)了opencv中的svm和libsvm兩個版本,供大家做參考。
[https://github.com/YihangLou/SVM-Minist-HandWriting-Recognition]https://github.com/YihangLou/SVM-Minist-HandWriting-Recognition?Github上的工程鏈接
Hog特征簡介
本實驗中,使用開源計算機視覺庫OpenCV作為圖像處理的基本工具,用其提供的loadImage函數(shù)讀入訓練樣本后,首先我們考慮如何對樣本中的手寫數(shù)字特征進行提取。在本實驗中我們采取了方向梯度直方圖(Histogram of OrientedGradient, HOG)的方法。HOG特征是一種在計算機視覺和圖像處理中用來進行物體檢測的特征描述子。在一副圖像中,局部目標的表象和形狀能夠被梯度和邊緣的方向密度分布很好地描述,而HOG通過計算和統(tǒng)計圖像局部區(qū)域的梯度方向直方圖來構成特征。
HOG特征提取算法的實現(xiàn)過程如下:
1)將待檢測的圖像灰度化;
2)采用Gamma校正法對輸入圖像進行顏色空間的標準化(歸一化)。目的是調節(jié)圖像的對比度,降低圖像局部的陰影和光照變化所造成的影響,同時可以抑制噪音的干擾。
3)計算圖像每個像素的梯度(包括大小和方向)。主要是為了捕獲輪廓信息,同時進一步弱化光照的干擾。
4)將圖像劃分成小cells(例如66像素/cell),并統(tǒng)計每個cell的梯度直方圖(不同梯度的個數(shù)),即可形成每個cell的descriptor。統(tǒng)計梯度直方圖過程如下:假設我們采用9個bin的直方圖來統(tǒng)計這66個像素的梯度信息。也就是將cell的梯度方向 分成9個方向塊,
如果這個像素的梯度方向 是 或者 ,直方圖第2個bin的計數(shù)就加1,這樣,對cell內每個像素用梯度方向在直方圖中進行加權投影(映射到固定的角度范圍),就可以得到這個cell的梯度方向直方圖了,就是該cell對應的9維特征向量(因為有9個bin)。梯度幅值 就是作為投影的權值的。例如說:這個像素的梯度方向是 ,然后它的梯度幅值 是2,那么直方圖第2個bin的計數(shù)就不是加1了,而是加2。
4)將每幾個cell組成一個block(例如3*3個cell/block),一個block內所有cell的特征descriptor串聯(lián)起來便得到該block的HOG特征descriptor;
5)將圖像image內的所有block的HOG特征descriptor串聯(lián)起來就可以得到該image的HOG特征descriptor了。這個就是最終的可供分類使用的特征向量了。
在我們的實驗中使用OpenCV提供的HOG算子HOGDescriotiptor,它的構造函數(shù)HOGDescriptor * hog = new HOGDescriptor(Size _winSize,Size _blockSize, Size _blockStride ,Size _cellSize , int bins);相關參數(shù)設置如表2.1所示。接下來我們只需再調用hog->compute()函數(shù)并以Image作為參數(shù)即可計算出其特征向量descriptors。
vectordescriptors;
hog->compute(Image, descriptors,Size(1,1), Size(0,0));
LibSVM配置
這里SVM的原理不就做介紹了,網(wǎng)上也有很多的資料介紹SVM
- 首先設置SVM參數(shù)。LibSVM提供了SVM參數(shù)結構svm_param,如下段代碼所示,各參數(shù)意義如表2.2所示。
//配置SVM參數(shù)
svm_parameter param;
param.svm_type = C_SVC;
param.kernel_type = RBF;
param.degree = 10.0;
param.gamma = 0.09;
param.coef0 = 1.0;
param.nu = 0.5;
param.cache_size = 1000;
param.C = 10.0;
param.eps = 1e-3;
param.p = 1.0;
在本實驗中選擇了C_SVC類型的SVM,并且選擇了REF核函數(shù)。
-
將待訓練的特征向量整理成LibSVM使用的數(shù)據(jù)格式。2.1.1中使用OpenCV提供的HOG方法得到了特征向量descriptors,要在LibSVM中使用上還需符合LibSVM的訓練數(shù)據(jù)文件格式,如下所示
<label> <index1>:<value1> <index2>:<value2> ... 其中<label> 是訓練數(shù)據(jù)集的目標值,對于分類,它是標識某類的整數(shù)(支持多個類)。<index> 是以1開始的整數(shù),可以是不連續(xù)的,但是必須在結尾處標記為index=-1;<value>為實數(shù),也就是我們提取出的特征向量。例如我們處理第一張手寫圖片train_0_0.jpg,該圖片表示的是手寫數(shù)字0,那么<label>標記為0;該圖片用HOG方法描述的特征向量descriptor是長度為324的vector<float>,那么將<index1>~<index324>分別標記為0,1,2...323,<index325>標記為-1表示結束;<value1>~<value324>分別賦值為descriptor[0],descriptor[1],descriptor[2]...descriptor[323]。 -
調用svm_train函數(shù)開始訓練,得到訓練模型svm_model,并保存于“*.model”文件。前面兩個步驟已經(jīng)分別設置好了SVM的一系列參數(shù)param并整理了待訓練特征向量的格式svm_prob,svm_train函數(shù)以param和svm_prob作為參數(shù)開始訓練。
訓練過程中輸出如圖所示,其中, #iter為迭代次數(shù);nu是選擇的核函數(shù)類型的參數(shù);obj為SVM文件轉換為的二次規(guī)劃求解得到的最小值;rho為判決函數(shù)的偏置項b;nSV為標準支持向量個數(shù)(0<a[i]<c);nBSV為邊界上的支持向量個數(shù)(a[i]=c);Total nSV為支持向量總個數(shù)(對于兩類來說, 因為只有一個分類模型Total nSV = nSV但是對于多類,這個是各個分類模型的nSV之和)。
得到的“*.model”文件如下所示:
4)讀入測試集圖片,提取其HOG特征并整理成LibSVM使用的數(shù)據(jù)格式svm_node。測試集格式與訓練集格式的唯一不同在于測試集不需要標記label,也具有index和value屬性。
5)調用svm_predict函數(shù)進行測試。首先通過svm_model * 加載訓練出的模型“*.Model”,svm_model 和svm_node作為svm_predict函數(shù)的參數(shù),該函數(shù)以返回一個int類型的數(shù)據(jù),即預測出的類別。
OpenCV SVM
除了2.1.2介紹的LibSVM工具,我們小組還嘗試了OpenCV提供的SVM工具,它是基于LibSVM軟件包開發(fā)的,優(yōu)點是使用起來比LibSVM更簡潔,下面簡要的介紹一下OpenCV中SVM的訓練和測試兩階段:
1)OpenCV中的SVM在訓練階段代碼如下所示:
其中CvTermCriteria設置了迭代終止準則,最大迭代次數(shù)設為1000次,結果的精確性設為FLT_EPSILON = 1.19e-7;CvSVMParams設置了SVM相關的訓練參數(shù),參數(shù)具體設置仍如表2.1所示。與LibSVM不同的是,OpenCV不需要將特征向量整理成特定的格式,只需要特征向量按行順序排好,給出它們的label,就可以調用訓練函數(shù)svm.train()進行訓練了。另外,OpenCV訓練出的模型保存在“.xml”文件中而非LibSVM中的“.Model”文件,如圖2.3所示。
最后所有的支持向量個數(shù)為6364個,與LibSVM完全一致,印證了OpenCV SVM底層是基于LibSVM的。
2)在測試階段,OpenCV SVM的用法與LibSVM基本一致,調用svm.predict函數(shù)進行測試。首先通過CvSVM svm加載訓練出的模型“*.xml”。接著將測試集圖片的HOG向量整理成一個個CvMat,它作為svm_predict函數(shù)的參數(shù)輸入,該函數(shù)以返回一個int類型的數(shù)據(jù),即預測出的類別。
代碼解讀
實驗代碼實現(xiàn)了LibSVM 和OpenCV SVM分類功能,完成了各個函數(shù)功能的封裝,整個SVM分類器共分為8個函數(shù),分別為:readTrainFileList、processHogFeature、trainSVM、trainLibSVM,readTestFileList,testLibSVM,testSVM,releaseAll。其中,每個函數(shù)的輸入輸出設置以及功能如下表所示:
實驗測試
本次實驗使用“MNIST DATABASE”, 數(shù)據(jù)集包含了0-9數(shù)字手寫體,共有60000張訓練數(shù)據(jù)集,10000張測試數(shù)據(jù)集。測試集的前5000個例子取自原始NIST訓練集,后5000取自原始NIST測試集,前5000個數(shù)據(jù)要比后5000個數(shù)據(jù)更干凈、容易。
預測結果是輸出到txt中的,通過Python腳本來分析
1)訓練正確率
在訓練集上進行正確率測試得到的結果是0.9884。
2)測試正確率
在10000張測試數(shù)據(jù)集上,我們的實驗結果準確率為0.9884,其中10*10的舉證結果如下,結果(i,j)代表將第i類錯分為第j類的次數(shù)。
實驗的主要錯分類分析
實驗中,有一些錯分類很難避免,如4和9的錯分以及7和2的錯分,如下圖所示。由于實驗數(shù)據(jù)本身難以識別,造成的錯分占據(jù)整個實驗數(shù)據(jù)的1%左右。
總結
以上是生活随笔為你收集整理的libsvm Minist Hog 手写体识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像滤镜艺术---PS图层混合模式之明度
- 下一篇: 前景检测算法_1(codebook和平均