loading...
  1. (Best and Easy) Support Vector Machines(SVM) + HOG Tutorial | OpenCV 3.0, 3.1, 3.2, 3.3 | Windows 10 | Visual Studio 2015 | x64 | Train & Test

(Best and Easy) Support Vector Machines(SVM) + HOG Tutorial | OpenCV 3.0, 3.1, 3.2, 3.3 | Windows 10 | Visual Studio 2015 | x64 | Train & Test

Hello Friends,

Have you ever wondered how can you create your own OpenCV 3 Support Vector Machines(SVM) + HOG Classifier? Did you want to create your own classifier that actually works? Are you tried of searching google for a good SVM tutorial but all you find it bunch of example SVM Tutorials that does nothing but show a test image with useless circles?
If the answer is Yes! , you have come to the right place my friend.
I have myself struggled a lot to get this working all because there wasn’t a good tutorial anywhere that existed which would teach you the SVM.
In this tutorial, we’ll create a simple Car Detector using SVM aka Support Vector Machines.

So, before we get started, let’s look at the pre-requisites.

1) Visual Studio 2015
2) Windows 10 x64 (works best)
3) OpenCV 3.0, 3.1, 3.2, 3.3 and above
4) Patience !!

If you are someone who doesn’t really bother what’s going on behind the scene and would want to straight out implement this goddamn classifier, then without further due, let’s look at the code. (Although, i would prefer that you understand what’s what before actually using it, but I know you always don’t have that options 🙂 !!!)

Special Note: A lot of things have changed between OpenCV 2.x and OpenCV 3.x builds with respect to SVM. I mean if you are trying to port the code or maybe using the existing classifier that you created in OpenCV 2.x in OpenCV 3.x, man you better off start fresh because things have changed like hell.

Step by Step for Training Phase:
1) Create a new ’empty’ project in Visual Studio 2015
2) Link the OpenCV Includes and Libs with the project (Follow this link on how to install OpenCV 3.3 with Visual Studio and run a test Solution)
3) For Training, Create 3 files namely:
a) Train.cpp
b) Datamanager.cpp
c) Datamanager.h
4) Name your classifier file under “svm->save(“firetrain.yml”);” to your desired filename
5) Create a folder called “Positive” inside the project and add all the positive images to it. (Size 64×64)
6) Create a folder called “Negative” inside the project and add all the Negative images to it. (Size 64×64)
7) (Optional) Use svm->trainAuto(td); instead of svm->train(td) to set value of C and gamma, but it takes a lot of time

Note: Shortly, after this post, i’ll create a crop_image software to assist you with the cropping of images.

Step by Step for Detection Phase:
1) Create a new ’empty’ project in Visual Studio 2015
2) Link the OpenCV Includes and Libs with the project (Follow this link on how to install OpenCV 3.3 with Visual Studio and run a test Solution)
3) For Detection, Create 1 file called “DetectCode.cpp” by excluding the above 3 training files and also referencing the classifier file in “#define TRAINED_SVM “firetrain.yml” that you created in training phase.

Note: There are hog parameters that you need to tune accordingly. I have plans to create a HOG based UI software, so that you can easily get all those parameters from your referenced image. Stay tuned for updates for it.

Algorithm pipeline(Training svm):
– > From the image dataset that you have created, randomly separate it into training and test set(80%, 20% split)
– > Set the hog windowSize(64×64) and Compute the HOG features for the training image set containing vehicles and non-vehicles.
– > Train a SVM using these HOG features. (Use linear or RBF SVM)
– > Test the trained SVM on the separate test imageset and evaluate the results and performance.
– > For the real world test, run a sliding window and use the SVM from above to predict vehicle/non-vehicle.

Algorithm pipeline(Detectting car in video):
– > Extract individual frame of the video frames.
– > Convert each captured frame into grayscale image.
– > Discard the upper half containing the sky part.
– > Choose a sliding window size, and resize to the trained size; Use SVM to predict
– > Filter the detect points for false positive(use template matching only for the subsection of detected)

Codes :

#Train.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//train.cpp
#include <opencv2/opencv.hpp>
//#include <opencv2/ml.hpp>
 
#include <iostream>
#include <string>
//#include "util/imageutils.h"
#include "DataSetManager.h"
 
 
 
using namespace std;
using namespace cv;
using namespace cv::ml;
 
 
 
HOGDescriptor hog(
        Size(64,64), //winSize
        Size(8,8), //blocksize
        Size(8,8), //blockStride,
        Size(8,8), //cellSize,
                 9, //nbins,
                  1, //derivAper,
                 -1, //winSigma,
                  0, //histogramNormType,
                0.2, //L2HysThresh,
                  0,//gammal correction,
                  64,//nlevels=64
                  1);
 
 
 
 
void getSVMParams(SVM *svm)
{
	cout << "Kernel type     : " << svm->getKernelType() << endl;
	cout << "Type            : " << svm->getType() << endl;
	cout << "C               : " << svm->getC() << endl;
	cout << "Degree          : " << svm->getDegree() << endl;
	cout << "Nu              : " << svm->getNu() << endl;
	cout << "Gamma           : " << svm->getGamma() << endl;
}
 
void SVMtrain(Mat &trainMat, vector<int> &trainLabels, Mat &testResponse, Mat &testMat) {
	Ptr<SVM> svm = SVM::create();
	svm->setGamma(0.50625);
        svm->setC(100);
	svm->setKernel(SVM::RBF);
	svm->setType(SVM::C_SVC);
	Ptr<TrainData> td = TrainData::create(trainMat, ROW_SAMPLE, trainLabels);
	svm->train(td);
	//svm->trainAuto(td);
	svm->save("firetrain.yml");
	svm->predict(testMat, testResponse);
	getSVMParams(svm);
 
	/*
	To acheive 100% rate.
	Descriptor Size : 576
Kernel type     : 2
Type            : 100
C               : 2.5
Degree          : 0
Nu              : 0
Gamma           : 0.03375
the accuracy is :100
 
	*/
 
}
 
void SVMevaluate(Mat &testResponse, float &count, float &accuracy, vector<int> &testLabels) {
 
	for (int i = 0; i<testResponse.rows; i++)
	{
		//cout << testResponse.at<float>(i,0) << " " << testLabels[i] << endl;
		if (testResponse.at<float>(i, 0) == testLabels[i]) {
			count = count + 1;
		}
	}
	accuracy = (count / testResponse.rows) * 100;
}
void computeHOG(vector<Mat> &inputCells, vector<vector<float> > &outputHOG) {
 
	for (int y = 0; y<inputCells.size(); y++) {
		vector<float> descriptors;
		hog.compute(inputCells[y], descriptors);
		outputHOG.push_back(descriptors);
	}
}
void ConvertVectortoMatrix(vector<vector<float> > &ipHOG, Mat & opMat)
{
 
	int descriptor_size = ipHOG[0].size();
	for (int i = 0; i<ipHOG.size(); i++) {
		for (int j = 0; j<descriptor_size; j++) {
			opMat.at<float>(i, j) = ipHOG[i][j];
		}
	}
}
 
int main(int argc, char ** argv)
{
 
	/**************** user code starts *******************/
	cout << " User code starts" << endl;
	DataSetManager dm;
	dm.addData("Positive", 1);// positive train data
	dm.addData("Negative", -1);// negative train data
										//dm.addData("./testfolder/test/",1);// test data
										// can also provide fullpath "/home/pankaj/opencv/programs/udacity/carND/cardetection"
										//dm.addData("./vehicles/vehicles/",2);
	cout << "Total data length : " << dm.getTotalDataNum() << endl;
	dm.distribute();
	dm.display();
	/***********load all the dataset into vector of Mat*********/
	vector<Mat> trainCells;
	vector<Mat> testCells;
	vector<int> trainLabels;
	vector<int> testLabels;
	for (int i = 0; i<dm.getTotalTrainDataNum(); i++) {
		string imageName = dm.TrainData[i].filename;
		Mat img = imread(imageName, CV_LOAD_IMAGE_GRAYSCALE);
		trainCells.push_back(img);
		trainLabels.push_back(dm.TrainData[i].label);
	}
	for (int i = 0; i<dm.getTotalTestDataNum(); i++) {
		string imageName = dm.TestData[i].filename;
		Mat img = imread(imageName, CV_LOAD_IMAGE_GRAYSCALE);
		testCells.push_back(img);
		testLabels.push_back(dm.TestData[i].label);
	}
	//loadTrainTestLabel(pathName,trainCells,testCells,trainLabels,testLabels);
	/***********Computer HOG descriptor for all the training and testcells *********/
	std::vector<std::vector<float> > trainHOG;
	std::vector<std::vector<float> > testHOG;
 
	//compute_hog(trainCells, gradient_lst);
	computeHOG(trainCells, trainHOG);
	computeHOG(testCells, testHOG);
 
	int descriptor_size = trainHOG[0].size();
	cout << "Descriptor Size : " << descriptor_size << endl;
	/******** HOG descriptor ends ****************************/
 
	/********Prepeare trainData and test data and call SVM ML algorithm*********/
	Mat trainMat(trainHOG.size(), descriptor_size, CV_32FC1);
	Mat testMat(testHOG.size(), descriptor_size, CV_32FC1);
	ConvertVectortoMatrix(trainHOG, trainMat);
	ConvertVectortoMatrix(testHOG, testMat);
 
	Mat testResponse;
	SVMtrain(trainMat, trainLabels, testResponse, testMat);
 
	float count = 0;
	float accuracy = 0;
	SVMevaluate(testResponse, count, accuracy, testLabels);
 
	cout << "the accuracy is :" << accuracy << endl;
 
	/**************** user code ends *******************/
 
	//waitKey(0);
	char ch;
	cin >> ch;
	return 0;
 
}

#DataSetManager.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//DataSetManager.cpp
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
#include "DataSetManager.h"
#include <algorithm>
 
using namespace cv;
using std::cout;
using std::endl;
using std::string;
 
#define EN_DEBUG
 
//constructor
DataSetManager::DataSetManager() :testDataPercent(20), validationDataPercent(0), totalDataNum(0), totalTrainDataNum(0), totalTestDataNum(0) {
	// default parameter initialization here
}
// setter and getter methods
 
void DataSetManager::setTestDataPercent(float num) { testDataPercent = num; }
void DataSetManager::setValidationDataPercent(float num) { validationDataPercent = num; }
int DataSetManager::getTotalDataNum() { return totalDataNum; }
int DataSetManager::getTotalTrainDataNum() { return totalTrainDataNum; }
int DataSetManager::getTotalTestDataNum() { return totalTestDataNum; }
 
//main functions
void DataSetManager::addData(std::string folderName, int classlabel) {
	// notice here that we are using the Opencv's embedded "String" class 
	std::vector<cv::String> filenames;
	cv::String folder = folderName.c_str();// converting from std::string->cv::String
	cv::glob(folder, filenames);
	// for each of these fileNames append them into the DataSet structure with labels
	for (size_t i = 0; i<filenames.size(); i++) {
		DataSet tempDataset;
		tempDataset.filename = static_cast<std::string>(filenames[i]);
		tempDataset.label = classlabel;
		dataList.push_back(tempDataset);
	}
	totalDataNum = totalDataNum + filenames.size();
}
 
// the distribute functions distributes the whole data into training data and test data.
void DataSetManager::distribute() {
	int n_test_valid = static_cast<int> (
		(validationDataPercent*totalDataNum / 100) + (testDataPercent*totalDataNum / 100));
	//cout<<" n_test_valid == "<< n_test_valid<<endl;
	int counter = 0;
	std::vector<int> rndIndex;
	std::vector<int>::iterator it;
	DataSet tempDataset;
	while (counter<n_test_valid) {
		// random number between [0-totalDataNum-1]
		int num = rand() % totalDataNum;
		it = std::find(rndIndex.begin(), rndIndex.end(), num);
		if (it != rndIndex.end())
			continue;//skip the rest of the loop if this num is already present
					 //we are here only if the 'num' is unique
		rndIndex.push_back(num);
		//cout<<" random number == "<< num<<endl;
		tempDataset.filename = static_cast<std::string>(dataList[num].filename);
		tempDataset.label = dataList[num].label;
		TestData.push_back(tempDataset);
		counter++;
	}
	std::sort(rndIndex.begin(), rndIndex.end());//sort in ascending order
#ifdef EN_DEBUG
	cout << "sortedIndexes: " << endl;
	for (std::vector<int>::iterator it = rndIndex.begin(); it != rndIndex.end(); ++it)
		cout << " " << *it << endl;
	cout << endl;
#endif 
 
	//cout<<" now fill the TrainData; only exclude the testData"<<endl;
 
	int curIdx = 0;
	int current = rndIndex[curIdx];
	//cout<<"rndIndex.size()= "<<rndIndex.size()<<endl;
	for (int i = 0; i<dataList.size(); i++) {
		//cout<<" current == "<< current<<" i = "<<i<<" curIndx= "<< curIdx;
		if (i != current) {
			//cout<<" inside Train";
			tempDataset.filename = static_cast<std::string>(dataList[i].filename);
			tempDataset.label = dataList[i].label;
			TrainData.push_back(tempDataset);
		}
		else if ((current == i) && (curIdx<rndIndex.size() - 1)) {
			//cout<<" inside Test";
			current = rndIndex[++curIdx];
		}
	}
 
	totalTrainDataNum = TrainData.size();
	totalTestDataNum = TestData.size();
}
void DataSetManager::display() {
 
	// display Data
	cout << "Training data length: " << getTotalTrainDataNum() << endl;
#ifdef EN_DEBUG
	for (int i = 0; i<getTotalTrainDataNum(); i++) {
		cout << " filename: " << TrainData[i].filename;
		cout << "	\tlabels: " << TrainData[i].label << endl;
	}
#endif
	cout << "Test data length: " << getTotalTestDataNum() << endl;
#ifdef EN_DEBUG
	for (int i = 0; i<getTotalTestDataNum(); i++) {
		cout << " filename: " << TestData[i].filename;
		cout << " \tlabels: " << TestData[i].label << endl;
	}
#endif
 
}

#DataSetManager.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#ifndef _DATASETMANAGER_H
#define _DATASETMANAGER_H
 
#include <iostream>
 
struct DataSet {
	std::string filename;
	float label;
};
 
class DataSetManager
{
private:
	// user defined data member
	float testDataPercent;
	float validationDataPercent;
 
	// derrived or internally calculated
	int totalDataNum;
	int totalTrainDataNum;
	int totalTestDataNum;
	int totalValidationDataNum;
 
public:
	//constructor
	DataSetManager();
 
	// setter and getter methods
	void setTestDataPercent(float num);
	void setValidationDataPercent(float num);
 
	int getTotalDataNum();
	int getTotalTrainDataNum();
	int getTotalTestDataNum();
	int getTotalValidationDataNum();
 
	// primary functions of the class
	void addData(std::string folderName, int classlabel);
	void read();
	void display();// displays the read file names for debugging
	void distribute();
	// ideally these are private; need to update
	std::vector<DataSet> dataList;
	std::vector<DataSet> TrainData;
	std::vector<DataSet> TestData;
	std::vector<DataSet> ValidationData;
};
 
#endif

DetectCode.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
//detectcar.cpp
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <ctime>
 
 
#include <io.h>
#include <memory>
 
 
#define WINDOW_NAME "WINDOW"
 
#define TRAFFIC_VIDEO_FILE "7.avi"
#define TRAINED_SVM "firetrain.yml" 
#define	IMAGE_SIZE Size(40,40)
#define save_video true
#define OUT_Video_File "march323230_project_video.avi"
 
using namespace cv;
using namespace cv::ml;
using namespace std;
 
bool file_exists(const string &file);
 
void draw_locations(Mat & img, const vector< Rect > & locations, const Scalar & color);
 
void readImage(string imgname, Mat & im);
//void test_image(Mat & img, const Size & size);
void test_video(const Size & size);
bool checkIfpatchIsVehicle(Mat & img2check);
 
void printHOGParams(HOGDescriptor &hog)
{
	cout << "HOG descriptor size is " << hog.getDescriptorSize() << endl;
	cout << "hog.windowSize: " << hog.winSize << endl;
	cout << " cellsize " << hog.cellSize << endl;
	cout << " hog.nbins " << hog.nbins << endl;
	cout << " blockSize " << hog.blockSize << endl;
	cout << " blockStride " << hog.blockStride << endl;
	cout << " hog.nlevels " << hog.nlevels << endl;
	cout << " hog.winSigma " << hog.winSigma << endl;
	cout << " hog.free_coef  " << hog.free_coef << endl;
	cout << " hog.DEFAULT_NLEVELS " << hog.DEFAULT_NLEVELS << endl;
 
}
 
 
int main(int argc, char** argv)
{
 
 
	test_video(IMAGE_SIZE);
	return 0;
}
void readImage(string imgname, Mat & im) {
 
	im = imread("54.jpg", IMREAD_COLOR);
	if (im.empty())
	{
		cout << " Invalid image read, imgname =argv[1] = " << imgname << endl;
		CV_Assert(false);
	}
	//cout<<"****** successfully image read, imgname = "<<imgname<<endl;
}
 
bool file_exists(const string &file)
{
	return _access(file.c_str(), 0) == 0;
}
 
 
 
 
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);
	cout << "alpha = " << alpha << endl;
	//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]));
	hog_detector[sv.cols] = (float)-rho;
}
 
void draw_locations(Mat & img, const vector< Rect > & locations, const Scalar & color)
{
	if (!locations.empty())
	{
		vector< Rect >::const_iterator loc = locations.begin();
		vector< Rect >::const_iterator end = locations.end();
		for (; loc != end; ++loc)
		{
			rectangle(img, *loc, color, 2);
		}
	}
}
 
void test_video(const Size & size)
{
	char key = 27;
	Mat img, draw;
	Ptr<SVM> svm;
	HOGDescriptor hog;
	hog.winSize = size;
	vector< Rect > locations;
	vector< Rect > found_filtered;
 
	// Load the trained SVM.
	svm = StatModel::load<SVM>(TRAINED_SVM);
	// Set the trained svm to my_hog
	vector< float > hog_detector;
	get_svm_detector(svm, hog_detector);
	hog.setSVMDetector(hog_detector);
	printHOGParams(hog);
 
	VideoCapture video;
	// Open the video file.
	video.open(TRAFFIC_VIDEO_FILE);
	if (!video.isOpened())
	{
		cerr << "Unable to open the device" << endl;
		exit(-1);
	}
	// Get the frame rate
	double rate = video.get(CV_CAP_PROP_FPS);
	cout << " Frame rate : " << rate << endl;
	cout << " Input video codec :" << video.get(CV_CAP_PROP_FOURCC);
	// initilaize the video writer object to write the video output
	std::string outputFile(OUT_Video_File);
	VideoWriter writer;
	int codec = static_cast<int>(video.get(CV_CAP_PROP_FOURCC));
	//int codec = CV_FOURCC('M', 'J', 'P', 'G');
	bool isWriterInitialized = false;
 
	int num_of_vehicles = 0;
	bool end_of_process = false;
	while (!end_of_process)
	{
		video >> img;
		if (img.empty())
			break;
 
 
		draw = img.clone();
		Mat cropped;
		cv::resize(draw, cropped, Size(720, 560));
 
		Mat temp, temp3;
		cvtColor(cropped, temp, COLOR_BGR2GRAY);
		/*Mat bgr[3];   //destination array
		split(temp3,bgr);//split source
		temp = bgr[0]+bgr[2];
		*/
		if (isWriterInitialized) {
			//execute only once
			isWriterInitialized = true;
			/*writer.open(outputFile,
			capture.get(CV_CAP_PROP_FOURCC),
			capture.get(CV_CAP_PROP_FPS),
			Size(capture.get(CV_CAP_PROP_FRAME_WIDTH),capture.get(CV_CAP_PROP_FRAME_HEIGHT)),
			true);*/
			writer.open(outputFile, codec, rate, cropped.size(), true);
		}
 
 
		locations.clear();
		// Rect(x,y,w,h) w->width=cols;h->rows
		// first remove the upper 50% from height  Original Cropped =size(720,560)=(cols,rows)
		Mat roi = temp(Rect(0, temp.rows*0.5, temp.cols, temp.rows - temp.rows*0.5));
		//size(roi) = size(720,280)
		//cout<<"roi.size() = "<<roi.size()<<endl;
		int y_offset = temp.rows*0.5;
		//again crop the lower 10 % to remove the images near dashboard-> remove false positives
		roi = roi(Rect(0, 0, roi.cols, roi.rows - 100));
		//cout<<"roi.size() = "<<roi.size()<<endl;
		//no offset required as this is the lower row colums.
 
		//hog.detectMultiScale(roi, locations);
		//hog.detectMultiScale(roi, locations, 1, Size(50, 50), Size(32, 32), 1, 2);//对图片进行多尺度行人检测
 
		hog.detectMultiScale(roi, locations, 0.00, Size(4, 8), Size(0, 0), 1.05, 2);//less false positive
																					//hog.detectMultiScale(roi, locations, 0.00, Size(8,8), Size(0,0), 1.05, 2);// less true negative(missed)
																					// add the offset
 
 
 
		std::vector<Rect>::iterator it = locations.begin();
		std::vector<Rect>::iterator itend = locations.end();
		vector<Rect> actuallocations;
		bool isVehicle = false;
		for (; it != itend; it++)
		{
			Rect current = *it;
			//cout<<" Rect current = "<< current<<endl;
			//cout<<" roi size= "<<roi.size()<<endl;
			Mat roi2Check = roi(Rect(current.x, current.y, current.width, current.height));//define a roi of 50x50
																						   //cout<<" roi2Check size= "<<roi2Check.size()<<endl;
			isVehicle = checkIfpatchIsVehicle(roi2Check);
			if (isVehicle)
				actuallocations.push_back(Rect(current.x, current.y + y_offset, current.width, current.height));
		}
		if (0 != actuallocations.size())
			draw_locations(cropped, actuallocations, Scalar(0, 255, 0));
 
		imshow(WINDOW_NAME, cropped);
 
 
 
 
 
		if (save_video)
			writer.write(cropped);
		//wait  infinite fro keypress
		key = (char)waitKey(3);
		if (27 == key)
			end_of_process = true;
	}
	// Close the video file.
	// Not required since called by destructor
	writer.release();
	video.release();
}
 
bool checkIfpatchIsVehicle(Mat & img2check)
{
	//cout<<"******inside function checkIfPatchIsVehicle "<<endl;
	bool isVehicle = false;
	//util::imdisp(img2check,"im2check");
	vector<string> templateList;
	templateList.push_back("temp1.png"); templateList.push_back("temp2.png");
	templateList.push_back("temp3.png"); templateList.push_back("temp4.png");
	templateList.push_back("temp5.png"); templateList.push_back("temp6.png");
	templateList.push_back("temp7.png");
	//templateList.push_back("temp8.png");
	//templateList.push_back("temp9.png");templateList.push_back("temp10.png");
 
	Mat matchScore = Mat::zeros(7, 1, CV_32FC1);
 
	for (int ii = 0; ii<templateList.size(); ii++) {
		Mat result;
 
		string imgname = templateList.at(ii);
		Mat templ, img2check_copy;
		readImage(imgname, templ);
		cvtColor(templ, templ, COLOR_BGR2GRAY);
		cv::resize(img2check, img2check, Size(50, 50));
		cv::resize(templ, templ, Size(50, 50));
		int result_cols = img2check.cols - templ.cols + 1;
		int result_rows = img2check.rows - templ.rows + 1;
 
		result.create(result_rows, result_cols, CV_32FC1);
 
		Canny(img2check, img2check_copy, 50, 150);
 
		//util::imdisp(img2check_copy,"canny");
 
 
		/// Do the Matching and Normalize
		matchTemplate(img2check_copy, templ, result, CV_TM_CCORR_NORMED);
 
		/// Localizing the best match with minMaxLoc
		double minVal; double maxVal; Point minLoc; Point maxLoc;
		Point matchLoc;
		minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
		matchScore.at<float>(ii, 0) = maxVal;
		if (maxVal>0.15)
			isVehicle = true;
	}
	//cout<<"MatchScore = "<<endl<<matchScore<<endl;
	float total = sum(matchScore)[0];
	cout << "sum(Matchscore) = " << cv::sum(matchScore)[0] << std::endl;
	if (total>0.13*templateList.size())
		isVehicle = true;
	//waitKey();
	return isVehicle;
}

Files for Download
Test Images containing Positive and Negative Dataset
1) testdatafolder

(Easy & Fast) Pre-Compiled OpenCV Libraries and Headers for 3.2 with Visual Studio 2015 x64 Windows 10 Support
Modern C++ libraries for your OpenCV toolbox




3 thoughts on “(Best and Easy) Support Vector Machines(SVM) + HOG Tutorial | OpenCV 3.0, 3.1, 3.2, 3.3 | Windows 10 | Visual Studio 2015 | x64 | Train & Test”

  1. jiesen says:

    Hi, where is the Traffic video you used for testing? Detection of my test videos is very slow.

  2. Yunus Dönmez says:

    I am wondering.The validationDataPercent value is 0.Why is not 80.I couldn’t understand it.

    1. Editor says:

      you can configure that as per your need.

Leave a Reply

Your email address will not be published. Required fields are marked *

Welcome to OpenCV World !! Come as a Guest, stay as a Family