使用方法:直接在matlab中运行,但注意更改图片路径名;
主要分三步:
1,初始化聚类中心,我使用K等分点做的;
2,随机性采样,出于效率的考虑;
3,剩余点划分,将未采集到的图像剩余点划分到簇类中。
clc;clear all;close all;
%% Kmeans聚类图像
K = 4;
im = imread('penguin.jpg');
im = imresize(im,[321,321],'nearest');
[R c lmd] = size(im);
elenum = numel(im(:,:,1));
total = [1:elenum];%总体;
dt = 0.1;%聚类中心迭代阈值;
for i = 1:size(im,lmd) %Cij表示第i波段成像,第j个
min_c = min(min(im(:,:,i)));
max_c = max(max(im(:,:,i)));
for k = 1:K
C(i,k) = min_c + k*((max_c - min_c)/(K + 1));
end
end
C = double(C);
C_orgi = C;%初始聚类中心;
%修改图像的存储模式
points(elenum) = struct('r',0,'g',0,'b',0,'cluster',0);
for i = 1:R
for j = 1:c
points((j-1)*R + i).r = im(i,j,1);
points((j-1)*R + i).g = im(i,j,2);
points((j-1)*R + i).b = im(i,j,3);
points((j-1)*R + i).cluster = 0;
end
end
smplrate = 1/10000;
smplseq = sort(randperm(elenum,ceil(elenum*smplrate)),'ascend');%随机性采样M*N个图像样本点
cluster(K,100) = struct('r',1,'c',1,'data',points(1));%存储簇类每行存储该簇类的样本点
counter(K) = 0;%记录每个簇类的样本点个数;
totalnum = 100;%聚类迭代最大次数;
for iteration = 1:totalnum
for i = smplseq
for j = 1:K
ptvalue(1,1) = points(i).r;
ptvalue(2,1) = points(i).g;
ptvalue(3,1) = points(i).b;
distclust(j) = norm(double(ptvalue) - double(C(:,j)));%存储样本点到聚类的距离;
end
clunum = find(distclust == min(distclust));%样本点距离聚类中心最小的簇类编号;
points(i).cluster = clunum;%标记该样本点类型;
counter(clunum) = counter(clunum) + 1;%样本计数增加一个
cluster(clunum,counter(clunum)).r = mod(i,R);
cluster(clunum,counter(clunum)).c = floor(i/R)+1;
cluster(clunum,counter(clunum)).data = points(i);
end
%更新每个聚类中心的
for i = 1:K
sum = repmat(double(0),[3,1]);
for j = 1:counter(i)
ptvalue(1,1) = cluster(i,j).data.r;
ptvalue(2,1) = cluster(i,j).data.g;
ptvalue(3,1) = cluster(i,j).data.b;
sum = sum + double(ptvalue);
end
if i == 1
C_new = sum/counter(i);
else
C_new = cat(2,C_new,sum/counter(i));
end
end
if norm(abs(C-C_new)) < dt
break;
end
C = C_new;
end
% 参数显示;
%disp('随机样本个数'),disp(size(smplseq,2));disp('初始聚类中心:');disp(C_orgi);disp('Kmeans 聚类新中心');disp(C);disp('聚类迭代次数');disp(iteration);
smpldiff = setdiff(total,smplseq);
for i = smpldiff
for j = 1:K
ptvalue(1,1) = points(i).r;
ptvalue(2,1) = points(i).g;
ptvalue(3,1) = points(i).b;
distclust(j) = norm(double(ptvalue) - double(C_new(:,j)));%存储样本点到聚类的距离;
end
clunum = find(distclust == min(distclust));%样本点距离聚类中心最小的簇类编号;
points(i).cluster = clunum;%标记该样本点类型;
counter(clunum) = counter(clunum) + 1;%样本计数增加一个
cluster(clunum,counter(clunum)).r = mod(i,R);
cluster(clunum,counter(clunum)).c = floor(i/R)+1;
cluster(clunum,counter(clunum)).data = points(i);
end
clusmap = zeros(R,c);
count = 0;
for i = 1:numel(points)
r = mod((i-1),R)+1;
c = ceil(i/R);%一维索引转换为二维索引,按列
if points(i).cluster~=0
clusmap(c,r) = points(i).cluster;
count = count + 1;
end
end
clusmap = clusmap';
stats = regionprops(clusmap);
imshow(clusmap,[]);