opencv中应用HOG特征训练SVM多分类器的一般框架
2016-09-28 19:08
661 查看
1.HOG特征提取
opencv里关于HOG特征的提取是通过函数HOGDescriptor()来完成的,主要有下面4个构造函数:CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8), cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1), histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true), nlevels(HOGDescriptor::DEFAULT_NLEVELS) {}
CV_WRAP HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1, int _histogramNormType=HOGDescriptor::L2Hys, double _L2HysThreshold=0.2, bool _gammaCorrection=false, int _nlevels=HOGDescriptor::DEFAULT_NLEVELS) : winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize), nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma), histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold), gammaCorrection(_gammaCorrection), nlevels(_nlevels) {}
CV_WRAP HOGDescriptor(const String& filename) { load(filename); }
HOGDescriptor(const HOGDescriptor& d) { d.copyTo(*this); }
实际应用过程中主要是第二个,其中有几个关键的参数:
winSize: 窗口的大小
blockSize:块的大小
blockStride:块滑动的增量
cellSize:元组的大小
nbins:梯度方向的数组,例如nBins=9时,在一个胞元内统计9个方向的梯度直方图,每个方向为180/9=20度。
实际应用中关键是弄清楚HOG特征的维数的计算,例如出入一幅64*64的图像,输出的结果就是一个很长的hog特征向量,向量的维度与上面的几个参数有关。例如按照第一个构造函数中默认的初始序列,可以计算得出hog的特征向量维度是:9*(16/8)*(16/8)*[(64-16)/8+1]*[(128-16)/8+1]=3780
size_t HOGDescriptor::getDescriptorSize() const { CV_Assert(blockSize.width % cellSize.width == 0 && blockSize.height % cellSize.height == 0); CV_Assert((winSize.width - blockSize.width) % blockStride.width == 0 && (winSize.height - blockSize.height) % blockStride.height == 0 ); return (size_t)nbins* (blockSize.width/cellSize.width)* (blockSize.height/cellSize.height)* ((winSize.width - blockSize.width)/blockStride.width + 1)* ((winSize.height - blockSize.height)/blockStride.height + 1); }
详情关于HOG的理解可见:
http://blog.csdn.net/zouxy09/article/details/7929348/
http://blog.csdn.net/raodotcong/article/details/6239431
2.提取HOG特征,进行SVM训练分类的流程
首先得有训练样本集和测试样本集,通常情况下,样本集中的样本的信息都是保存在文本文件中方便读取。通常情况下,如果样本的数量比较多,需要用bat批处理程序来提取文件名信息:dir /b/s/p/w *.jpg>train_list.txt 新建txt文档,将其保存为.bat文件,用Notepad保存比较方便。
考虑到样本集一般比较多,数量也未知,一般需要用到STL中的vector
opencv中SVM的使用可以参考官方文档:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html
源码:
#include "cv.h" #include "highgui.h" #include <ml.h> #include <iostream> #include <fstream> #include <string> #include <vector> using namespace cv; using namespace std; int main() { int ImgWidht = 64; int ImgHeight = 64; vector<string> img_path; vector<int> img_catg; int nLine = 0; string buf; ifstream svm_data( "tran.txt" ); unsigned long n; while( svm_data ) { if( getline( svm_data, buf ) ) { //三种类别,前10个,中间10个,最后10个 if( nLine <10 ) { img_catg.push_back(0);//图像类别 img_path.push_back( buf );//图像路径 } else if(nLine <20 ) { img_catg.push_back(1); img_path.push_back( buf );//图像路径 } else { img_catg.push_back(2); img_path.push_back( buf );//图像路径 } nLine ++; } } svm_data.close();//关闭文件 Mat data_mat, res_mat; int nImgNum = nLine; //读入样本数量 //样本矩阵,nImgNum:行数代表样本的数量,每一行就是由一张图片计算得到HOG的特征向量, data_mat = Mat::zeros( nImgNum, 1764, CV_32FC1 ); //HOG特征的位数: 9*(16/8)*(16/8)*[(64-16)/8+1]*[(64-16)/8+1]=1764 //类型矩阵,存储每个样本的类型标志 res_mat = Mat::zeros( nImgNum, 1, CV_32FC1 ); Mat src; Mat trainImg = Mat::zeros(ImgHeight, ImgWidht, CV_8UC3);//需要分析的图片 for( string::size_type i = 0; i != img_path.size(); i++ ) { src = imread(img_path[i].c_str(), 1); cout<<" processing "<<img_path[i].c_str()<<endl; resize(src, trainImg, cv::Size(ImgWidht,ImgHeight), 0, 0, INTER_CUBIC); HOGDescriptor *hog=new HOGDescriptor(cvSize(ImgWidht,ImgHeight),cvSize(16,16),cvSize(8,8),cvSize(8,8), 9); //构造HOG,具体意思见参考文章1,2 vector<float>descriptors;//结果数组 hog->compute(trainImg, descriptors, Size(1,1), Size(0,0)); //调用计算函数开始计算 if (i==0) { data_mat = Mat::zeros( nImgNum, descriptors.size(), CV_32FC1 ); //根据输入图片大小进行分配空间 } cout<<"HOG dims: "<<descriptors.size()<<endl; n=0; for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++) { data_mat.at<float>(i,n) = *iter; n++; } //cout<<SVMtrainMat->rows<<endl; res_mat.at<float>(i, 0) = img_catg[i]; cout<<" end processing "<<img_path[i].c_str()<<" "<<img_catg[i]<<endl; } CvSVM svm ; CvSVMParams param; CvTermCriteria criteria; criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON ); param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria ); /* SVM种类:CvSVM::C_SVC Kernel的种类:CvSVM::RBF degree:10.0(此次不使用) gamma:8.0 coef0:1.0(此次不使用) C:10.0 nu:0.5(此次不使用) p:0.1(此次不使用) 然后对训练数据正规化处理,并放在CvMat型的数组里。 */ //☆☆☆☆☆☆☆☆☆(5)SVM学习☆☆☆☆☆☆☆☆☆☆☆☆ svm.train( data_mat, res_mat, Mat(), Mat(), param ); //☆☆利用训练数据和确定的学习参数,进行SVM学习☆☆☆☆ svm.save( "SVM_DATA.xml" ); //检测样本 vector<string> img_tst_path; ifstream img_tst( "test.txt" ); while( img_tst ) { if( getline( img_tst, buf ) ) { img_tst_path.push_back( buf ); } } img_tst.close(); Mat test; char line[512]; ofstream predict_txt( "SVM_PREDICT.txt" ); for( string::size_type j = 0; j != img_tst_path.size(); j++ ) { test = imread( img_tst_path[j].c_str(), 1);//读入图像 resize(test, trainImg, cv::Size(ImgWidht,ImgHeight), 0, 0, INTER_CUBIC);//要搞成同样的大小才可以检测到 HOGDescriptor *hog=new HOGDescriptor(cvSize(ImgWidht,ImgHeight),cvSize(16,16),cvSize(8,8),cvSize(8,8),9); //窗口大小,块大小,块滑动增量,cell的大小,bins的个数 vector<float>descriptors;//结果数组 hog->compute(trainImg, descriptors,Size(1,1), Size(0,0)); //调用计算函数开始计算 cout<<"The Detection Result:"<<endl; cout<<"HOG dims: "<<descriptors.size()<<endl; Mat SVMtrainMat = Mat::zeros(1,descriptors.size(),CV_32FC1); n=0; for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++) { SVMtrainMat.at<float>(0,n) = *iter; n++; } int ret = svm.predict(SVMtrainMat); std::sprintf( line, "%s %d\r\n", img_tst_path[j].c_str(), ret ); printf("%s %d\r\n", img_tst_path[j].c_str(), ret);//输出预测的结果,ret的值就代表类别 //getchar(); predict_txt<<line; } predict_txt.close(); system("PAUSE"); return 0; }
结果:
相关文章推荐
- OpenCV3.2.0中使用HOG特征训练SVM分类器时重点注意事项
- 用opencv的traincascade.exe训练行人的HAAR、LBP和HOG特征的xml文件,并对分类器进行加载和检测
- SVM+HOG特征训练分类器
- 利用opencv训练基于Haar特征、LBP特征、Hog特征的分类器cascade.xml
- (OpenCV3.2.0)基于HOG特征的SVM训练与测试实例
- Adaboost应用系列之三:Opencv2.4.X中利用Adaboost训练HOG特征产生xml分类器
- HOG特征的SVM分类器训练代码
- Adaboost应用系列之三:Opencv2.4.X中利用Adaboost训练HOG特征产生xml分类器
- HOG特征的SVM分类器训练代码
- 利用OpenCV中默认的SVM参数进行HOG行人检测,默认参数是根据Dalal的方法训练的。
- HAAR、LBP和HOG特征训练分类器
- OpenCV 实践程序10——利用 haar特征和adaboost方法训练分类器
- HOG特征+SVM训练过程
- 吐血总结:HOG特征+SVM训练过程
- HOG+SVM 自己制作训练样本+训练分类器
- Opencv+SVM对HOG进行训练
- 用opencv自带的traincascade.exe训练给予haar特征和LBP特征的分类器
- 自己训练SVM分类器进行HOG行人检测
- opencv训练分类器(HAAR,LBP等特征)
- 自己训练SVM分类器进行HOG行人检测