Mean Shift,我们 翻译为“均值飘移”。其在聚类,图像平滑。图像分割和跟踪方面得到了比较广泛的应用。由于本人目前研究跟踪方面的东西,故此主要介绍利用Mean Shift方法进行目标跟踪,从而对MeanShift有一个比较全面的介绍。
    (以下某些部分转载常峰学长的“Mean Shift概述”) Mean Shift 这个概念最早是由Fukunaga等人于1975年在一篇关于概率密度梯度函数的估计(The Estimation of the Gradient of a Density Function, with Applications in Pattern Recognition )中提出来的,其最初含义正如其名,就是偏移的均值向量,在这里Mean Shift是一个名词,它指代的是一个向量,但随着Mean Shift理论的发展,Mean Shift的含义也发生了变化,如果我们说Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束.
然而在以后的很长一段时间内Mean Shift并没有引起人们的注意,直到20年以后,也就是1995年,另外一篇关于Mean Shift的重要文献(Mean shift, mode seeking, and clustering )才发表.在这篇重要的文献中,Yizong Cheng对基本的Mean Shift算法在以下两个方面做了推广,首先Yizong Cheng定义了一族核函数,使得随着样本与被偏移点的距离不同,其偏移量对均值偏移向
量的贡献也不同,其次Yizong Cheng还设定了一个权重系数,使得不同的样本点重要性不一样,这大大扩大了Mean Shift的适用范围.另外Yizong Cheng指出了Mean Shift可能应用的领域,并给出了具体的例子。
values翻译
Comaniciu等人在还(Mean-shift Blob Tracking through Scale Space)中把非刚体的跟踪问题近似为一个Mean Shift最优化问题,使得跟踪可以实时的进行。目前,利用Mean Shift进行跟踪已经相当成熟。
目标跟踪不是一个新的问题,目前在计算机视觉领域内有不少人在研究。所谓跟踪,就是通过已知的图像帧中的目标位置到目标在下一帧中的位置。
下面主要以代码形式展现Mean Shift在跟踪中的应用。
void CObjectTracker::ObjeckTrackerHandlerByUser(IplImage *frame)//跟踪函数
      {
          m_cActiveObject = 0;
  if (m_sTrackingObjectTable[m_cActiveObject].Status)
          {
              if (!m_sTrackingObjectTable[m_cActiveObject].assignedAnObject)
              {
                    FindHistogram(frame,m_sTrackingObjectTable[m_cActiveObject].initHistogram);
                    m_sTrackingObjectTable[m_cActiveObject].assignedAnObject = true;
              }
              else
              {
                    FindNextLocation(frame);//利用mean shift 迭代出目标下一个位置点
            DrawObjectBox(frame);
              }
        }
}
void CObjectTracker::FindNextLocation(IplImage *frame)
{
int i, j, opti, optj;
SINT16 scale[3]={-3, 3, 0};
FLOAT32 dist, optdist;
SINT16 h, w, optX, optY;
/
/try no-scaling
FindNextFixScale(frame);//出目标的下一个大致范围
optdist=LastDist;
optX=m_sTrackingObjectTable[m_cActiveObject].X;
optY=m_sTrackingObjectTable[m_cActiveObject].Y;
//try one of the 9 possible scaling
i=rand()*2/RAND_MAX;
j=rand()*2/RAND_MAX;
h=m_sTrackingObjectTable[m_cActiveObject].H;
w=m_sTrackingObjectTable[m_cActiveObject].W;
if(h+scale[i]>10 && w+scale[j]>10 && h+scale[i]<m_nImageHeight/2 && w+scale[j]<m_nImageWidth/2)
{
  m_sTrackingObjectTable[m_cActiveObject].H=h+scale[i];
  m_sTrackingObjectTable[m_cActiveObject].W=w+scale[j];
  FindNextFixScale(frame);
  if( (dist=LastDist) < optdist ) //scaling is better
  {
    optdist=dist;
//    printf("Next%f->\n", dist);
  }
  else //no scaling is better
  {
    m_sTrackingObjectTable[m_cActiveObject].X=optX;
    m_sTrackingObjectTable[m_cActiveObject].Y=optY;
    m_sTrackingObjectTable[m_cActiveObject].H=h;
    m_sTrackingObjectTable[m_cActiveObject].W=w;
  }
};
TotalDist+=optdist; //the latest distance
// printf("\n");
}
这里仍然在跟踪的基础上讲解mean shift。首先还是把mean shift的原理用数学公式说一下吧。1、目标模型,算法采用的是特征值的加权概率分布来描述目标模型。这应该是模式识别中主要描述目标的模型,不同于自动控制理论中采用的状态方程。目标模型共m个特征值(可以理解为像素灰度值)
其中X0是窗口中心点向量值(可能为RBG 向量或者灰度值), Xi 是窗口内第i 点向量值。C 为归一化常数,保障q1+q2+q3+……qm=1,H 为核函数的带宽向量。M 为特征值的个数,对应于图像处理可以理解为灰度等级划分的个数,从而特征值u 为对应的灰度等级。d 函数为脉冲函数,保证只有具有u 特征值的像素才对概率分布作出贡献。从而k函数可以理解为u 灰度值的一个加权频数。
2、 匹配对象,也采用特征值加权概率分布
其中,Y 为匹配对象的中心, Xi 是匹配窗口内第i 点向量值, Hh 为匹配窗口的核函数带宽向量。 Ch 为匹配窗口特征向量的归一化常数。
3、 匹配对象与目标模型的相似程度,相似函数可采用Bhattacharyya 函数
4、 匹配过程就是寻相似函数最大值的寻优过程,Mean-Shift 采用的是梯度下降法。首先将(Y) 在
(Y0)附近进行泰勒级数展开,取前两项。即:
要使得(Y) 向最大值迭代,只要Y 的搜索方向与梯度方向一致即可,通过求导可得到Y0的梯度方向为:
为权值。因此如果如下确定Y1,那么Y1-Y0将与梯度方向一致。
以上为mean shift的数学原理。有关文字的叙述已经在上一篇中提到了。用mean shift来跟踪属于确定性算法,粒子滤波器属于统计学方法。meanshift跟踪算法相对于粒子滤波器来说可能实时性更好一些,但是跟踪的准确性在理论上还是略逊于粒子滤波器的。mean shift跟踪的的实质就是通过对应的模板来确定目标的下一个位置。通过迭代到新的中心点(即是目标的新的位置点)。有关跟踪的code如下所示:
/**********************************************************************
Bilkent University:
Mean-shift Tracker based Moving Object Tracker in Video
Version: 1.0
Compiler: Microsoft Visual C++ 6.0 (tested in both debug and release
          mode)
Modified by Mr Zhou
**********************************************************************/
#include "ObjectTracker.h"
#include "utils.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/*
#define GetRValue(rgb)  ((UBYTE8) (rgb))
#define GetGValue(rgb)  ((UBYTE8) (((ULONG_32) (rgb)) >> 8))

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。