SVM+HOG for multi-classification of images (OpenCV implementation)

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.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325632071&siteId=291194637