首頁>技術>

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;}
更多的效果圖

15
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Python圖表繪製很簡單,一文帶你學會如何生成帶圖例的餅圖