opencv3.0函式呼叫,svm訓練分類器
阿新 • • 發佈:2019-01-31
#include <iostream>#include <fstream>#include <opencv2/opencv.hpp>#include <opencv2/ml/ml.hpp>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/objdetect/objdetect.hpp>#include <string> #include <io.h>using namespace std;using namespace cv;using namespace cv::ml;#define PosSamNO 480 //正樣本個數 #define NegSamNO 3384 //負樣本個數 #define HardExampleNO 0 //難例個數 int main(int argc, char** argv){//HOG檢測器,用來計算HOG描述子的 //檢測視窗(48,48),塊尺寸(16,16),塊步長(8,8),cell尺寸(8,8),直方圖bin個數9 param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria ); cv::HOGDescriptor hog(cv::Size(64, 64), cv::Size(16, 16), cv::Size(16, 16), cv::Size(8, 8), 9);int DescriptorDim;//HOG描述子的維數,由圖片大小、檢測視窗大小、塊大小、細胞單元中直方圖bin個數決定 SVM::Params params; params.svmType = SVM::C_SVC; params.C = 0.1; params.kernelType = SVM::LINEAR;//SVM::LINEAR;//SVM::LINEAR; params.termCrit = TermCriteria(TermCriteria::MAX_ITER, (int)10000, 1e-6);//正樣本圖片路徑檔案,具體通過圖片生成圖片路徑檔案的程式碼,在我上傳的資源裡面可以找到 std::ifstream finPos("E:/opencv_studydocumence/opencv_study/HOG+SVM/code/Release/labels_20180206/svm20180206_x.txt");//負樣本圖片的檔案列表 std::ifstream finNeg("E:/opencv_studydocumence/opencv_study/HOG+SVM/code/Release/labels_20180206/svmtrain_neg.txt"); std::string ImgName;//所有訓練樣本的特徵向量組成的矩陣,行數等於所有樣本的個數,列數等於HOG描述子維數 cv::Mat sampleFeatureMat;//訓練樣本的類別向量,行數等於所有樣本的個數,列數等於1;1表示有目標,-1表示無目標 cv::Mat sampleLabelMat;//依次讀取正樣本圖片,生成HOG描述子 for (int num = 0; num < PosSamNO && getline(finPos, ImgName); num++) { std::cout << "Processing:" << ImgName << std::endl; std::cout << "1" << std::endl; cv::Mat image = cv::imread(ImgName);//HOG描述子向量 std::vector<float> descriptors;//計算HOG描述子,檢測視窗移動步長(8,8) hog.compute(image, descriptors, cv::Size(8, 8));//處理第一個樣本時初始化特徵向量矩陣和類別矩陣,因為只有知道了特徵向量的維數才能初始化特徵向量矩陣 if (0 == num) {//HOG描述子的維數 DescriptorDim = descriptors.size();//初始化所有訓練樣本的特徵向量組成的矩陣,行數等於所有樣本的個數,列數等於HOG描述子維數sampleFeatureMat sampleFeatureMat = cv::Mat::zeros(PosSamNO + NegSamNO + HardExampleNO, DescriptorDim, CV_32FC1);//初始化訓練樣本的類別向量,行數等於所有樣本的個數,列數等於1 sampleLabelMat = cv::Mat::zeros(PosSamNO + NegSamNO + HardExampleNO, 1, CV_32SC1); }//將計算好的HOG描述子複製到樣本特徵矩陣sampleFeatureMat for (int i = 0; i < DescriptorDim; i++) {//第num個樣本的特徵向量中的第i個元素 sampleFeatureMat.at<float>(num, i) = descriptors[i]; }//正樣本類別為17,有目標 sampleLabelMat.at<float>(num, 0) = 9; }//依次讀取負樣本圖片,生成HOG描述子 for (int num = 0; num < NegSamNO && getline(finNeg, ImgName); num++) { std::cout << "-1"<< std::endl; std::cout << "Processing:" << ImgName << std::endl; cv::Mat src = cv::imread(ImgName); cv::resize(src, src, cv::Size(64, 64));//HOG描述子向量 std::vector<float> descriptors;//計算HOG描述子,檢測視窗移動步長(8,8) hog.compute(src, descriptors, cv::Size(8, 8)); std::cout << "descriptor dimention:" << descriptors.size() << std::endl;//將計算好的HOG描述子複製到樣本特徵矩陣sampleFeatureMat for (int i = 0; i < DescriptorDim; i++) {//第PosSamNO+num個樣本的特徵向量中的第i個元素 sampleFeatureMat.at<float>(num + PosSamNO, i) = descriptors[i]; }//負樣本類別為-1,無目標 sampleLabelMat.at<float>(num + PosSamNO, 0) = -1; }//處理HardExample負樣本 if (HardExampleNO > 0) {//HardExample負樣本的檔案列表 std::ifstream finHardExample("svmtrain_hard.txt");//依次讀取HardExample負樣本圖片,生成HOG描述子 for (int num = 0; num < HardExampleNO && getline(finHardExample, ImgName); num++) { std::cout << "2" << std::endl; std::cout << "Processing:" << ImgName << std::endl; cv::Mat src = cv::imread(ImgName, cv::IMREAD_GRAYSCALE); cv::resize(src, src, cv::Size(64, 64));//HOG描述子向量 std::vector<float> descriptors;//計算HOG描述子,檢測視窗移動步長(8,8) hog.compute(src, descriptors, cv::Size(8, 8));//將計算好的HOG描述子複製到樣本特徵矩陣sampleFeatureMat for (int i = 0; i < DescriptorDim; i++) {//第PosSamNO+num個樣本的特徵向量中的第i個元素 sampleFeatureMat.at<float>(num + PosSamNO + NegSamNO, i) = descriptors[i]; }//負樣本類別為-1,無目標 sampleLabelMat.at<float>(num + PosSamNO + NegSamNO, 0) =2; } }//訓練SVM分類器 //迭代終止條件,當迭代滿1000次或誤差小於FLT_EPSILON時停止迭代 std::cout << "start training SVM" << std::endl;//cout << "Starting training process" << endl;Ptr<SVM> svm = StatModel::train<SVM>(sampleFeatureMat, ROW_SAMPLE, sampleLabelMat, params); cout << "Finished training process" << endl;//訓練分類器 //svm->train(td); std::cout << "訓練完成" << std::endl;//將訓練好的SVM模型儲存為xml檔案 svm->save("20180206_xmls/svmx_20180206.xml");return 0;}