k-means 算法因为简单易实现,所以有许多应用。其中一个有意思是应用于有损图像压缩。其核心思想是通过聚类将颜色表示数量减少。例如,传统RGB,每个通道0~255(8 bits),则可以表示16777216 (24 bits)种颜色,通过聚类可以减少到16种颜色。下面以此为例,比较一下原始图像与压缩图像。
迭代次数 50 次,聚类数目 16。
图像来源:http://cs229.stanford.edu/ps/ps3/mandrill-large.tiff
可见颜色减少了很多,图像变得没那么细腻了。
原始图像:
压缩图像:
matlab 代码如下:
A = double(imread('mandrill-large.tiff'));
[M, N, V] = size(A);
% Training param
numIter = 50; % 迭代次数
K = 16; % 聚类数
m = M*N; % 样本数
% reshape to X, y
y = 1 : M*N; % 聚类结果
X = reshape(A, M*N, V); % 样本
% Init centroids (choose 16 sample randomly).
cen = X(randperm(M*N, K), :);
% k-means 迭代
for t = 1:numIter
% 为每个样本选择一个质心。
for i = 1:m
y(i) = nearest(X(i,:), cen); % 最近的质心(欧式距离,请自定义)
end
% 更新所有质心。
for j = 1:K
cluster = X(y == j, :);
cen(j,:) = sum(cluster, 1) / size(cluster, 1);
end
end
% 聚类量化
Z = X;
for i = 1:m
Z(i, :) = cen(y(i), :);
end
B = reshape(Z, M, N, V);
imshow(uint8(round(B)));
figure();
imshow(uint8(round(A)));