c語言版本opencv3/4 svm+hog訓練自己的資料集——儀表盤的檢測1
專案背景:最近在做一個機器人巡檢儀表盤的專案,需要識別眾多的儀表盤並讀數。因此需要用svm識別出錶盤大體位置再進行擺盤示數的識別。
話不多說,先上效果圖訓練的圖片比較少,因此檢測框有些許的歪斜。可以增加圖片達到更準確的檢測效果。
一、訓練準備訓練集及測試集:連結:https://pan.baidu.com/s/19m0-WSNqWYYc0U94tAUyog提取碼:rcoc複製這段內容後開啟百度網盤手機App,操作更方便哦
路徑位置:
正樣本是128128的儀表圖片,如下圖:
負樣本是從整張圖片集合中裁剪的128128的圖片:
下面是將最終要識別的19201080等解析度圖片裁剪成128128小圖片的程式碼:
/***************************************************************************************************************************** 檔名:cankao4.cpp* 檔案功能:訓練並測試SVM的前一步,將圖片解析度進行調整,包括訓練集和測試集的調整* 參考來源:csdn https://xiaorun.blog.csdn.net/article/details/82902267?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param* 編寫時間:2020.10.17* 作者:狄雲* 版本:1.0.0* 時間:2020.10.17* 內容:將圖片解析度進行調整* 版本:1.1.0* 時間:2020.10.21* 內容:增加將正樣本歸一化到128*128python程式碼:功能:將當期資料夾下的檔名寫到txt檔案裡def read_directory(directory_name):for filename in os.listdir(directory_name):print(filename) # 僅僅是為了測試fw.write(filename + '\n') # 列印成功資訊# img = cv2.imread(directory_name + "/" + filename)# #####顯示圖片######## cv2.imshow(filename, img)# cv2.waitKey(0)# ####################### #####儲存圖片########## cv2.imwrite("D://wangyang//face1" + "/" + filename, img)images_path0='./'txt_save_path0='./train.txt'fw = open(txt_save_path0, "w")read_directory(images_path0)#這裡傳入所要讀取資料夾的絕對路徑,加引號(引號不能省略!)****************************************************************************************************************************/#include <iostream> #include <fstream> #include <stdlib.h> //srand()和rand()函式 #include <time.h> //time()函式 #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;int CropImageCount = 0; //裁剪出來的負樣本圖片個數 string num2str(int i){ stringstream ss; ss << i; return ss.str();}//模式選擇#define MODE_1 0 //將訓練集調整為128*128的#define MODE_2 1 //將一張圖片裁剪成各種128*128大小的作為負樣本int main(){#if MODE_1 Mat src,dst; string ImgName; string saveName;//裁剪出來的負樣本圖片檔名 ifstream fin("E:\\VS_project\\opencv_1017_test\\opencvtest\\train_picture\\train\\pos\\2\\train.txt");//開啟原始正樣本圖片檔案列表 //一行一行讀取檔案列表 while (getline(fin, ImgName)) { cout << "處理:" << ImgName << endl; ImgName = "E:\\VS_project\\opencv_1017_test\\opencvtest\\train_picture\\train\\pos\\2\\" + ImgName; cout << ImgName; src = imread(ImgName, 1);//讀取圖片 resize(src, dst, Size(128,128)); CropImageCount++; saveName = "E:\\VS_project\\opencv_1017_test\\opencvtest\\train_picture\\train\\pos\\2\\train_pos_img\\" + num2str(CropImageCount) + ".jpg"; //sprintf(saveName,"F:\\BaiduNetdiskDownload\\INRIADATA\\normalized_images\\train\\train_neg_img\\noperson%06d.jpg",++CropImageCount);//生成裁剪出的負樣本圖片的檔名 imwrite(saveName, dst);//儲存檔案 }#endif#if MODE_2 Mat src; string ImgName; string saveName;//裁剪出來的負樣本圖片檔名 ifstream fin("E:\\VS_project\\opencv_1017_test\\opencvtest\\train\\neg\\train.txt");//開啟原始負樣本圖片檔案列表 //一行一行讀取檔案列表 while (getline(fin, ImgName)) { cout << "處理:" << ImgName << endl; ImgName = "E:\\VS_project\\opencv_1017_test\\opencvtest\\train\\neg\\" + ImgName; cout << ImgName; src = imread(ImgName, 1);//讀取圖片 //printf("ImhName%s", ImgName); //cout<<"寬:"<<src.cols<<",高:"<<src.rows<<endl; //圖片大小應該能能至少包含一個64*128的視窗 if (src.cols >= 128 && src.rows >= 128) { srand(time(NULL));//設定隨機數種子 time(NULL)表示當前系統時間 //從每張圖片中隨機取樣10個64*128大小的不包含人的負樣本 for (int i = 0; i<10; i++) { int x = (rand() % (src.cols - 128)); //左上角x座標 int y = (rand() % (src.rows - 128)); //左上角y座標 //cout<<x<<","<<y<<endl; Mat imgROI = src(Rect(x, y, 128, 128)); CropImageCount++; saveName = "E:\\VS_project\\opencv_1017_test\\opencvtest\\train\\neg\\new\\" + num2str(CropImageCount) + ".jpg"; //sprintf(saveName,"F:\\BaiduNetdiskDownload\\INRIADATA\\normalized_images\\train\\train_neg_img\\noperson%06d.jpg",++CropImageCount);//生成裁剪出的負樣本圖片的檔名 imwrite(saveName, imgROI);//儲存檔案 } } }#endif return 0;}
二、訓練及測試程式碼:包含訓練和測試程式碼,透過開頭那個模式選擇。
/***************************************************************************************************************************** 檔名:cankao4.cpp* 檔案功能:svm訓練單分類,且有檢測框那種* 參考來源:csdn https://xiaorun.blog.csdn.net/article/details/82902267?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param* 編寫時間:2020.10.17* 作者:狄雲* 版本:1.0.0* 時間:2020.10.17* 內容:初步執行,跑通訓練及測試。多分類及單分類區別介紹引數介紹https://www.cnblogs.com/br170525/p/9236479.html多尺度分類介紹https://blog.csdn.net/tanmx219/article/details/82012519https://blog.csdn.net/sazass/article/details/94431965****************************************************************************************************************************/#include <iostream> #include <fstream> #include <stdlib.h> //srand()和rand()函式 #include <time.h> //time()函式 #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> #include<opencv2\opencv.hpp>#include <opencv2\imgproc\types_c.h>//模式選擇#define TRAIN_MODE 0 //訓練模式#define TEST_ONE_PICTURE_MODE_1 1 //測試一張圖片模式1#define TEST_ONE_PICTURE_MODE_2 0 //測試一張圖片模式2using namespace std;using namespace cv;using namespace ml;void get_svm_detector(const Ptr< SVM > & svm, vector< float > & hog_detector);void convert_to_ml(const std::vector< Mat > & train_samples, Mat& trainData);void load_images(const String & dirname, vector< Mat > & lst, bool showImages);void sample_neg(const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, const Size & size);void computeHOGs(const Size wsize, const vector< Mat > & lst, vector< Mat > & gradient_lst);//函式定義/////////void get_svm_detector(const Ptr< SVM >& svm, vector< float > & hog_detector){ // get the support vectors Mat sv = svm->getSupportVectors(); const int sv_total = sv.rows; // get the decision function Mat alpha, svidx; double rho = svm->getDecisionFunction(0, alpha, svidx); //CV_Assert(alpha.total() == 1 && svidx.total() == 1 && sv_total == 1); //括號中的條件不滿足時,返回錯誤 //CV_Assert((alpha.type() == CV_64F && alpha.at<double>(0) == 1.)||(alpha.type() == CV_32F && alpha.at<float>(0) == 1.f)); //CV_Assert(sv.type() == CV_32F); hog_detector.clear(); hog_detector.resize(sv.cols + 1); memcpy(&hog_detector[0], sv.ptr(), sv.cols * sizeof(hog_detector[0])); //memcpy指的是c和c++使用的記憶體複製函式,memcpy函式的功能是從源src所指的記憶體地址的起始位置開始複製n個位元組到目標dest所指的記憶體地址的起始位置中。 hog_detector[sv.cols] = (float)-rho;}//////////** Convert training/testing set to be used by OpenCV Machine Learning algorithms.*TrainData is a matrix of size (#samples x max(#cols,#rows) per samples), in 32FC1.*Transposition of samples are made if needed.*//////////void convert_to_ml(const vector< Mat > & train_samples, Mat& trainData){ //--Convert data const int rows = (int)train_samples.size(); //行數等於訓練樣本個數 const int cols = (int)std::max(train_samples[0].cols, train_samples[0].rows); //列數取樣本圖片中寬度與高度中較大的那一個 Mat tmp(1, cols, CV_32FC1); //< used for transposition if needed trainData = Mat(rows, cols, CV_32FC1); for (size_t i = 0; i < train_samples.size(); ++i) { CV_Assert(train_samples[i].cols == 1 || train_samples[i].rows == 1); if (train_samples[i].cols == 1) { transpose(train_samples[i], tmp); tmp.copyTo(trainData.row((int)i)); } else if (train_samples[i].rows == 1) { train_samples[i].copyTo(trainData.row((int)i)); } }}/////////void load_images(const String & dirname, vector< Mat > & lst, bool showImages = false){ //載入目錄下的圖片樣本 vector< String > files; glob(dirname, files); //返回一個包含有匹配檔案/目錄的陣列。出錯則返回false for (size_t i = 0; i < files.size(); ++i) { Mat img = imread(files[i]); // load the image if (img.empty()) // invalid image, skip it. { cout << files[i] << " is invalid!" << endl; continue; } if (showImages) { imshow("image", img); waitKey(1); } img_lst.push_back(img); //將Img壓入img_lst }}/////////void sample_neg(const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, const Size & size){ //該函式對每一個負樣本取樣出一個隨機的64*128尺寸的樣本,由於之前已經取樣過了,所以main函式中沒有使用該函式 Rect box; box.width = size.width; //等於檢測器寬度 box.height = size.height; //等於檢測器高度 const int size_x = box.width; const int size_y = box.height; srand((unsigned int)time(NULL)); //生成隨機數種子 for (size_t i = 0; i < full_neg_lst.size(); i++) { //對每個負樣本進行裁剪,隨機指定x,y,裁剪一個尺寸為檢測器大小的負樣本 box.x = rand() % (full_neg_lst[i].cols - size_x); box.y = rand() % (full_neg_lst[i].rows - size_y); Mat roi = full_neg_lst[i](box); neg_lst.push_back(roi.clone()); }}/////////void computeHOGs(const Size wsize, const vector< Mat > & lst, vector< Mat > & gradient_lst){ //計算HOG特徵 HOGDescriptor hog; hog.winSize = wsize; //Rect r = Rect(0, 0, wsize.width, wsize.height); //r.x += (img_lst[0].cols - r.width) / 2; //正樣本圖片的尺寸減去檢測器的尺寸,再除以2 //r.y += (img_lst[0].rows - r.height) / 2; Mat gray; vector< float > descriptors; for (size_t i = 0; i< lst.size(); i++) { cvtColor(img_lst[i], gray, COLOR_BGR2GRAY); hog.compute(gray, descriptors, Size(8, 8), Size(0, 0)); //Size(8,8)為視窗移動步長, gradient_lst.push_back(Mat(descriptors).clone()); }}/////////int test_trained_detector(String obj_det_filename, String test_dir, String videofilename){ //當videofilename為空,則只檢測圖片中的行人 cout << "Testing trained detector..." << endl; HOGDescriptor hog; hog.load(obj_det_filename); vector< String > files; glob(test_dir, files); int delay = 0; VideoCapture cap; if (videofilename != "") { cap.open(videofilename); } obj_det_filename = "testing " + obj_det_filename; namedWindow(obj_det_filename, WINDOW_NORMAL); for (size_t i = 0;; i++) { Mat img; if (cap.isOpened()) { cap >> img; delay = 1; } else if (i < files.size()) { img = imread(files[i]); } if (img.empty()) { return 0; } vector< Rect > detections; vector< double > foundWeights; hog.detectMultiScale(img, detections, foundWeights); for (size_t j = 0; j < detections.size(); j++) { if (foundWeights[j] < 0.5) continue; //清楚權值較小的檢測視窗 Scalar color = Scalar(0, foundWeights[j] * foundWeights[j] * 200, 0); rectangle(img, detections[j], color, img.cols / 400 + 1); } imshow(obj_det_filename, img); if (27 == waitKey(delay)) { return 0; } } return 0;}int main(int argc, char** argv){#if TEST_ONE_PICTURE_MODE_1 //測試單張圖片模式 //當videofilename為空,則只檢測圖片中的行人 cout << "Testing trained detector..." << endl; HOGDescriptor hog; //hog.load("D:/my_detector.yml"); Mat dst; hog.load("E:/VS_project/opencv_1017_test/opencvtest/train/1024_yibaio_1_duomubiao.yml"); Mat test_img = imread("test/0_0023.jpg");//讀取圖片 resize(test_img, test_img, Size(400,400)); //namedWindow("測試圖片", 0); //imshow("測試圖片", test_img); //waitKey(1000); if (test_img.empty()) { cout << " 待預測影象不存在: " << endl; } vector< Rect > detections; vector< double > foundWeights; hog.detectMultiScale(test_img, detections, foundWeights); for (size_t j = 0; j < detections.size(); j++) { if (foundWeights[j] < 0.) continue; //清楚權值較小的檢測視窗 Scalar color = Scalar(0, 255, 0); rectangle(test_img, detections[j], color, test_img.cols / 400 + 1); } namedWindow("result", 0); imshow("result", test_img); waitKey(1000); waitKey(1000);#endif#if TEST_ONE_PICTURE_MODE_2 //測試單張圖片模式 //當videofilename為空,則只檢測圖片中的行人 cout << "Testing trained detector..." << endl; Ptr<ml::SVM>svm = ml::SVM::load("svm6_13.xml");//載入訓練好的xml檔案, Mat test_img = imread("333333.jpg");//讀取圖片 if (test_img.empty()) { cout << " 待預測影象不存在: " << endl; } namedWindow("測試圖片", 0); imshow("測試圖片", test_img); waitKey(1000); cvtColor(test_img, test_img, COLOR_BGR2GRAY); int thickness = -1; int lineType = 8; thickness = 2; lineType = 8; HOGDescriptor hog; hog.winSize = Size(128, 128);// Set the trained svm to my_hog //hog描述子//HOGDescriptor *hog = new HOGDescriptor(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);/*************************************************************************************************線性SVM訓練完成後得到的XML檔案裡面,有一個數組,叫做support vector,還有一個數組,叫做alpha,有一個浮點數,叫做rho;將alpha矩陣同support vector相乘,注意,alpha*supportVector,將得到一個列向量。之後,再該列向量的最後新增一個元素rho。如此,變得到了一個分類器,利用該分類器,直接替換opencv中行人檢測預設的那個分類器(cv::HOGDescriptor::setSVMDetector()),就可以利用你的訓練樣本訓練出來的分類器進行行人檢測了。***************************************************************************************************/ vector< float > hog_detector; get_svm_detector(svm, hog_detector); hog.setSVMDetector(hog_detector); vector< Rect > detections; vector< double > foundWeights; hog.detectMultiScale(test_img, detections, foundWeights); for (size_t j = 0; j < detections.size(); j++) { if (foundWeights[j] < 0.5) continue; //清楚權值較小的檢測視窗 //Scalar color = Scalar(0, foundWeights[j] * foundWeights[j] * 200, 0); Scalar color = Scalar(0, 255, 0); rectangle(test_img, detections[j], color, test_img.cols / 400 + 1); } namedWindow("result", 0); imshow("result", test_img); waitKey(1000); waitKey(1000); #endif#if TRAIN_MODE cout << "HELLO WORLD" << endl; const char* keys = { "{help h| | show help message}" "{pd1 | E:/VS_project/opencv_1017_test/opencvtest/train/1/ | path of directory contains possitive images}" //正樣本1 "{pd2 | E:/VS_project/opencv_1017_test/opencvtest/train/2/ | path of directory contains possitive images}" //正樣本2 "{nd | E:/VS_project/opencv_1017_test/opencvtest/train/neg/ | path of directory contains negative images}" //負樣本 "{td | E:/VS_project/opencv_1017_test/opencvtest/test/ | path of directory contains test images}" //測試樣本 "{fn | E:/VS_project/opencv_1017_test/opencvtest/train/1024_yibaio_1_duomubiao.yml | file name of trained SVM}" //儲存的模型 "{tv | | test video file name}" "{dw | 128 | width of the detector}" //檢測器寬度 "{dh | 128 | height of the detector}" "{d |false| train twice}" "{t |true| test a trained detector}" "{v |false| visualize training steps}" }; CommandLineParser parser(argc, argv, keys); //命令列函式,讀取keys中的字元, 其中key的格式為:名字 簡稱| 內容 |提示字元。 if (parser.has("help")) { parser.printMessage(); exit(0); } String pos_dir_1 = parser.get< String >("pd1"); //正樣本1目錄 String pos_dir_2 = parser.get< String >("pd2"); //正樣本2目錄 cout << pos_dir_1 << endl; cout << pos_dir_2 << endl; String neg_dir = parser.get< String >("nd"); //負樣本目錄 String test_dir = parser.get< String >("td"); //測試樣本目錄 String obj_det_filename = parser.get< String >("fn"); //訓練好的SVM檢測器檔名 String videofilename = parser.get< String >("tv"); //測試影片 int detector_width = parser.get< int >("dw"); //檢測器寬度 int detector_height = parser.get< int >("dh"); //檢測器高度 bool test_detector = parser.get< bool >("t"); //測試訓練好的檢測器 bool train_twice = parser.get< bool >("d"); //訓練兩次 bool visualization = parser.get< bool >("v"); //訓練過程視覺化(建議false,不然爆炸) //根據評論,以下5行程式碼在初次執行時,請註釋掉。該段程式碼是為了對已經訓練好的模型進行測試的,初次執行時,因為還未有任何模型引數,所以可能會報錯。 //if (test_detector) //若為true,測對測試集進行測試 //{ // test_trained_detector(obj_det_filename, test_dir, videofilename); // exit(0); //} if (pos_dir_1.empty() || pos_dir_2.empty() || neg_dir.empty()) //檢測訓練集和測試集合是否是空的 { parser.printMessage(); cout << "Wrong number of parameters.\n\n" << "Example command line:\n" << argv[0] << " -pd=/INRIAPerson/96X160H96/Train/pos -nd=/INRIAPerson/neg -td=/INRIAPerson/Test/pos -fn=HOGpedestrian96x160.yml -d\n" << "\nExample command line for testing trained detector:\n" << argv[0] << " -t -dw=96 -dh=160 -fn=HOGpedestrian96x160.yml -td=/INRIAPerson/Test/pos"; exit(1); } vector< Mat > pos_lst_1, //正樣本1圖片向量 pos_lst_2, //正樣本2圖片向量 full_neg_lst, //負樣本圖片向量 neg_lst, //取樣後的負樣本圖片向量 gradient_lst; //HOG描述符存入到該梯度資訊裡面 vector< int > labels; //標籤向量 clog << "Positive images are being loaded..."; //正樣本讀取結束/*************************************************************************************************************** 1、載入正樣本1圖片 ****************************************************************************************************************/ load_images(pos_dir_1, pos_lst_1, visualization); //載入圖片 pos正樣本的尺寸為96*160 if (pos_lst_1.size() > 0) { clog << "...[done]" << endl; } else { clog << "no image in " << pos_dir_1 << endl; return 1; } Size pos_image_size = pos_lst_1[0].size(); //令尺寸變數pos_image_size=正樣本尺寸 //檢測所有正樣本是否具有相同尺寸 for (size_t i = 0; i < pos_lst_1.size(); ++i) { if (pos_lst_1[i].size() != pos_image_size) { cout << "All positive images should be same size!" << endl; exit(1); } } pos_image_size = pos_image_size / 8 * 8; //令pos_image_size的尺寸為檢測器的尺寸 if (detector_width && detector_height) { pos_image_size = Size(detector_width, detector_height); } labels.assign(pos_lst_1.size(), +1); //assign()為labels分配pos_lst.size()大小的容器,用+1填充 表示為正樣本 const unsigned int old = (unsigned int)labels.size(); //舊標籤大小 clog << "Negative 1 images are being loaded...";/************************************************************************************************************** 2、載入正樣本2圖片****************************************************************************************************************/ //load_images(pos_dir_2, pos_lst_2, visualization); //載入圖片 pos正樣本的尺寸為96*160 //if (pos_lst_2.size() > 0) //{ // clog << "...[done]" << endl; //} //else //{ // clog << "no image in " << pos_dir_2 << endl; // return 1; //} Size pos_image_size = pos_lst_2[0].size(); 令尺寸變數pos_image_size=正樣本尺寸 檢測所有正樣本是否具有相同尺寸 //for (size_t i = 0; i < pos_lst_2.size(); ++i) //{ // if (pos_lst_2[i].size() != pos_image_size) // { // cout << "All positive images should be same size!" << endl; // exit(1); // } //} //pos_image_size = pos_image_size / 8 * 8; 令pos_image_size的尺寸為檢測器的尺寸 //if (detector_width && detector_height) //{ // pos_image_size = Size(detector_width, detector_height); //} labels.assign(pos_lst_2.size(), +2); //labels.insert(labels.end(), pos_lst_2.size(), +2); assign()為labels分配pos_lst.size()大小的容器,用+1填充 表示為正樣本 //old = (unsigned int)labels.size(); //舊標籤大小 //clog << "Negative 2 images are being loaded..."; /************************************************************************************************************** 3、載入負樣本圖片 ****************************************************************************************************************/ load_images(neg_dir, neg_lst, false); //載入負樣本圖片 //sample_neg(full_neg_lst, neg_lst, pos_image_size); clog << "...[done]" << endl; labels.insert(labels.end(), neg_lst.size(), -1); //在labels向量的尾部新增neg_lst.size()大小的容器,用-1填充 表示為負樣本 CV_Assert(old < labels.size()); //CV_Assert()作用:CV_Assert()若括號中的表示式值為false,則返回一個錯誤資訊。 /************************************************************************************************************** 4、計算正樣本1 HOG特徵 ****************************************************************************************************************/ clog << "Histogram of Gradients are being calculated for positive images..."; computeHOGs(pos_image_size, pos_lst_1, gradient_lst); //計算正樣本圖片的HOG特徵 clog << "...[done]" << endl; /************************************************************************************************************** 5、計算正樣本2 HOG特徵 ****************************************************************************************************************/ //clog << "Histogram of Gradients are being calculated for positive images..."; //computeHOGs(pos_image_size, pos_lst_2, gradient_lst); //計算正樣本圖片的HOG特徵 //clog << "...[done]" << endl; /************************************************************************************************************** 6、計算負樣本 HOG特徵 ****************************************************************************************************************/ clog << "Histogram of Gradients are being calculated for negative images..."; computeHOGs(pos_image_size, neg_lst, gradient_lst); //計算負樣本圖片的HOG特徵 clog << "...[done]" << endl; /************************************************************************************************************** 7、訓練 ****************************************************************************************************************/ Mat train_data; convert_to_ml(gradient_lst, train_data); //轉化為ml所需的訓練資料形式 clog << "Training SVM..."; Ptr< SVM > svm = SVM::create(); /* Default values to train SVM */ svm->setCoef0(0.0); svm->setDegree(3); svm->setTermCriteria(TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 1000, 1e-3)); svm->setGamma(0); svm->setKernel(SVM::LINEAR); //採用線性核函,其他的sigmoid 和RBF 可自行設定,其值由0-5。 svm->setNu(0.5); svm->setP(0.1); // for EPSILON_SVR, epsilon in loss function? svm->setC(0.01); // From paper, soft classifier //svm->setType(SVM::C_SVC); // C_SVC; // EPSILON_SVR; // may be also NU_SVR; // do regression task svm->setType(SVM::EPS_SVR); // C_SVC; // EPSILON_SVR; // may be also NU_SVR; // do regression task svm->train(train_data, ROW_SAMPLE, Mat(labels)); clog << "...[done]" << endl; vector< float > hog_detector; //定義hog檢測器 get_svm_detector(svm, hog_detector); //得到訓練好的檢測器 HOGDescriptor hog; hog.winSize = pos_image_size; //視窗大小 hog.setSVMDetector(hog_detector); hog.save(obj_det_filename); //儲存分類器 //test_trained_detector(obj_det_filename, test_dir, videofilename); //檢測訓練集 #endif return 0;}
更多的效果圖
最新評論