meanshift的基本原理这里就不介绍了,详情可参考我的博客。
meanshift图像聚类的。这里的聚类也像过去的滤波一样,需要一个矩阵模板,不过这个模板就是当前处理的像素周围提取一个r*r的矩阵,然后把这个矩阵化为一维向量,再对这个向量进行meanshift,最终迭代到的值再赋值给当前处理的像素。所以可以这样理解,把图像经过meanshift迭代到相同值的像素聚为一类。(这段理解出自)实现代码方法可参见该博主的博客。
这里说一下我对该博主代码的理解,不对的话,欢迎大家在评论区批评指正。
把这个矩阵化为一维向量,再对这个向量进行meanshift”???
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
从mean_shift函数中的循环内:
for i=1:m*n
if i ~= point
ser(i)=ser(i)/(i-point); %i-point是距离,就是各种公式里的h
end
end
ser(i)代表中心像素与邻域像素的灰度差,ser(i)/(i-point)是为了根据邻域点到中心点的距离,设置不同的权重。比如一个5*5的邻域应该用ser(i)除以对应的(距离中心点的距离),而不应该简单的用(i-point)作为邻域点到中心点的距离吧。
权重矩阵应该定义为:
下面放上我修改后的代码。(那位博主的代码也能实现均值飘移,且效果良好。而我的这个版本,就处理效果而言,都差不多)
main.m:
clear all;
close all;
clc;
r=2; %滤波半径
k=2; %权重矩阵的指数,k越大,最终图像的飘移程度越高
img=imread('lena.jpg'); %灰度图像
weight=matrix_weight(r,k); %求权重矩阵
weight=reshape(weight,[1 (2*r+1)^2]);
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);
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));
matrix_weight.m:
function weight=matrix_weight(r,k)
%k:对距离进行k次幂计算作为最终的权值
weight=zeros(2*r+1,2*r+1);
for i=1:2*r+1
for j=
weight(i,j)=(norm([i,j]-[r+1,j+1]))^k;
end
end
end