[综] meanshift算法
Meanshift,聚类算法
http://www.cnblogs.com/liqizhou/archive/2012/05/12/2497220.html
记得刚读研究生的时候,学习的第一个算法就是meanshift算法,所以一直记忆犹新,今天和大家分享一下Meanshift算法,如有错误,请在线交流。
Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束.
1. Meanshift推导
给定d维空间Rd的n个样本点 ,i=1,…,n,在空间中任选一点x,那么Mean Shift向量的基本形式定义为:
Sk是一个半径为h的高维球区域,满足以下关系的y点的集合,
k表示在这n个样本点xi中,有k个点落入Sk区域中.
以上是官方的说法,即书上的定义,我的理解就是,在d维空间中,任选一个点,然后以这个点为圆心,h为半径做一个高维球,因为有d维,d可能大于2,所以是高维球。落在这个球内的所有点和圆心都会产生一个向量,向量是以圆心为起点落在球内的点位终点。然后把这些向量都相加。相加的结果就是Meanshift向量。
如图所以。其中黄色箭头就是Mh(meanshift向量)。
再以meanshift向量的终点为圆心,再做一个高维的球。如下图所以,重复以上步骤,就可得到一个meanshift向量。如此重复下去,meanshift算法可以收敛到概率密度最大得地方。也就是最稠密的地方。
最终的结果如下:
Meanshift推导:
把基本的meanshift向量加入核函数,核函数的性质在这篇博客介绍:http://www.cnblogs.com/liqizhou/archive/2012/05/11/2495788.html
那么,meanshift算法变形为
(1)
解释一下K()核函数,h为半径,Ck,d/nhd 为单位密度,要使得上式f得到最大,最容易想到的就是对上式进行求导,的确meanshift就是对上式进行求导.
(2)
令:
K(x)叫做g(x)的影子核,名字听上去听深奥的,也就是求导的负方向,那么上式可以表示
对于上式,如果才用高斯核,那么,第一项就等于fh,k
第二项就相当于一个meanshift向量的式子:
那么(2)就可以表示为
下图分析的构成,如图所以,可以很清晰的表达其构成。
要使得=0,当且仅当=0,可以得出新的圆心坐标:
(3)
上面介绍了meanshift的流程,但是比较散,下面具体给出它的算法流程。
- 选择空间中x为圆心,以h为半径为半径,做一个高维球,落在所有球内的所有点xi
- 计算,如果<ε(人工设定),推出程序。如果>ε, 则利用(3)计算x,返回1.
2.meanshift在图像上的聚类:
真正大牛的人就能创造算法,例如像meanshift,em这个样的算法,这样的创新才能推动整个学科的发展。还有的人就是把算法运用的实际的运用中,推动整个工业进步,也就是技术的进步。下面介绍meashift算法怎样运用到图像上的聚类核跟踪。
一般一个图像就是个矩阵,像素点均匀的分布在图像上,就没有点的稠密性。所以怎样来定义点的概率密度,这才是最关键的。
如果我们就算点x的概率密度,采用的方法如下:以x为圆心,以h为半径。落在球内的点位xi 定义二个模式规则。
(1)x像素点的颜色与xi像素点颜色越相近,我们定义概率密度越高。
(2)离x的位置越近的像素点xi,定义概率密度越高。
所以定义总的概率密度,是二个规则概率密度乘积的结果,可以(4)表示
(4)
其中:代表空间位置的信息,离远点越近,其值就越大,表示颜色信息,颜色越相似,其值越大。如图左上角图片,按照(4)计算的概率密度如图右上。利用meanshift对其聚类,可得到左下角的图。
----------------------------------------------------------------------------------------------------------------------
meanshift算法
http://blog.sina.com.cn/s/blog_6fd15d5f01016agj.html
Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束.
1. Meanshift推导
给定d维空间Rd的n个样本点 ,i=1,…,n,在空间中任选一点x,那么Mean Shift向量的基本形式定义为:
Sk是一个半径为h的高维球区域,满足以下关系的y点的集合,
k表示在这n个样本点xi中,有k个点落入Sk区域中.
以上是官方的说法,即书上的定义,我的理解就是,在d维空间中,任选一个点,然后以这个点为圆心,h为半径做一个高维球,因为有d维,d可能大于2,所以是高维球。落在这个球内的所有点和圆心都会产生一个向量,向量是以圆心为起点落在球内的点位终点。然后把这些向量都相加。相加的结果就是Meanshift向量。
如图所以。其中黄色箭头就是Mh(meanshift向量)。
再以meanshift向量的终点为圆心,再做一个高维的球。如下图所以,重复以上步骤,就可得到一个meanshift向量。如此重复下去,meanshift算法可以收敛到概率密度最大得地方。也就是最稠密的地方。
最终的结果如下:
Meanshift推导:
把基本的meanshift向量加入核函数,核函数的性质在这篇博客介绍:http://www.cnblogs.com/liqizhou/archive/2012/05/11/2495788.html
那么,meanshift算法变形为
(1)
解释一下K()核函数,h为半径,Ck,d/nhd 为单位密度,要使得上式f得到最大,最容易想到的就是对上式进行求导,的确meanshift就是对上式进行求导.
(2)
令:
K(x)叫做g(x)的影子核,名字听上去听深奥的,也就是求导的负方向,那么上式可以表示
对于上式,如果才用高斯核,那么,第一项就等于fh,k
第二项就相当于一个meanshift向量的式子:
那么(2)就可以表示为
下图分析的构成,如图所以,可以很清晰的表达其构成。
要使得=0,当且仅当=0,可以得出新的圆心坐标:
(3)
上面介绍了meanshift的流程,但是比较散,下面具体给出它的算法流程。
- 选择空间中x为圆心,以h为半径为半径,做一个高维球,落在所有球内的所有点xi
- 计算,如果<ε(人工设定),推出程序。如果>ε, 则利用(3)计算x,返回1.
2.meanshift在图像上的聚类:
真正大牛的人就能创造算法,例如像meanshift,em这个样的算法,这样的创新才能推动整个学科的发展。还有的人就是把算法运用的实际的运用中,推动整个工业进步,也就是技术的进步。下面介绍meashift算法怎样运用到图像上的聚类核跟踪。
一般一个图像就是个矩阵,像素点均匀的分布在图像上,就没有点的稠密性。所以怎样来定义点的概率密度,这才是最关键的。
如果我们就算点x的概率密度,采用的方法如下:以x为圆心,以h为半径。落在球内的点位xi 定义二个模式规则。
(1)x像素点的颜色与xi像素点颜色越相近,我们定义概率密度越高。
(2)离x的位置越近的像素点xi,定义概率密度越高。
所以定义总的概率密度,是二个规则概率密度乘积的结果,可以(4)表示
(4)
其中:代表空间位置的信息,离远点越近,其值就越大,表示颜色信息,颜色越相似,其值越大。如图左上角图片,按照(4)计算的概率密度如图右上。利用meanshift对其聚类,可得到左下角的图。
http://www.cnblogs.com/liqizhou/archive/2012/05/12/2497220.html
Matlab中meanshift算法
mean-shift 的特点是把支撑空间和特征空间在数据密度的框架下综合了起来。对图像来讲,支撑空间就是像素点的坐标,特征空间就是对应像素点的灰度或者RGB三分量。将这两个空间综合后,一个数据点就是一个5维的向量:[x,y,r,g,b]。
这在观念上看似简单,实质是一个飞跃,它是mean-shift方法的基点。
mean-shift方法很宝贵的一个特点就是在这样迭代计算的框架下,求得的mean-shift向量必收敛于数据密度的局部最大点。可以细看[ComaniciuMeer2002]的文章。
写了点程序,可以对图像做简单的mean-shift filtering,供参考:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [DRGB, DSD, MSSD] = MScut(sMode, RGB_raw, hs, hf, m );
% designed for segmenting a colour image using mean-shift [ComaniciuMeer 2002]
% image must be color
% procedure in mean-shift
% 1. combine support space and feature space to make a mean-shift space
% based data description
% 2. for every mean-shift space data
% 3. do mean-shift filtering
% until convergence
% 4. end
% 5. find the converged mean-shift space data that you are interested in
% and label it
% 6. repeat the above steps
%
% a -- data in support space
% b -- data in feature space
% x -- data in mean-shift space
% f(.) -- data density function
% k(.) -- profile function (implicit)
% g(.) -- profile function (explicit)
% m -- mean shift vector
% hs -- bandwidth in support space
% hf -- bandwidth in feature space
% M -- threshold to make a distinct cluster
%% enter $hs$, $hf$, $m$ if necessary
if ~exist('hs')
hs = input('please enter spatial bandwidth (hs):n');
end
if ~exist('hf')
hf = input('please enter feature bandwidth (hf):n');
end
if ~exist('m')
m = input('please enter minimum cluster size (m):n');
end
switch upper(sMode)
case 'RGB'
RGB = double( RGB_raw );
case 'gray'
error('FCMcut must use colored image to do segmentation!')
end
sz = size(RGB);
mTCUT = Tcut( RGB(:,:,1) ); % trivial segmentation
%% project data into mean-shift space to make $MSSD$ (mean-shift space data)
mT = repmat([1:sz(1)]', 1, sz(2));
vX = mT(1:end)'; % row
mT = repmat([1:sz(2)], sz(1), 1);
vY = mT(1:end)'; % column
mT = RGB(:,:,1);
vR = mT(1:end)'; % red
mT = RGB(:,:,2);
vG = mT(1:end)'; % green
mT = RGB(:,:,3);
vB = mT(1:end)'; % blue
MSSD = [vX, vY, vR, vG, vB];
%% make $g$ - explicit profile function
disp('Using flat kernel: Epanechnikov kernel...')
g_s = ones(2*hs+1, 2); % 's' for support space
g_f = ones(2*hf+1, 3); % 'f' for feature space
%% main part $$
nIteration = 4;
nData = length(MSSD); % total number of data
DSD = MSSD*0; % 'DSD' for destination space data
for k = 1:nData
%
tMSSD = MSSD(k,:); % 't' for temp
for l = 1:nIteration
%
mT = abs( MSSD - repmat(tMSSD, nData, 1));
vT = logical( (mT(:,1)<=hs).*(mT(:,2)<=hs).*(mT(:,3)<=hf).*(mT(:,4)<=hf).*(mT(:,5)<=hf) );
v = MSSD(vT,:);
% update $tMSSD$
tMSSD = mean( v, 1 );
if nIteration == l
DSD(k,:) = tMSSD;
end
end
end
% show result
DRGB = RGB * 0;
DRGB(:,:,1) = reshape(DSD(:,3), sz(1), sz(2)); % red
DRGB(:,:,2) = reshape(DSD(:,4), sz(1), sz(2)); % red
DRGB(:,:,3) = reshape(DSD(:,5), sz(1), sz(2)); % red
figure, imshow(uint8(DRGB), [])
-------------------------------------------------------------------------------------------------------------------------
matlab练习程序(meanshift图像聚类)
http://www.cnblogs.com/tiandsp/archive/2012/11/20/2779601.html
关于这个meanshift,一来可以用来作为目标跟踪,二来可以用来进行图像聚类。我这里只实现了图像聚类,当然,是按自己的理解编写的程序。至于目标跟踪将来一定也是要实现的,因为我最初看这个算法的原因就是想用他来跟踪目标的。
meanshift的基本原理我就不介绍了,比起我的介绍,网上有不少牛人们比我解释的好,最后我会列出我参考的文章。我这里说一下我是怎么理解meanshift图像聚类的。这里的聚类也像过去的滤波一样,需要一个模板矩阵,不过这个模板不是事先设置好的矩阵,而是在当前处理的像素周围提取一个r*r的矩阵,然后把这个矩阵化为一维向量,再对这个向量进行meanshift,最终迭代到的值再赋值给当前处理的像素。所以可以这样理解,把图像经过meanshift迭代到相同值的像素聚为一类。
我这里使用的是灰度图像,至于彩色图像,我看到一篇博客上把rgb域转换到luv域上再去做处理,这个我就不太清楚了,不过我看他的代码其中有一部分很像均值滤波。虽然我没有和他用一样的方法,不过他的代码也可以参考一下。传送门在此。
下面是代码(这都是我自己的理解,不能保证都正确,不过至少可以为你的编码提供一些思路):
main.m
clear all;
close all;
clc; r=2; %滤波半径
img=imread('lena.jpg');
imshow(img);
img=double(img);
[m n]=size(img); imgn=zeros(m+2*r+1,n+2*r+1); imgn(r+1:m+r,r+1:n+r)=img;
imgn(1:r,r+1:n+r)=img(1:r,1:n);
imgn(1:m+r,n+r+1:n+2*r+1)=imgn(1:m+r,n:n+r);
imgn(m+r+1:m+2*r+1,r+1:n+2*r+1)=imgn(m:m+r,r+1:n+2*r+1);
imgn(1:m+2*r+1,1:r)=imgn(1:m+2*r+1,r+1:2*r);
imshow(mat2gray(imgn)) for i=1+r:m+r
for j=1+r:n+r
ser=imgn(i-r:i+r,j-r:j+r);
ser=reshape(ser,[1 (2*r+1)^2]); %将二维模板变为一维
imgn(i,j)=mean_shift(ser,2*r^2+2*r+1); %取模板最中间的那个值作为迭代初值 end
end figure;
imgn=imgn(r+1:m+r,r+1:n+r);
imshow(mat2gray(imgn));
meanshift.m
function re= mean_shift( ser,p)
[m n]=size(ser);
tmp=double(ser); pre_w=tmp(p);
point=p;
while 1
ser=tmp-pre_w; for i=1:m*n
if i ~= point
ser(i)=ser(i)/(i-point); %i-point是距离,就是各种公式里的h
end
end ser=ser.^2;
K=(1/sqrt(2*pi))*exp(-0.5*ser); %传说中的核函数
w=sum(tmp.*(K))/sum(K); if abs(w-pre_w)<0.01
break;
end
pre_w=w;
end
% tmp1=abs(tmp-w);
% [i point]=min(tmp1);
re=w;
% if max(tmp)-w<0.01
% point=0;
% end
% point=w;
end
处理的效果:
原图
半径为2处理的效果
——————————下面是2013.5.30添加————————————
上一部分的meanshift图像聚类还需修改,下面实现最简单的meanshift算法,完全按照原理来。
最后的参考文献都是很好的总结,不过这次我是参考的《图像处理、分析与机器视觉(第3版)》这本书。
下面是通常所见的迭代效果:
程序如下:
clear all; close all; clc; %测试数据
mu=[0 0]; %均值
S=[30 0;0 35]; %协方差
data=mvnrnd(mu,S,300); %产生300个高斯分布数据
plot(data(:,1),data(:,2),'o'); h=3; %核的大小
x=[data(1,1) data(1,2)]; %以第一个数据为迭代初值
pre_x=[0 0]; hold on
while norm(pre_x-x)>0.01; pre_x=x;
plot(x(1),x(2),'r+');
u=0; %分子累加项
d=0; %分母累加项
for i=1:300
%最关键的两步,均值位移公式实现
k=norm((x-data(i,:))/h).^2;
g=(1/sqrt(2*pi))*exp(-0.5*k); u=data(i,:)*g+u;
d=g+d;
end
M=u/d; %迭代后的坐标位置
x=M; end
参考:
1.http://en.wikipedia.org/wiki/Mean-shift wiki百科,介绍的简介明了。
2.http://www.cnblogs.com/liqizhou/archive/2012/05/12/2497220.html 非常详细的理解。
3.http://emuch.net/bbs/viewthread.php?tid=4626864 小木虫上一个同学的理解。
4.http://en.wikipedia.org/wiki/Kernel_(statistics) 介绍核函数的。
5.http://wenku.baidu.com/view/11b6a7de6f1aff00bed51eac.html 提出meanshift算法的论文,虽然我没怎么看,不过想对算法彻底理解的还是看这篇好。
------------------------------------------------------------------------------------------------------------
Meanshift图像平滑之opencv实现
http://www.cnblogs.com/easymind223/archive/2012/07/03/2574887.html
一句话一幅图理解meanshift算法:
对于集合中的每一个元素,对它执行下面的操作:把该元素移动到它邻域中所有元素的特征值的均值的位置,不断重复直到收敛。
准确的说,不是真正移动元素,而是把该元素与它的收敛位置的元素标记为同一类。对于图像来说,所有元素程矩阵排列,特征值便是像素的灰度值。
Meanshift的这种思想可以应用于目标跟踪、图像平滑、边缘检测、聚类等,是一种适应性很好的算法,缺点是速度非常慢。
本文以图像平滑为例对其说明
从网上找代码不如自己动手写。说明一下两个参数的含义,hs和hr是核函数的窗口大小,hs是距离核函数,控制子窗口的大小,同时也影响计算速度。hr是颜色核函数,是颜色差值的阈值,maxiter是最大迭代次数。转载请注明出处,谢谢。本文算法只是用作实验之用,没有进行优化,计算时会有重复计算的地方,速度非常慢,且只支持3通道图像。
1 void MyTreasureBox::MeanShiftSmooth(const IplImage* src, IplImage* dst, int hs, int hr, int maxIter)
2 {
3 if(!src)return ;
4
5 IplImage* srcLUV = cvCreateImage( cvGetSize( src ), src->depth, src->nChannels );
6 IplImage* dstLUV = cvCreateImage( cvGetSize( src ), src->depth, src->nChannels );
7
8 cvCvtColor( src, srcLUV, CV_RGB2Luv);
9 cvCopy( srcLUV, dstLUV );
10
11 int widthstep = srcLUV->widthStep;
12 int channel = srcLUV->nChannels;
13
14 for( int y = 0; y<src->height; y++ )
15 {
16 for( int x = 0; x<src->width; x++ )
17 {
18 uchar L = (uchar)srcLUV->imageData[y *widthstep + x *channel];
19 uchar U = (uchar)srcLUV->imageData[y *widthstep + x *channel + 1];
20 uchar V = (uchar)srcLUV->imageData[y *widthstep + x *channel + 2];
21 int xx = x;
22 int yy = y;
23
24 int nIter = 0;
25 int count, sumL, sumu, sumv, sumx, sumy;
26
27 while(nIter < maxIter)
28 {
29 count = 0;
30 sumL = sumu = sumv = 0;
31 sumx = sumy = 0;
32
33 for( int m = y - hs; m <= y + hs; m++ )
34 {
35 for( int n = x - hs; n <= x + hs; n++ )
36 {
37 if(m >= 0 && m < src->height && n >= 0 && n < src->width)
38 {
39 uchar l = (uchar)srcLUV->imageData[m *widthstep + n *channel];
40 uchar u = (uchar)srcLUV->imageData[m *widthstep + n *channel + 1];
41 uchar v = (uchar)srcLUV->imageData[m *widthstep + n *channel + 2];
42
43 double dist = sqrt( (double)((L - l)^2 + (U - u)^2 + (V - v)^2) );
44 if( dist < hr )
45 {
46 count++;
47 sumL += l;
48 sumu += u;
49 sumv += v;
50 sumx += n;
51 sumy += m;
52 }
53 }
54 }
55 }
56 if(count == 0)break;
57 L = sumL / count;
58 U = sumu / count;
59 V = sumv / count;
60 xx = sumx / count;
61 yy = sumy / count;
62
63 nIter++;
64 }
65 dstLUV->imageData[y *widthstep + x *channel] = L;
66 dstLUV->imageData[y *widthstep + x *channel + 1] = U;
67 dstLUV->imageData[y *widthstep + x *channel + 2] = V;
68 }
69 }
70
71 cvCvtColor( dstLUV, dst, CV_Luv2RGB );
72 cvReleaseImage(&srcLUV);
73 cvReleaseImage(&dstLUV);
74 }
hs和hr的控制可以参阅下图
[综] meanshift算法的更多相关文章
- 基于 MeanShift 算法的目标跟踪问题研究
参考:http://www.cnblogs.com/tornadomeet/archive/2012/03/15/2398769.html MeanShift 算法作为一种基于特征的跟踪方法,基本思想 ...
- meanShift算法介绍
meanShift,均值漂移,在聚类.图像平滑.切割.跟踪等方面有着广泛的应用.meanShift这个概念最早是由Fukunage在1975年提出的,其最初的含义正如其名:偏移的均值向量:但随着理论的 ...
- Meanshift算法学习
ref:参考自:这里(目标跟踪) Meanshift图像分割:这里 最近看到FT算法使用meanshift算法进行显著图的分割,于是就来学习他的姿势 对于集合中的每一个元素,对它执行下面的操作:把该元 ...
- Meanshift算法
[转载自Liqizhou],原文地址 Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束. 1. ...
- 31(2).密度聚类---Mean-Shift算法
Mean-Shift 是基于核密度估计的爬山算法,可以用于聚类.图像分割.跟踪等领域.
- matlab工具箱之人眼检测+meanshift跟踪算法--人眼跟踪
Viola-Jones 人眼检测算法+meanshift跟踪算法 这次的代码是对视频中的人眼部分进行检测加跟踪,检测用的是matlab自带的人眼检测工具箱 下面是matlab官网介绍这个算法的一些东西 ...
- Meanshift均值漂移算法
通俗理解Meanshift均值漂移算法 Meanshift车手?? 漂移?? 秋名山??? 不,不,他是一组算法, 今天我就带大家来了解一下机器学习中的Meanshift均值漂移. Mea ...
- Meanshift,聚类算法(转)
原帖地址:http://www.cnblogs.com/liqizhou/archive/2012/05/12/2497220.html 记得刚读研究生的时候,学习的第一个算法就是meanshif ...
- 目标跟踪算法meanshift优缺点
原博主:http://blog.csdn.net/carson2005/article/details/7341051 meanShift算法用于视频目标跟踪时,采用目标的颜色直方图作为搜索特征,通过 ...
随机推荐
- 漏洞复现——httpd换行解析漏洞
漏洞原理: 在解析php文件时,1.php\x0A这种格式的文件将会被认为php文件解析,进而可以绕过一些服务器的安全策略. 漏洞版本: 2.4.0~2.4.29 漏洞复现: 复现该漏洞是利用dock ...
- vue-常用指令
一.一些指令 1.v-bind 绑定元素(简写 :) <div id="app-2"> <span v-bind:title="message" ...
- 和系统运行状况相关的Shell命令总结
1. Linux的实时监测命令(watch): watch 是一个非常实用的命令,可以帮你实时监测一个命令的运行结果,省得一遍又一遍的手动运行.该命令最为常用的两个选项是-d和-n,其中-n表 ...
- javascript中NAN undefined 和null
null 表示无值,而 undefined 表示一个未声明的变量,或已声明但没有赋值的变量,或一个并不存在的对象属性. NaN 属性是代表非数字值的特殊值.该属性用于指示某个值不是数字.可以把 Num ...
- Windows IIS服务挂载NAS共享文件存储
本文介绍如何结合阿里云NAS的SMB协议支持和ECS Windows虚拟机,使用Windows内置的互联网信息服务(IIS)来提供Web和FTP服务. 阿里云文件存储服务NAS主要面向阿里云ECS 实 ...
- H5-移动端实现滑屏翻页-原生js/jquery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- angualr Material Icons
首先需要项目引入 angualr meterial icons的资源库 图标资源链接 https://klarsys.github.io/angular-material-icons/ <md- ...
- Centos7修改分区空间
一:缩小/home空间 1.1:备份/home内容 cp -r /home/* /homebak 1.2:删除挂载/home umount /home 1.3:删除/home所在lv lvremove ...
- vue bus的使用
vue中的bus事件,一般作为中央事件总线来使用 简单例子:比如在A,B组件为兄弟组件,现在A要调用B的中C事件 1.创建一个bus.js 内容: import Vue from 'vue' cons ...
- [多线程] 线程中的synchronized关键字锁
为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...