深入剖析mean shift 图像分割 原理及代码

上网搜了一下,还没发现把mean shift原理说的很清楚的文章,我就来写一段了:

首先你要知道这是PAMI 2003的一篇文章,非常经典的哦,Mean Shift: A Robust Approach Toward Feature Space Analysis。当然原文有17页,都是一些复杂的公式。。。。。

Mean shift主要用在图像平滑和图像分割(那个跟踪我现在还不清楚),先介绍一下平滑的原理:

输入是一个5维的空间,2维的(x,y)地理坐标,3维的(L,u,v)的颜色空间坐标,当然你原理也可以改写成rgb色彩空间或者是纹理特征空间。

先介绍一下核函数,有uniform的,也有高斯的核函数,不管是哪个的,其基本思想如下:简单的平滑算法用一个模板平均一下,对所有的像素,利用周围的像素平均一下就完事了,

这个mean shift的是基于概率密度分布来的,而且是一种无参的取样。有参的取样就是假设所有的样本服从一个有参数的概率分布函数,比如说泊松分布,正态分布等等,高中生都知道概率公式里面是有参数的,在说一下特征空间是一个5维的空间,距离用欧几里德空间就可以了,至少代码里就是这样实现的,而本文的无参取样是这样的:在特征空间里有3维的窗口(想象一下2维空间的窗口),对于一个特征空间的点,对应一个5维的向量,可以计算该点的一个密度函数,如果是有参的直接带入该点的坐标就可以求出概率密度了,基于窗函数的思想就是考虑它邻近窗口里的点对它的贡献, 它假设密度会往密集一点的地方转移,算出移动之后的一个5维坐标,该坐标并会稳定,迭代了几次之后,稳定的地方是modes。这样每一个像素点都对应一个这么一个modes,用该点的后3维的值就是平滑的结果了,当然在算每个点的时候,有些地方可能重复计算了,有兴趣的化你可以参考一下源代码,确实是可以优化的。总结一下mean shift的平滑原理就是在特征空间中向密度更高的地方shift(转移)。

其次是怎么利用mean shift分割图像

先对图像进行平滑,

第2步利用平滑结果建立区域邻接矩阵或者区域邻接链表,就是在特征空间比较近的二间在2维的图像平面也比较接近的像素算成一个区域,这样就对应一个区域的邻接链表,记录每个像素点的label值。当然代码中有一个传递凸胞的计算,合并2个表面张力很接近的相邻区域,这个我还没想怎么明白,希望比较清楚的朋友讲一讲。最后还有一个合并面积较小的区域的操作,一个区域不是对应一个modes值嘛,在待合并的较小的那个区域中,寻找所有的邻接区域,找到距离最小的那个区域,合并到那个区域就ok了。

void msImageProcessor::Filter(int sigmaS, float sigmaR, SpeedUpLevel speedUpLevel)这个是平滑操作,sigmaS是2维的平面窗口的窗函数,sigmaR是颜色空间的窗函数,最后一个参数表示是否加速算法。

void msImageProcessor::FuseRegions(float sigmaS, int minRegion)这个就是合并较小区域的一个函数。

void msImageProcessor::Segment(int sigmaS, float sigmaR, int minRegion, SpeedUpLevel speedUpLevel)这个是分割函数,里面包括了平滑功能。再详细的我也不说了。。。。。

最后是怎么调用问题:void CImageProcessing::mydebug()
{
int x,y;
    int width_ = imageWidth;
int height_ = imageHeight;
unsigned char *tmp = new unsigned char[width_ * height_ * 3];
unsigned char *dst = tmp;

for (x = 0;x < imageHeight; x ++)
   for(y = 0;y < imageWidth; y++)
   {
    //Color tmp = (*imageData_RGB)(y, x);
    //uchar * data = &CV_IMAGE_ELEM(ip,uchar,x,y*3) ;
   // *(dst++) = data[2] ;
   // *(dst++) = data[1] ;
   // *(dst++) = data[0] ;
    
    *(dst++) = (*imageData_RGB)(y, x).channel[0];
    *(dst++) = (*imageData_RGB)(y, x).channel[1];
    *(dst++) = (*imageData_RGB)(y, x).channel[2];
   }
   cbgImage_->SetImageFromRGB( tmp, width_, height_, true);
   delete []tmp;
  
   msImageProcessor *iProc = new msImageProcessor();
   iProc->DefineImage(cbgImage_->im_, COLOR, height_, width_);
   iProc->SetSpeedThreshold(0.1);
   iProc->Segment(5,8,10,NO_SPEEDUP);
// iProc->Filter(5,8,NO_SPEEDUP);
// iProc->FuseRegions(mWinSize,mAreaSize);//°ë¾¶ºÍ×îСÇøÓòÃæ»ý
} 至于怎么调试编译我看我是说不清楚了。。。。。。。。。。。。。。。。。。。。。。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值