1. 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对其聚类,可得到左下角的图。
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), [])
2. kmeans
基本简介
matlab中有kmeans函数直接可以调用,
使用方法:
Idx=Kmeans(X,K)
[Idx,C]=Kmeans(X,K)
[Idx,C,sumD]=Kmeans(X,K)
[Idx,C,sumD,D]=Kmeans(X,K)
[…]=Kmeans(…,’Param1’,Val1,’Param2’,Val2,…)
各输入输出参数介绍:
X N*P的数据矩阵
K 表示将X划分为几类,为整数
Idx N*1的向量,存储的是每个点的聚类标号
C K*P的矩阵,存储的是K个聚类质心位置
sumD 1*K的和向量,存储的是类间所有点与该类质心点距离之和
D N*K的矩阵,存储的是每个点与所有质心的距离
下面转于http://blog.sina.com.cn/s/blog_51eea616010091ub.html
K平均标准算法是选取样本的前K个样本作为初始聚类中心,但这种方法收敛速度慢。
有几种改进算法:
1.在样本空间随机选取;
2.用小中取大法选取聚类中心;
3.根据样本的统计特性来选取,即根据样本均值和方差来选取,在u+s 和u-s之间等间隔取k个点作为聚类中心,这种方法收敛速度快。
4.根据样本的分布密度来选取,有点借鉴P窗法的味道。
下面把K平均算法程序贴在下面,希望同仁们对他提出代码优化的宝贵意见:
function KMeansv0(K,N,E,data,ff,cf)
%K=the number of clusters
%N=the maximum times of iteration
%E=the deviation theshold
%data=the pixel infor of figure
%ff=the feature selected
data=im2double(data);
r=data(:,:,1);
g=data(:,:,2);
b=data(:,:,3);
height=size(data,1);
width=size(data,2);
pixnum=height*width;
flag=zeros(pixnum,1);
samples=generatesamp(r,g,b,height,width,pixnum);
sampled=selectfeature(samples,ff);
oldcenter=centerselect(K,sampled,cf);
color=colorgenerate(K);
L=1;
%程序主体
while(1)
D=distfun(sampled,oldcenter);
for i=1:pixnum
j=find(D(i,:)==min(D(i,:)));
if size(j,2)>1
flag(i)=j(1);
else
flag(i)=j;
end
end
updatefig(flag,samples,color,data);
newcenter=recalcu(flag,sampled,K,oldcenter);
if L>=N
break;
else
L=L+1;
t=0;
for i=1:K
err=distfun(newcenter(i),oldcenter(i));
if err>=E
oldcenter(i,:)=newcenter(i,:); %%modified
else
t=t+1;
end
end
if t==K
break;
end
end
end
end
%%以下是自函数部分
function samples=generatesamp(r,g,b,height,width,pixnum)
% p=0;
% for i=1:height
% for j=1:width
% p=p+1;
% samples(p,:)=[r(i,j),g(i,j),b(i,j),i,j];
% end
% end
r1=reshape(r,height*width,1);
g1=reshape(g,height*width,1);
b1=reshape(b,height*width,1);
x=linspace(1,height,height);
x1=repmat(x',width,1);
y1=ones(pixnum,1); %%modified ,maybe improve speed
for i=2:width
y=ones(height,1).*i;
star=height*(i-1)+1;
stop=star+height-1;
y1(star:stop,1)=y(:,1);
end
samples=[r1 g1 b1 x1 y1];
end
function center=centerselect(k,sampled,cf)
%select the first K pixel as the origincenter
center=zeros(k,size(sampled,2));
switch cf
case 1 %select the first k sampled as center
for i=1:k
center(i,:)=sampled(i,:);
end
case 2 %select k centers randamly
% p=round(rand(k,1))*size(sampled,1)+1;
% center(:,:)=sampled(p',:);
case 3 %select k centers according to max(min)
s=round(rand*(size(sampled,1)/2))+1;
tempc(1,:)=sampled(s,:);
for j=2:k
d=distfun(sampled,tempc);
dmin=zeros(size(sampled,1),1);
for i=1:size(sampled,1)
dmin(i,1)=min(d(i,:));
end
% index=find(dmin==max(dmin)); %logical index is usually...
%faster than FIND
[dmax,index]=max(dmin);
tempc(j,:)=sampled(index,:);
end
center=tempc;
case 4 %select k centers according to mean and variance
m=mean(sampled);
v=std(sampled);
t1=m-v;
t2=m+v;
p=size(sampled,2);
for i=1:p
temp=linspace(t1(i),t2(i),k);
center(:,i)=temp';
end
end
end
function color=colorgenerate(k)
% r=[255 0 0];
% g=[0 255 0];
% b=[0 0 255];
% l1=linspace(1,0,k);
color=zeros(k,3);
% l2=rand(1,k);
for i=1:k
% color(i,:)=[round(rand(1,1)*255) round(rand(1,1)*255)...
% round(rand(1,1)*255)];
color(i,:)=[rand rand rand];
% color(i,:)=round(l1(i)*r)+round((1-l1(i))*g.*l2(i))...
% +round((1-l1(i))*b.*(1-l2(i)));
end
end
function sampled=selectfeature(samples,ff)
p=sum(ff);
flag=find(ff==1);
num=size(samples,1);
sampled=zeros(num,p);
% for i=1:num
% for j=1:p
% sampled(i,j)=samples(i,flag(j));
% end
% end
for j=1:p
sampled(:,j)=samples(:,flag(j)); %compared with above ,improve speed
end
end
function D = distfun(X, C)
%DISTFUN Calculate point to cluster centroid distances.
[n,p] = size(X);
D = zeros(n,size(C,1));
nclusts = size(C,1);
for i = 1:nclusts
D(:,i) = (X(:,1) - C(i,1)).^2;
for j = 2:p
D(:,i) = D(:,i) + (X(:,j) - C(i,j)).^2;
end
end
end
function updatefig(flag,samples,color,data)
[n,p]=size(samples);
for i=1:n
for j=1:3
samples(i,j)=color(flag(i),j);
data(samples(i,4),samples(i,5),j)=samples(i,j);
end
end
data=im2uint8(data);
% hold on
figure,imshow(data);
% hold off
end
function newcenter=recalcu(flag,sampled,k,oldcenter)
sumtemp=zeros(k,size(sampled,2));
aveg=zeros(k,size(sampled,2));
for i=1:k
tt=find(flag==i);
if size(tt,1)==0
aveg(i,:)=oldcenter(i,:);
continue;
end
num=size(tt,1);
temp=zeros(num,size(sampled,2));
for j=1:num
temp(j,:)=sampled(tt(j),:);
end
[n,p]=size(temp);
for l=1:p
sumtemp(i,l)=sum(temp(:,l));
aveg(i,l)=sumtemp(i,l)./n;
end
end
newcenter=aveg;
end
原图和处理结果图:
参数选择:
类数:6,最大迭代次数:50,误差:10^-5,特征选择:RGB,初始类心:均值方差法.