hog是一个基于梯度的直方图提取算法,最初用于行人检测,效果拔群。之后DPM的出现将行人(目标)检测的准确率产生了巨大的提升。HOG特征提取在opencv2.2+版本里面已经实现。我的另外一篇博客推荐了几个很好的关于理解hog特征的博客。
以下在推荐两个:
http://blog.csdn.net/raocong2010/archive/2011/03/11/6239431.aspx
本文中介绍了opencv中HOGDescriptor构造函数各个参数的含义。
从另外我从http://blog.csdn.net/yangtrees/article/details/7471222 上找来了一段代码。即是使用HOG + SVM 进行图像分类。虽然没有太多注释,但逻辑还是很清楚的。我根据他的代码,把程序中的一些功能函数化了。具体有以下三个文件:
1. hog_svm.h (声明了一些函数)
2. hog_svm.cpp(函数具体实现, 主要内容都在这里)
3. main.cpp(测试程序)
注:在main函数中,trainNames.txt中保存着训练集图像的地址,trainLabels.txt中保存对应的训练集图像标签
testNames.txt中保存测试集图像的地址。
1.hog_svm.h
#ifndef HOG_SVM_
#define HOG_SVM_
#include
#include
#include
using namespace cv;
using namespace std;
namespace hog_svm {
vector extractHOGFeature(const Mat & src);
/*
imgList 为包含所有训练图像路径的文本文件
labelList是与它对应的图像的标签
labelList中图像的标签由整型数字表示
返回值为指向CvSVM的指针 (为啥不直接返回CvSVM对象,因为函数返回对象时需要调用复制构造函数,但CvSVM的复制构造函数是private的)
*/
CvSVM* getHOGSVM(string imgList, string labelList);
/*
这函数不用了,别看了
imgPath 中存储所有图像的路径
imgCatg中存储与图像所对应的标签
dataMat是提取特征后的矩阵, resMat为图像的标签,两者都是每行对应一张图想
void extractHOGFeature(const vector & imgPath, const vector & imgCatg,
Mat & dataMat, Mat & resMat);
*/
//返回值为float类型
float svmPredict(CvSVM * hogSvm, const Mat & image);
}
#endif
#include "hog_svm.h"
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
const int hog_svm_ImageHeight = 256;
const int hog_svm_ImageWidth = 256;
vector hog_svm::extractHOGFeature(const Mat & src)
{
Mat tempImg;
resize(src, tempImg, Size(hog_svm_ImageWidth, hog_svm_ImageHeight));
HOGDescriptor *hog = new HOGDescriptor(Size(hog_svm_ImageWidth, hog_svm_ImageHeight),
Size(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
//存储特征计算结果
vector descriptors;
hog->compute(tempImg, descriptors, Size(1, 1), Size(0, 0));
return descriptors;
}
//这个接口设计的不好
/*
void hog_svm::extractHOGFeature(const vector & imgPath, const vector & imgCatg,
Mat & dataMat, Mat & resMat)
{
Mat src, tempImg;
resMat = Mat::zeros(imgPath.size(), 1, CV_32FC1);
for (int i = 0; i < imgPath.size(); i++)
{
src = imread(imgPath[i], CV_LOAD_IMAGE_COLOR);
resize(src, tempImg, Size(hog_svm_ImageWidth, hog_svm_ImageHeight));
HOGDescriptor *hog = new HOGDescriptor(Size(hog_svm_ImageWidth, hog_svm_ImageHeight),
Size(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
//存储特征计算结果
vector descriptors;
hog->compute(tempImg, descriptors, Size(1, 1), Size(0, 0));
if (0 == i)
dataMat = Mat::zeros(imgPath.size(), descriptors.size(), CV_32FC1);
//存储计算后的特征值和标签
for (int inn = 0; inn < descriptors.size(); inn++)
dataMat.at(i, inn) = descriptors[inn];
resMat.at(i, 0) = imgCatg[i];
}//for int i
}
*/
CvSVM* hog_svm::getHOGSVM(string imgList, string labelList)
{
///1.将图像路径和标签存储到向量中/
ifstream imgListStream(imgList);
ifstream labelListStream(labelList);
vector imgPath;
vector imgCatg;
string imgItemPath;
int imgItemCatg;
while (imgListStream >> imgItemPath)
{
labelListStream >> imgItemCatg;
imgPath.push_back(imgItemPath);
imgCatg.push_back(imgItemCatg);
}
imgListStream.close();
labelListStream.close();
///2.对图像resize后,提取图像的HOG特征/
Mat src, tempImg;
Mat dataMat, resMat = Mat::zeros(imgPath.size(), 1, CV_32FC1);
for (int i = 0; i < imgPath.size(); i++)
{
src = imread(imgPath[i], CV_LOAD_IMAGE_COLOR);
//存储特征计算结果
vector descriptors = extractHOGFeature(src);
if (0 == i)
dataMat = Mat::zeros(imgPath.size(), descriptors.size(), CV_32FC1);
//存储计算后的特征值和标签
for (int inn = 0; inn < descriptors.size(); inn++)
dataMat.at(i, inn) = descriptors[inn];
resMat.at(i, 0) = imgCatg[i];
}//for int i
///3,SVM参数设置//
/*
SVM种类:CvSVM:C_SVC 如果数据线性不可分的话就用这个
Kernel种类:LINEAR (无核函数)
*/
CvSVM *hogSvm = new CvSVM();
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 500, 1e-6);
int featureLength = dataMat.cols;
///4.训练SVM///
hogSvm->train(dataMat, resMat, Mat(), Mat(), params);
return hogSvm;
}
float hog_svm::svmPredict(CvSVM * hogSvm, const Mat & image)
{
vector descriptors = extractHOGFeature(image);
int featureLength = descriptors.size();
Mat predictMat = Mat::zeros(1, featureLength, CV_32FC1);
for (int i = 0; i < featureLength; i++)
predictMat.at(0, i) = descriptors[i];
return (hogSvm->predict(predictMat));
}
3.main.c
#include
#include
#include
#include "hog_svm.h"
#include
#include
using namespace std;
using namespace cv;
using namespace hog_svm;
int main()
{
CvSVM* svm = getHOGSVM("trainNames.txt", "trainLabels.txt");
ifstream fin("testNames.txt");
ofstream fout("predictRes.txt");
string str;
int kase = 0;
while (fin >> str)
{
Mat image = imread(str, CV_LOAD_IMAGE_COLOR);
float res = svmPredict(svm, image);
fout << res << endl;
cout << ++kase << " 个测试结束" << endl;
}
system("pause");
return 0;
}