A few months ago, I wrote an article about MATLAB's implementation of SVM+HOG for multi-classification of images. Link: http://blog.csdn.net/cuixing001/article/details/70908064 It was first implemented with opencv, but the recognition effect Very bad, I thought I wrote the wrong code, and then I struggled for a long time, only to find that there is a big problem with the selection of the kernel function! This time it was changed to a linear kernel, and the effect is good in these pictures (the image dataset used is: link: https://pan.baidu.com/s/1i5OhC7z password: utn7 ).
The OpenCV code is as follows:
//SVM multi-class training test #include <opencv2/opencv.hpp> #include <iostream> #include <fstream> using namespace cv; using namespace std; Size imageSize = Size(64, 64); void coumputeHog(const Mat& src, vector<float> &descriptors) { HOGDescriptor myHog = HOGDescriptor(imageSize, Size(16, 16), cvSize(8, 8), cvSize(8, 8), 9); myHog.compute(src.clone(),descriptors,Size(1,1),Size(0,0)); } int main(int argc, char** argv){ ifstream inLabels("myImageLabels.txt"), inImages("myImageList.txt"),inTestimage("myImagetest.txt"); string imageName; signed imageLabel; vector<Mat> vecImages; vector<int> vecLabels; CvSVM *mySVM = new CvSVM(); CvSVMParams params = CvSVMParams(); params.svm_type = CvSVM::C_SVC; params.kernel_type = CvSVM::LINEAR; params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 10000, 1e-10); vector<float> vecDescriptors; #if(1) //Whether training is required while ((inImages>>imageName)&&(inLabels>>imageLabel)) { Mat src = imread(imageName, 0); resize(src, src, imageSize); vecImages.push_back(src); vecLabels.push_back(imageLabel); } inLabels.close(); inImages.close(); Mat dataDescriptors; Mat dataResponse = (Mat) vecLabels; for (size_t i = 0; i < vecImages.size(); i++) { Mat src = vecImages[i]; Mat tempRow; coumputeHog(src, vecDescriptors); if (i == 0) { dataDescriptors = Mat::zeros(vecImages.size(), vecDescriptors.size(), CV_32FC1); } tempRow = ((Mat)vecDescriptors).t(); tempRow.row(0).copyTo(dataDescriptors.row(i)); } mySVM->train(dataDescriptors, dataResponse, Mat(), Mat(), params); string svmName = to_string(88) + "_mysvm.xml"; mySVM->save(svmName.c_str()); #else mySVM->load("mysvm.xml"); #endif // predict string testPath; while (inTestimage >> testPath) { Mat test = imread(testPath, 0); resize(test, test, imageSize); vector<float> imageDescriptor; coumputeHog(test, imageDescriptor); Mat testDescriptor = Mat::zeros(1, imageDescriptor.size(), CV_32FC1); for (size_t i = 0; i < imageDescriptor.size(); i++) { testDescriptor.at<float>(0, i) = imageDescriptor[i]; } float label = mySVM->predict(testDescriptor, false); cout << label << endl; imshow("test image", test); waitKey(0); } inTestimage.close(); delete mySVM; return 0; }
The above code uses "myImageLabels.txt", "myImageList.txt", and "myImagetest.txt" as training image labels, training image paths, and test image paths, respectively.
The format of the stored content is as follows:
Label=1, 2, 3, 4, and 5 represent the five categories of airplanes, butterfly, camera, scissors, and sunflower, respectively. The test effect is as follows, and the effect of changing to RBF is very poor:
Predict an image each time you press the space bar.