opencv SVM 训练行人检测器注意事项
2015-03-03 11:42
323 查看
<span style="color: rgb(255, 0, 0); font-size: 18px; font-weight: bold; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">事项1:支持向量一个的原因?</span>
如下的解答:用opencv2.49的我是这么理解的:对于线性SVM,在opencv\sources\modules\ml\src\svm.cpp这个源码的optimize_linear_svm()函数中opencv的作者已经解释很很清楚了,“we optimize only linear SVM: compress all the
support vectors into one.”,support_vector*alpha的工作他已经做了,直接拿生成的<support_vector>+<rho>应该就可以作为分类器拿去用了,<support_vector>代表-w,<rho>代表b,而线性分类器不就是wx+b=0吗?(只有线性分类器做了此项优化,其他非线性SVM请按照原来的步骤操作)
事项2:一般训练应该包括以下几步:
1、提取正负样本hog特征
2、投入svm分类器训练,得到model
3、由model生成检测子
4、利用检测子检测负样本,得到hardexample
5、提取hardexample的hog特征并结合第一步中的特征一起投入训练,得到最终检测子。
经过以上步骤,检测效果会有大的提升。
事项3:如何得到W,并将其转化为opencv中的检测器
假设线性分类器是wx+b=0,这里得到的<support_vector>*<alpha>相当于-w,得到的rho相当于b,所以这里相当于将<support_vector>*<alpha>得到的结果<rec>每一项都取负,得到w,与b组成新的Mat后代入到detectMultiScale()中进行识别。
<span style="font-size:14px;">//继承自CvSVM的类,因为生成setSVMDetector()中用到的检测子参数时,需要用到训练好的SVM的decision_func参数, //但通过查看CvSVM源码可知decision_func参数是protected类型变量,无法直接访问到,只能继承之后通过函数访问 class MySVM : public CvSVM { public: //获得SVM的决策函数中的alpha数组 double * get_alpha_vector() { return this->decision_func->alpha; } int get_alpha_count() { return this->sv_total; } //获得SVM的决策函数中的rho参数,即偏移量 float get_rho() { return this->decision_func->rho; } int get_sv_dim() { return this->var_all; } int get_sv_count() { return this->decision_func->sv_count; } float** get_sv() { return this->sv; } }; </span>
将训练好的SVM转化为检测算子
<span style="font-size:12px;">vector<float> getSVMDetector(MySVM svm) { /************************************************************************************************* 线性SVM训练完成后得到的XML文件里面,有一个数组,叫做support vector,还有一个数组,叫做alpha,有一个浮点数,叫做rho; 将alpha矩阵同support vector相乘,注意,alpha*supportVector,将得到一个列向量。之后,再该列向量的最后添加一个元素rho。 如此,变得到了一个分类器,利用该分类器,直接替换opencv中行人检测默认的那个分类器(cv::HOGDescriptor::setSVMDetector()), 就可以利用你的训练样本训练出来的分类器进行行人检测了。 ***************************************************************************************************/ int DescriptorDim = svm.get_var_count();//特征向量的维数,即HOG描述子的维数 int supportVectorNum = svm.get_support_vector_count();//支持向量的个数 cout<<"支持向量个数:"<<supportVectorNum<<endl; Mat alphaMat = Mat::zeros(1, supportVectorNum, CV_32FC1);//alpha向量,长度等于支持向量个数 Mat supportVectorMat = Mat::zeros(supportVectorNum, DescriptorDim, CV_32FC1);//支持向量矩阵 Mat resultMat = Mat::zeros(1, DescriptorDim, CV_32FC1);//alpha向量乘以支持向量矩阵的结果 //将支持向量的数据复制到supportVectorMat矩阵中 for(int i=0; i<supportVectorNum; i++) { const float * pSVData = svm.get_support_vector(i);//返回第i个支持向量的数据指针 for(int j=0; j<DescriptorDim; j++) { //cout<<pData[j]<<" "; supportVectorMat.at<float>(i,j) = pSVData[j]; } } //将alpha向量的数据复制到alphaMat中 double * pAlphaData = svm.get_alpha_vector();//返回SVM的决策函数中的alpha向量 for(int i=0; i<supportVectorNum; i++) { alphaMat.at<float>(0,i) = pAlphaData[i]; } //计算-(alphaMat * supportVectorMat),结果放到resultMat中 //gemm(alphaMat, supportVectorMat, -1, 0, 1, resultMat);//不知道为什么加负号? resultMat = -1 * alphaMat * supportVectorMat; //得到最终的setSVMDetector(const vector<float>& detector)参数中可用的检测子 vector<float> myDetector; //将resultMat中的数据复制到数组myDetector中 for(int i=0; i<DescriptorDim; i++) { myDetector.push_back(resultMat.at<float>(0,i)); } //最后添加偏移量rho,得到检测子 myDetector.push_back(svm.get_rho()); cout<<"检测子维数:"<<myDetector.size()<<endl; //保存检测子参数到文件 // ofstream fout("HOGDetectorForOpenCV_2400PosINRIA_12000Neg.txt"); // for(int i=0; i<myDetector.size(); i++) // { // fout<<myDetector[i]<<endl; // } return myDetector; }</span>
调用检测算子,并转化为opencv格式,进行多尺度检测
vector<float> myDetector = getSVMDetector(svm); //设置HOGDescriptor的检测子 HOGDescriptor myHOG; myHOG.setSVMDetector(myDetector); //myHOG.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
<span style="font-size: 18px;"><strong> </strong></span><span style="font-size:14px;">Mat src = imread("5.png"); vector<Rect> found, found_filtered;//矩形框数组 cout<<"进行多尺度HOG人体检测"<<endl; myHOG.detectMultiScale(src, found, 0, Size(8,8), Size(32,32), 1.05, 2);//对图片进行多尺度行人检测 cout<<"找到的矩形框个数:"<<found.size()<<endl; //画矩形框,因为hog检测出的矩形框比实际人体框要稍微大些,所以这里需要做一些调整 for(int i=0; i<found.size(); i++) { Rect r = found[i]; r.x += cvRound(r.width*0.1); r.width = cvRound(r.width*0.8); r.y += cvRound(r.height*0.07); r.height = cvRound(r.height*0.8); rectangle(src, r.tl(), r.br(), Scalar(0,255,0), 3); } namedWindow("src",0); imshow("src",src); waitKey(); </span>
相关文章推荐
- opencv SVM 训练行人检测器注意事项
- opencv SVM 训练行人检测器注意事项
- Tesseract训练注意事项
- opencv训练注意事项
- BatchNorm层训练和测试的注意事项
- (转)采用opencv_cascadetrain进行训练的步骤及注意事项
- 神经网络细节与训练注意事项
- 采用opencv_cascadetrain进行训练的步骤及注意事项
- Tensorflow利用GPU训练注意事项
- OpenCV的HOG+SVM训练程序注意事项
- 乒乓球训练注意事项
- ITF跆拳道训练注意事项
- 深度学习第五课-训练注意事项与框架使用
- ITF跆拳道训练注意事项
- OpenCV的HOG+SVM训练程序注意事项
- 狗狗训练11招 及 训犬注意事项
- 七月算法深度学习笔记5--CNN训练注意事项与框架使用
- 分类器训练——haar分类器的使用方法及注意事项
- noip注意事项,训练时经验与技巧
- 入门训练:写程序应注意的事项