SVM+HOG对图像进行多分类(OpenCV实现)

前几个月写了篇关于MATLAB实现SVM+HOG对图像进行多分类,链接:http://blog.csdn.net/cuixing001/article/details/70908064,先开始是用opencv实现的,可是识别效果很差,以为我写错代码了,后来纠结了好久好久,才发现是核函数选择有很大问题!这次改为线性核,效果在这些图片中(所用的图像数据集为:链接: https://pan.baidu.com/s/1i5OhC7z 密码: utn7)表现不错。

OpenCV代码如下:

//SVM多分类训练测试
#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) //是否需要训练
	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

	// 预测
	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;
}


上面代码用到"myImageLabels.txt", "myImageList.txt","myImagetest.txt"分别为训练图像标记,训练图像路径,测试图像路径。

里面保存内容格式如下:


label=1,2,3,4,5分别表示airplanes,butterfly,camera,scissors,sunflower这五类,测试效果如下,改成RBF效果就很差了:

每按下一次空格键就预测一张图片。


猜你喜欢

转载自blog.csdn.net/cuixing001/article/details/77001977