(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
Hi, where is the Traffic video you used for testing? Detection of my test videos is very slow.
I am wondering.The validationDataPercent value is 0.Why is not 80.I couldn’t understand it.
you can configure that as per your need.