K均值图像压缩

xiaoxiao2021-02-28  59

使用K均值来减少一张图片的颜色种类,既能压缩图片,也能保留图片的特征!

主要步骤:

1、选取聚类中心的数量(即压缩后图片的颜色种类)

聚类中心是一个1×3的矩阵,3指的是通道数(通常为RGB三通道)。

2、计算每个像素点到聚类中心的距离(像素点之间的差距)

每张图片的每个像素都有一个像素值,三通道需要分开计算,然后求平均。这里使用的是欧氏距离:

通道1:d1 = ( pic[i][0] - centre[j][0] )^2

通道2:d2 = ( pic[i][1] - centre[j][1] )^2

通道3:d3 = ( pic[i][2] - centre[j][2] )^2

Distance = ( d1 + d2 + d3 ) / 3

3、将像素点归入最近的聚类中心

假设 Distance[i] 为像素点 i 到每个聚类中心的距离的集合,则类别 x = argmin( Distance[i] )。

4、得到新的聚类中心

把归入每个聚类中心的像素点求平均,平均值即为新的聚类中心,同样3通道要分开!

5、重复上述步骤直到聚类中心不变

具体代码(Python3):

import numpy as np from matplotlib import pyplot as plt from matplotlib import image as img import random pic = img.imread('Kaer.png') #Original Picture plt.figure() plt.imshow(pic) plt.axis('off') plt.title('Original Picture') k = 16 #The number of cluster centroids data = pic.reshape(pic.shape[0]**2,3) #3 means RGB '''Create empty list to store the points''' list = [] for i in range(k): list.append([]) '''Compute min distance''' def Min_distance(centre,rgb): min_distance = 1.0e+10 for i in range(len(centre)): distance = ((centre[i][0]-rgb[0])**2+(centre[i][1]-rgb[1])**2+(centre[i][2]-rgb[2])**2)/3 if distance < min_distance: min_distance = distance c_i = i return c_i '''Random Initialization''' centroid = [] rnd = random.sample(range(0,data.shape[0]+1),k) for i in rnd: centroid.append(data[i,:]) '''K-means Algorithm''' while True: centroid_1 = centroid for i in range(k): list[i].clear() #cluster points to the centroids for i in range(data.shape[0]): c_i = Min_distance(centroid,data[i,:]) #c_i represents the index in centroid list[c_i].append(i) centroid.clear() #find new centroids for i in range(k): sum = np.array([0.0, 0.0, 0.0]) for j in list[i]: sum += data[j,:] mean = sum/len(list[i]) centroid.append(mean) if centroid == centroid_1: #cluster centroid doesn't change break '''Draw the picture''' #replace the pixels for i in range(k): for j in list[i]: data[j,:] = centroid[i] #Processed Picture new_pic = data.reshape(int(data.shape[0]**0.5),int(data.shape[0]**0.5),3) plt.figure() plt.imshow(new_pic) plt.axis('off') plt.title('Processed Picture') plt.show()

最后的效果是:

上面是用16种颜色代替原图的效果!

然后两张图的大小分别是:

转载请注明原文地址: https://www.6miu.com/read-2622380.html

最新回复(0)