github数据集: 智能算法的课件和参考资料以及实验代码
我们可以用k-means算法将灰度图分成N个梯度
我们知道,一般的彩色图像指的是在RGB颜色空间下的图像,这样的图像三个通道分别是R(red)G(green)B(blue)。而灰度图指的是单通道的,将三通道的图像转为单通道常用方法有YUV法和平均法。
如何将一幅彩色图像转换为灰度图呢?根据人眼对红绿蓝三色的敏感程度,可以使用以下方式进行转换:
Gray = R*0.299+G*0.587+B*0.114
这也是最常用的一种转换,另外还有一种常用的转换叫平均值法,即取去红绿蓝三色的平均值为灰度:
Gray=(R+G+B)/3;
下面使用K-means算法将lenna256.bmp图像聚类成N类来处理:
close all
clear all
clc
I=imread('lenna256.bmp'); % 从指定的文件名(这里是相对目录,即当前程序所在目录)读取图像
I=im2double(I); % 把灰度图像的数据类型转换成双精度浮点数类型
J=zeros(size(I)); % 256*256 8位的灰度图
N=4; % 聚类成N类
[m,n]=size(I); % m=256,n=256
center=zeros(1,N);
% 下面初始化簇中心,有N个簇中心
for i=1:N
mrand1=randi(m);
nrand1=randi(n);
center(1,i)=I(mrand1,nrand1);
end
label=zeros(m,n);
s=zeros(1,N);
num=zeros(1,N);
newcenter=zeros(1,N);
th=0.01;
while 1
distance=zeros(1,N);
for i=1:m
for j=1:n
for x=1:N
distance(x)=abs(I(i,j)-center(1,x));% 一维距离,直接相差取绝对值
end
[~,temp]=min(distance);
label(i,j)=temp; % 第i行j列的样本属于temp类别
end
end
for i=1:m
for j=1:n
% 求第i,j个样本到N个簇中心的平均距离
for x=1:N
if(label(i,j)==x)
s(1,x)=s(1,x)+I(i,j);
num(1,x)=num(1,x)+1; % 计算每个类别的样本数量
end
end
end
end
% 计算新的N个簇的中心
for x=1:N
newcenter(1,x)=s(1,x)/num(1,x);
end
% 当簇中心变化很小时收敛
if(abs(min(newcenter)-min(center))<th)
break;
else
center=newcenter;
end
end
for i=1:m
for j=1:n
for x=1:N
if(label(i,j)==x)
J(i,j)=center(x)*255; % 将样本划分到所属类别中
end
end
end
end
figure,
subplot(1,2,1),imshow(I); % 将图像窗口分成1行2列,并在第一个子窗口显示图像img
subplot(1,2,2),imshow(uint8(J)); % 同上,只不过换成在第二个子窗口显示img
% 注意:
% subplot(1,2,2),imshow(J); 会得到白色图像
% 可以使用subplot(1,2,2),imshow(J/255);
注意imshow的使用:
matlab中显示图像的语句是:
imshow(img)
imshow(img,[low high])
其中,[low high]用于指定图像显示的灰度范围,图像中灰度值等于或低于low的都将用显示为黑色,灰度值等于或大于high的都显示为白色。如果你用空矩阵[]来代替 [low high], imshow 函数将使用 [min(img(:))max(img(:))]作为第二个参数。
在某些需要保证精度的场合,我们可能会将图像数据保存为double型,此时运行 imshow(img)会得到一张空白的图。
这是因为imshow()显示图像时对double型是认为在0-1范围内,即大于1时都是显示为白色,而imshow()显示uint8型时是0-255范围。
解决办法就是调整图像的数据区间或调整显示的区间:
方法一: imshow(img/256); -----------将图像矩阵转化到0-1之间。
方法二: imshow(I,[]); -----------将显示区间转换到 min(img(:)) 到max(img(:))之间
分成四类结果如下: