首页 > 代码库 > 对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的点,这个可以自己设定>