首页 > 代码库 > 对opencv MeanShift 融合矩形框的改进
对opencv MeanShift 融合矩形框的改进
OPENCV 中的代码改进,当然要根据自己的实际情况来,OPENCV 中行人检测有两种矩形框的融合算法,这里只对meanshift 方法做改进
如果有更好的方法,希望可以跟我讲下。
对于去除重合部分,我也写了改进,看懂了可以加到自己程序中。
为什么要做局部MeanShift?
图1.全局MeanShift
如图所示:两幅图像距离较近且有多个矩形框,全局MeanShift融合后可能会造成这种结果
而如果用局部融合就能避免这种情况。
/*----------------------------------分数判定:begin--------------------------------------------------*/ //////////////将感兴趣区域归一化后计算HOG特征--begin//////////////////// cvSetImageROI(imageOrigin,r); IplImage *test=cvCreateImage(cvGetSize(imageOrigin),8,3); cvCopyImage(imageOrigin,test); cvResetImageROI(imageOrigin); IplImage* testTempImg=cvCreateImage(cvSize(40,40),8,3); cvZero(testTempImg); cvResize(test,testTempImg); hog->compute(testTempImg, descriptors,Size(1,1), Size(0,0)); //Hog特征计算 Mat another(descriptors); descriptors.clear(); ////////////将感兴趣区域归一化后计算HOG特征--end/////////////// double ret = 0; ret = ssvm.get_calc_liner(vec_count,var_count,a,another,results,alpha,0)-rho; //计算SVM分数 //////////////////////////// cvReleaseImage(&test); cvReleaseImage(&testTempImg); //////////////////////////// if(ret <0) { continue; //去掉SVM 分值小于0的图像 } rc_.push_back(rcc); weights.push_back(ret); double rate = max(rcc.width*1.0/40,rcc.height*1.0/40); //选取长宽最大值,作为尺度,考虑还不够周到,这里改变,Meanshift 全部都要改 //这里还可以改进 foundScales.push_back(rate); /*----------------------------------分数判定:end--------------------------------------------------*/ //////////上述应该是一个循环,加入多个点////////////// /////////////////////////融合过程-begin//////////////////////////// //vector<Rect> rc_;//矩形框 // vector<double> weights;//权重,score // vector<double> foundScales;//放缩尺度 groupRectangles_meanshift1(rc_, weights, foundScales, 0.3, Size(40,40)); //框出来的矩形框进行融合 //groupRectangles_meanshift1该函数在最后定义// ///////////////////////融合过程-end/////////////////////////// //////////////////重合去重第一步:计算融合后的分值////////////////// for( i = 0; i < rc_.size(); i++ ) { //加入矩形框 Rect r = rc_[i]; found_filtered.push_back(r); } vector<float> found_score(found_filtered.size()); //矩形框的分数 for( i = 0; i < found_filtered.size(); i++ ) { Rect r = found_filtered[i]; ////////////////////////////////// cvSetImageROI(imageOrigin,r); IplImage *test=cvCreateImage(cvGetSize(imageOrigin),8,3); cvCopyImage(imageOrigin,test); cvResetImageROI(imageOrigin); IplImage* testTempImg=cvCreateImage(cvSize(40,40),8,3); cvZero(testTempImg); cvResize(test,testTempImg); hog->compute(testTempImg, descriptors,Size(1,1), Size(0,0)); //Hog特征计算 Mat another(descriptors); descriptors.clear(); double ret = 0; ret= ssvm.get_calc_liner(vec_count,var_count,a,another,results,alpha,0)-rho; cvReleaseImage(&test); cvReleaseImage(&testTempImg); found_score[i]=ret; //////////////////////////// } ////////重合去重第二步:矩形框内的部分,取分值最大的///// //////////////////////found_filtered为融合后的矩形框////////////////////////// for( i = 0; i < found_filtered.size(); i++ ) { //进行了重合去除,选取附近分值最大矩形框 Rect r = found_filtered[i]; for( j = 0; j < rc_.size(); j++ ) if( j != i && (r & found_filtered[j]).area() == r.area()) {//这里是将重叠的部分,分值小的矩形框的权重设为-1,为了取最大值 if(found_score[i]>found_score[j]) { found_score[j]=-1; break; } else { found_score[i]=-1; break; } } } ////////重合去重第三步:重叠部分,取分值最大的///// ////////////////////////////////////////////////////////////////// for( i = 0; i < found_filtered.size(); i++ ) { //进行了重合去除 Rect r = found_filtered[i]; for( j = 0; j < rc_.size(); j++ ) //判定重合是否大于相较面积的70%(这个比例有待测试) //判定都为上一步过滤后的结果,可能存在部分相较,但不包含的情况 if( j != i && (r & found_filtered[j]).area() >= r.area()*0.7 &&found_score[j]!=-1&&found_score[i]!=-1) {//这里是将重叠的部分,分值小的矩形框的权重设为-1 if(found_score[i]>found_score[j]) { found_score[j]=-1; break; } else { found_score[i]=-1; break; } } } for(int i=0;i<found_filtered.size();i++) { if (found_score[i]==-1)//将分值等于-1的过滤掉 { continue; } Rect r = found_filtered[i]; r.x -= cvRound(r.width*0.05); r.width = cvRound(r.width*1.05); r.y -= cvRound(r.height*0.05); r.height = cvRound(r.height*1.05); rectangle(img_dst, r.tl(), r.br(), cv::Scalar(0,255,0), 2); //在图像上画矩形框 } /*-----------------------MeanShift做局部的(源程序是对全局)------------------------*/ //meanshift 融合 class MeanshiftGrouping { public: // MeanshiftGrouping msGrouping(smothing, hits,rectList, hitWeights, 1e-5, 100);//得到 /////////////////////////////////////////////////////////////////////// // msGrouping.getModes(resultHits, resultWeights, 1); ////////////////////////////////////////////////////////////////////// MeanshiftGrouping(const Point3d& densKer, const vector<Point3d>& posV,const vector<Rect>&list, const vector<double>& wV, double eps, int maxIter = 20) { densityKernel = densKer; weightsV = wV; positionsV = posV; positionsCount = (int)posV.size(); meanshiftV.resize(positionsCount); distanceV.resize(positionsCount); iterMax = maxIter; modeEps = eps; for (unsigned i = 0; i<positionsV.size(); i++) { meanshiftV[i] = getNewValue(positionsV[i],list[i],list);//positionV 只有中点坐标没有长宽。 distanceV[i] = moveToMode(meanshiftV[i],list[i],list);//做最大为iterMax次循环//均值漂移后的值 meanshiftV[i] -= positionsV[i];//这一步后面没用到 } } void getModes(vector<Point3d>& modesV, vector<double>& resWeightsV, const double eps) { for (size_t i=0; i <distanceV.size(); i++) { bool is_found = false; for(size_t j=0; j<modesV.size(); j++) { if ( getDistance(distanceV[i], modesV[j]) < eps)//欧式距离小于阈值 { is_found=true; break; } } if (!is_found) { modesV.push_back(distanceV[i]);//添加距离较大的点,也就是说两个点距离较大,不是同一个矩形框 } } resWeightsV.resize(modesV.size()); for (size_t i=0; i<modesV.size(); i++) { resWeightsV[i] = getResultWeight(modesV[i]);//得到点的权值 } } protected: vector<Point3d> positionsV; vector<double> weightsV; Point3d densityKernel; int positionsCount; vector<Point3d> meanshiftV; vector<Point3d> distanceV; int iterMax; double modeEps; Point3d getNewValue(const Point3d& inPt ,const Rect inR ,const vector<Rect>list) const {//inPt 输入三维坐标 、inR 为输入的矩形 list为所有矩形 Point3d resPoint(.0); Point3d ratPoint(.0); int value=http://www.mamicode.com/20;//只考虑矩形框四个角差值小于20的点,这个可以自己设定>
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。