用java实现均值偏移(Mean-Shift)算法

我们首先了解一下什么是均值偏移(Mean-Shift)算法,如下:

均值偏移(mean shift,也叫均值漂移或均值平移)这个概念最早是由Fukunaga等人于1975年在《The estimation of the gradient of a density function with application in pattern recognitioin》这篇关于概率密度梯度函数的估计中提出来的,其最初含义正如其名,就是偏移的均值向量。 它是一种无参估计算法,沿着概率梯度的上升方向寻找分布的峰值。

然而在以后的很长一段时间内mean shift并没有引起人们的注意,直到20年以后,也就是1995年,另外一篇关于Mean shift的重要文献《Mean shift analysis and application》才发表。在这篇重要的文献中,Yizong cheng对基本Mean shift算法在以下两个方面做了推广,首先定义了一族核函数,使得随着样本与被偏移点的距离不同,其偏移量对均值偏移向量的贡献也不同,其次设定了一个权重系数,使得不同的样本点重要性不一样,这大大扩大了Mean shift的适用范围。直到1998年Bradski将MeanShift算法用于人脸的跟踪才使得此算法的优势在目标跟踪领域体现出来。

MeanShift算法是一种无参概率密度估计法,算法利用像素特征点概率密度函数的梯度推导而得, MeanShift算法通过迭代运算收敛于概率密度函数的局部最大值,实现目标定位和跟踪,也能对可变形状目标实时跟踪,对目标的变形,旋转等运动也有较强的鲁棒性。MeanShift算法是一种自动迭代跟踪算法,由 MeanShift补偿向量不断沿着密度函数的梯度方向移动。在一定条件下,MeanShift算法能收敛到局部最优点,从而实现对运动体准确地定位。

均值平移算法是一种非参数的统计迭代算法。

该算法可以使用在运动跟踪方面上。

我们现在开始用java实现,如下:

首先是计算欧式距离

//计算欧式距离
	private static double countDistance(double[] p1,double[] p2) {
		
		double sum=0;
		
		for(int i=0;i

然后是随机抽取向量

//随机抽取向量
	private static double[] randomVector(DenseMatrix64F src) {
		
		double[] rs = new double[src.numCols];
		
		Random r=new Random();
		
		int inx = r.nextInt(src.numRows);
		
		for(int i=0;i

然后是筛选指定向量指定半径内的所有向量

private static DenseMatrix64F findDatasInCircle(DenseMatrix64F src,double[] p,double r) {
		
		DenseMatrix64F rs = new DenseMatrix64F(0,src.numCols);
		
		for(int i=0;i

然后是计算新的向量叠加

private static double[] countVectorSuperposition(DenseMatrix64F src) {
		
		double[] rs = new double[src.numCols];
		
		for(int i=0;i

然后是主方法

public static double[] meanShift(DenseMatrix64F dataSet,double r) {
		
		
		//随机选取向量
		double[] rs = randomVector(dataSet);
		
		double diff = Double.MAX_VALUE;
		
		double change = Double.MAX_VALUE;
	
		
		//开始迭代
		while(diff > 0 && change != 0) {
			
			//筛选半径内所有向量
			DenseMatrix64F subVectors = findDatasInCircle(dataSet,rs,r);
			
			//计算向量叠加
			double[] sumVectors  = countVectorSuperposition(subVectors);
			
			
			//计算目标向量
			double vCount = countDistance(rs,sumVectors);
			
			change = vCount-diff;
			
			diff = vCount;
			
			System.out.println("diff :"+diff);
			
			//更新圆心向量
			rs = sumVectors;
		}
		
		
		
		return rs;
		

	}

ok现在开始测试

List list = new ArrayList();
        try{
            BufferedReader br = new BufferedReader(new FileReader("D:\\test.txt"));
            String s = null;
            while((s = br.readLine())!=null){
            	list.add(s);
            }
            br.close();    
        }catch(Exception e){
            e.printStackTrace();
        }
        
        DenseMatrix64F dataMatIn = new DenseMatrix64F(list.size(),2);

        for(int i=0;i

测试结果如下:

用java实现均值偏移(Mean-Shift)算法_第1张图片

向量最终不再变化

你可能感兴趣的:(java,AI,运动检测,算法,机器学习)