【機器學習--opencv3.4.1版本基於Hog特徵描述子Svm對經典手寫數字識別】
阿新 • • 發佈:2018-11-05
方向梯度直方圖(Histogram of Oriented Gradient, HOG)特徵是一種在計算機視覺和影象處理中用來進行物體檢測的特徵描述子。HOG特徵通過計算和統計影象區域性區域的梯度方向直方圖來構成特徵。
#include <iostream> #include <fstream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/objdetect/objdetect.hpp> #include <opencv2/ml/ml.hpp> using namespace std; using namespace cv; using namespace cv::ml; int main(){ //winsize(64,128),blocksize(16,16),blockstep(8,8),cellsize(8,8),bins9 //檢測視窗(64,128),塊尺寸(16,16),塊步長(8,8),cell尺寸(8,8),直方圖bin個數9 HOGDescriptor hog(Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9); //HOG檢測器,用來計算HOG描述子的 int DescriptorDim;//HOG描述子的維數,由圖片大小、檢測視窗大小、塊大小、細胞單元中直方圖bin個數決定 Mat sampleFeatureMat;//所有訓練樣本的特徵向量組成的矩陣,行數等於所有樣本的個數,列數等於HOG描述子維數 Mat sampleLabelMat;//訓練樣本的類別向量,行數等於所有樣本的個數,列數等於1;1表示有人,-1表示無人 Ptr<SVM> svm = SVM::create();//SVM分類器 string ImgName;//圖片名(絕對路徑) ifstream finPos("img.txt");//正樣本圖片的檔名列表 if (!finPos) { cout << "Pos/Neg imglist reading failed..." << endl; return 1; } for (int num = 0; num < 200 && getline(finPos, ImgName); num++) { std::cout << "Now processing original positive image: " << ImgName << endl; ImgName = "Image\\" + ImgName;//加上正樣本的路徑名 Mat src = imread(ImgName);//讀取圖片 //if (CENTRAL_CROP) // src = src(Rect(16, 16, 128, 128));//將96*160的INRIA正樣本圖片剪裁為64*128,即剪去上下左右各16個畫素 vector<float> descriptors;//HOG描述子向量 hog.compute(src, descriptors, Size(8, 8));//計算HOG描述子,檢測視窗移動步長(8,8) //處理第一個樣本時初始化特徵向量矩陣和類別矩陣,因為只有知道了特徵向量的維數才能初始化特徵向量矩陣 if (0 == num) { DescriptorDim = descriptors.size(); //初始化所有訓練樣本的特徵向量組成的矩陣,行數等於所有樣本的個數,列數等於HOG描述子維數sampleFeatureMat sampleFeatureMat = Mat::zeros(200, DescriptorDim, CV_32FC1); //初始化訓練樣本的類別向量,行數等於所有樣本的個數,列數等於1;1表示有人,0表示無人 sampleLabelMat = Mat::zeros(200, 1, CV_32SC1);//sampleLabelMat的資料型別必須為有符號整數型 } //將計算好的HOG描述子複製到樣本特徵矩陣sampleFeatureMat for (int i = 0; i<DescriptorDim; i++) sampleFeatureMat.at<float>(num, i) = descriptors[i];//第num個樣本的特徵向量中的第i個元素 sampleLabelMat.at<int>(num, 0) = num / 20;//正樣本類別為1,有人 } finPos.close(); //輸出樣本的HOG特徵向量矩陣到檔案 svm->setType(SVM::C_SVC); svm->setC(0.01); svm->setKernel(SVM::LINEAR); svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 3000, 1e-6)); std::cout << "Starting training..." << endl; svm->train(sampleFeatureMat, ROW_SAMPLE, sampleLabelMat);//訓練分類器 std::cout << "Finishing training..." << endl; //將訓練好的SVM模型儲存為xml檔案 svm->SVM::save("SVM_HOG.xml"); //imshow("src", src); waitKey(); return 0; }
基於xml檔案的預測:
#include <iostream> #include <fstream> #include <opencv2/core/bufferpool.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/objdetect/objdetect.hpp> #include <opencv2/ml/ml.hpp> using namespace std; using namespace cv; using namespace cv::ml; int main(){ //reat SVM classfier Ptr<SVM> svm = SVM::create(); //load train file svm = SVM::load("SVM_HOG.xml"); if (!svm){ cout << "Load file failed..." << endl; } Mat test; test = imread("123.png"); //winsize(64,128),blocksize(16,16),blockstep(8,8),cellsize(8,8),bins9 //檢測視窗(64,128),塊尺寸(16,16),塊步長(8,8),cell尺寸(8,8),直方圖bin個數9 HOGDescriptor hog(Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9); vector<float> descriptors;//HOG描述子向量 hog.compute(test, descriptors, Size(8, 8));//計算HOG描述子,檢測視窗移動步長(8,8) int r = svm->predict(descriptors); //對所有行進行預測 cout << "The number is " << r << endl; //waitKey();//note:The function only works if there is at least one HighGUI window created and the window is active.If there are several HighGUI windows, any of them can be active. //getchar(); system("pause"); return 1; }
訓練好的xml檔案與資料集合:https://download.csdn.net/my
C=參考部落格:https://blog.csdn.net/wwwsssZheRen/article/details/79542693?utm_source=blogxgwz4