聚類算法——kmeans和meanshift

聚類算法——kmeans和meanshift [轉]

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

基本簡介

k-means 算法接受輸入量 k ;然後將n個數據對象劃分爲 k個聚類以便使得所獲得的聚類滿足:同一聚類中的對象相似度較高;而不同聚類中的對象相似度較小。聚類相似度是利用各聚類中對象的均值所獲得一個“中心對象”(引力中心)來進行計算的。
處理流程k-means 算法基本步驟
(1)  從 n個數據對象任意選擇 k 個對象作爲初始聚類中心;
(2)  根據每個聚類對象的均值(中心對象),計算每個對象與這些中心對象的距離;並根據最小距離重新對相應對象進行劃分;
(3)  重新計算每個(有變化)聚類均值(中心對象);
(4)  計算標準測度函數,當滿足一定條件,如函數收斂時,則算法終止;如果條件不滿足則回到步驟(2)。


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,初始類心:均值方差法.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章