一幅多通道图像(RGB,多光谱等)本质是一个三维张量A。A的三个维度是高度(H),宽度(W),通道数(B),可看做B个二维矩阵的集合,每个矩阵是某一个通道(波段)下的灰度图。
实现思路
假设将图像分为k个类别,设置迭代次数为iteration次。主要分为以下四个步骤:
1.统计图像信息
记录图像张量的三个大小参数(HWB),图像中像素点的个数。
2.初始化类别中心
随机在图像中找到k个点作为初始“簇中心”,将每个中心的各个波段数值(DN值)储存在矩阵center中。
矩阵每一行代表了一个簇中心,不同列是各个通道的DN值。
3.计算距离、分类
这里使用欧式距离。对每一个像素点,都应计算其与k个簇中心的欧氏距离,即两者各个波段下DN值之差的平方和(再开根号)。对于每个点,会计算出k个欧氏距离,找出距离最小的那一类,将该点归入其中。
注意这项操作计算的是像素点在光谱空间的距离。这里生成一个W*H的矩阵,按顺序存放每个像素点归属的类别,以便最后可视化。
4.更新簇中心
按上述方法遍历整幅图像后,每一类别下都有了若干个像素点。我们计算每一类下所有点在光谱空间中的平均位置(DN值的平均)。最终每一类可求出一个光谱空间的平均位置点(B维向量),我们将其作为新的簇中心,更新center矩阵。
循环执行步骤3和4,直到达到某一阈值或标准,结束循环。
MATLAB代码
程序运行速度比较慢,900*800的彩色图像,分为5类循环6次,跑了10分钟才完成?
function imkmeans (k,iteration)
A = double(imread('G:\'));
%统计图像信息
[H,W,B] = size(A);
num = H*W;
%初始化类别中心
centerid = zeros(k,2);center = zeros(k,B);
for i = 1:k
centerid(i,:) = [randi(H,1),randi(W,1)];
end
for i = 1:k
for j = 1:B
center(i,j) = A(centerid(i,1) , centerid(i,2) , j);
end
end
%分类(计算距离),d是kk*1的向量.kk=k
class = zeros(H,W);
while iter < iteration
cst = zeros(k,num,B);
for i = 1:H
for j = 1:W
d = zeros(k,1);
for kk = 1:k
for h = 1:B
d(kk) = d(kk) + (A(i,j,h) - center(kk,h))^2;
end
end
classid = find(d == min(d),1);
class(i,j) = classid;
c = 1;
while cst(classid,c,1) ~= 0
c = c + 1;
end
cst(classid,c,:) = A(i,j,:);
end
end
%利用上面的cst矩阵计算各类别的光谱空间平均坐标。
for i = 1:k
for j = 1:B
center(i,B) = sum(cst(i,:,j)) / sum(cst(i,:,j)~=0);
end
end
iter = iter+1;
end
figure
imagesc(class)
使用4个波段,对TM数据进行分类的结果:
参考链接: https://www.cnblogs.com/lliuye/p/9144312.html