關於這個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算法的論文,雖然我沒怎么看,不過想對算法徹底理解的還是看這篇好。