本方法实现参考冈萨雷斯《数字图像处理》第四版教程P555页
均值聚类实际是将图像的所有像素划分给规定数量k的聚类,每个像素都将会被分给具有最近均值的聚类
算法一般步骤为
初始化(确定k值,以及初始种子点的值,这里以灰度值进行聚类)————》进行划分,算待划分像素点值与种子点的L1或L2范数,看离谁进划分到哪一类————》划分结束后,就要更新种子点,可以以将划分的每一类的均值当做每一类新的种子点————》循环往复,直至迭代到不满足判定条件位置(即,更新迭代到种子点没发生什么变化时)
这里本人实现了一个k=2的聚类,代码如下
clear all
%读入图像
I=imread('1212.JPG');
G=rgb2gray(I);
G=im2double(G);
[h,w]=size(G);
%先聚合两类,k=2
k=2;
%迭代阈值T,规定与前三步的均值比较
T=2;
storage=zeros(1,6);
%随机赋种
m=zeros(1,k);
m(1)=0.7;
m(2)=0.8;
%创建标记矩阵
label=zeros([h,w]);
%指示这是第几次循环
index=1;
while abs(m(1)-storage(1))+abs(m(2)-storage(2))>0.4
%标记时,0为第一类,1为第二类
for x=1:w
for y=1:h
% G(y,x)
if abs(G(y,x)-m(1))-abs(G(y,x)-m(2))>0
% a=(G(y,x)-m(1))^2
% b=(G(y,x)-m(2))^2
label(y,x)=1;
end
end
end
%更新聚类中心
sum1=0;
sum2=0;
count1=0;
for x=1:w
for y=1:h
if label(y,x)==0
count1=count1+1;
sum1=sum1+G(y,x);
else
sum2=sum2+G(y,x);
end
end
end
position=mod(index,3);
storage(position+1)=m(1);
storage(position+2)=m(2);
m(1)=sum1/count1;
m(2)=sum2/(h*w-count1);
index=index+1;
end
%对比
figure(1)
imshow(label)
title('kmeans聚类结果')
thresh=graythresh(G);
bw=im2bw(G,thresh);
figure(2)
imshow(bw)
title('ostu结果')
下图是测试图像
下图是利用本文实现的kmenas和ostu大津法分割的结果对比,可以看到实现的效果还是不错的