hog特征是一种进行物体检测的特征,常常被用来进行行人检测和物体分类。本文是利用opencv中的hog特征提取算法结合svm分类器进行简单的物体分类。
代码
#include <opencv2/core/core.hpp>
#include <opencv2/ml/ml.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <string>
#include <stdio.h>
#include <iostream>
using namespace cv;
using namespace std;
using namespace cv;
using namespace std;
int main()
{
string classnum[5];
classnum[0] = "./elephant/image_";
classnum[1] = "./butterfly/image_";
classnum[2] = "./cup/image_";
classnum[3] = "./camera/image_";
classnum[4] = "./crocodile_head/image_";
vector<Mat> imageall;
Mat data;
const int trainnum = 45;
const int testnum = 5;
const int desnum = 30;
const int k = 200;
HOGDescriptor hog(Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);//定义hog描述子
for (int i = 0; i < 5; i++)
for (int j = 1; j <= trainnum; j++)
{
string num;
char numm[10];
sprintf(numm, "%04d.jpg", j);
num = numm;
string name = classnum[i] + num;
cout << name << endl;
Mat image1 = imread(name, 0);
resize(image1, image1, Size(128, 128));
cout <<"image:"<< image1.size() << endl;
imshow("1", image1);
vector<KeyPoint> keypoints1, keypoints2;
//SurfFeatureDetector detector(desnum);
//detector.detect(image1, keypoints1);
//SiftDescriptorExtractor Desc;
vector<float> descriptors;
float fea[8100];
//float fea[3459];
hog.compute(image1, descriptors, Size(4, 4));//提取hog特征
int dim = descriptors.size();
cout << dim << endl;
for (int i = 0; i < dim; i++)
fea[i] = descriptors[i];
data.push_back(Mat(1, dim, CV_32FC1, fea));
}
cout << data.size() << endl;
Mat fealabel;
for (int i = 0; i < trainnum*5; i++)
{
fealabel.push_back(Mat(1, 1, CV_32FC1, i / trainnum));
}
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 20000, 1e-6);
// 对SVM进行训练
CvSVM SVM;
SVM.train(data, fealabel, Mat(), Mat(), params);
for (int i = 0; i < 5 * trainnum; i++)
{
// cout<<feature.row(i)<<endl;
cout << i / trainnum << " " << SVM.predict(data.row(i)) << endl;
}
Mat test;
//测试过程
for (int i = 0; i < 5; i++)
for (int j =50-testnum+1; j <= 50; j++)
{
string num;
char numm[10];
sprintf(numm, "%04d.jpg", j);
num = numm;
string name = classnum[i] + num;
cout << name << endl;
Mat image1 = imread(name, 0);
resize(image1, image1, Size(128, 128));
cout << "image:" << image1.size() << endl;
imshow("1", image1);
vector<KeyPoint> keypoints1, keypoints2;
SurfFeatureDetector detector(desnum);
detector.detect(image1, keypoints1);
SiftDescriptorExtractor Desc;
vector<float> descriptors;
float fea[8100];
hog.compute(image1, descriptors, Size(4, 4));
int dim = descriptors.size();
cout << dim << endl;
for (int i = 0; i < dim; i++)
fea[i] = descriptors[i];
test.push_back(Mat(1, dim, CV_32FC1, fea));
}
int count = 0;
for (int i = 0; i < 5 * testnum; i++)
{
// cout<<feature.row(i)<<endl;
int a = i / testnum;
int b = SVM.predict(test.row(i));
if (a == b)
count++;
cout << a << " " << b << endl;
}
cout << count*1.0 / (5 * testnum) << endl;
waitKey();
}
注意hog特征在使用svm训练时一定要用linear的模型,我理解是用其他的模型容易产生过拟合。opencv svm参数是这样设置的:
params.kernel_type = CvSVM::LINEAR;
还有训练之前注意吧图片都resize成一样大小~