Code前端首页关于Code前端联系我们

Python 使用聚类算法对图像进行颜色压缩,附上完整代码,

terry 2年前 (2023-09-25) 阅读数 54 #后端开发

DCT是最原始的图像压缩算法,它的全称是Discrete Cosine Transform,即离散余弦变换。

无独有偶,小编此前做过图像视频处理相关的研发工作,对图像处理更感兴趣。之前也看到过利用聚类来压缩图像颜色,所以简单回顾一下,分享给大家参考和学习。

聚类算法本文不再详细介绍。不知道怎么做的人只要记住核心思想即可:人以群分,物以群分。 ?离散余弦变换

原图,4.47MB

本文展示的图像数据全部基于此图,故宫.jpgPython 利用聚类算法对图片进行颜色压缩,附完整代码故宫

色彩压缩效果4203*420 = 12192768条线,即1219万个像素和1219万个色点
被压缩为10个色点和128个色点Python 利用聚类算法对图片进行颜色压缩,附完整代码压缩效果

,所有这些都可以介绍为R表示的图像数据(红色)、G(绿色)和 B(蓝色)。该图像是一个颜色矩阵。可以理解为每一行都是由排成一行的指定像素组成,如此多的行组合起来就可以了,当你得到图像时,不要害怕这个高级术语:三维矩阵。

Python 利用聚类算法对图片进行颜色压缩,附完整代码图像颜色矩阵

我们可以对图像颜色矩阵进行变换,将其转换为我们知道的二维矩阵。每个 RGB 颜色都是一个特征列。这个矩阵一共有4032*3024行=12192768行,也就是1219万个像素,1219万个颜色点

先把点放在第一行,然后把点放在第二行,以此类推,然后将每个点展开为 3 列。这是 numpy 矩阵变换时的数据变化规则

变换后的结果如下图: Python 利用聚类算法对图片进行颜色压缩,附完整代码颜色矩阵变换

转换为二维矩阵后,数据风格会不会和平常一样分析?用于聚类,只有3个特征列,分别是R、G、B

确定要使用的颜色数量(簇中簇的数量)

总共有 4032*3024 行 = 12192768 行数据。我们将把它分为多少个类别?我们可以先粗略地取一些值,比如分为2类、3类、5类等,然后利用肘部法则粗略地确定一个合适的类别数(簇数)

使用SSE指数,结合肘部规则,分为10类比较合适Python 利用聚类算法对图片进行颜色压缩,附完整代码确定类别数量

然后使用这10个类别的中心坐标颜色来恢复图像,相当于使用10种颜色对图像进行着色,可以看到图像与原图基本一致。除了锯齿状的天空之外,图像的其他部分都显示得很完美。目前图像大小为 997KBPython 利用聚类算法对图片进行颜色压缩,附完整代码10 个类别

极端情况下簇为 2 种颜色

因为原始图像中蓝色较多。分成2类的时候,除了蓝色,还有深棕色

Python 利用聚类算法对图片进行颜色压缩,附完整代码 第2类

太有想象力了,用黑白来表达

上面可以用颜色是有代表性的,所以我的想象力很广阔。你可以尝试一下黑白搭配。效果如下图,有点让人想起手绘风格的图片Python 利用聚类算法对图片进行颜色压缩,附完整代码黑白

完整代码

from skimage import io
# from sklearn.cluster import KMeans
from sklearn.cluster import MiniBatchKMeans  #提升聚类速度
import numpy as np
import sklearn.metrics as sm
import matplotlib.pyplot as plt

np.set_printoptions(threshold=np.inf)

image = io.imread('故宫.jpg')
io.imshow(image)

data=image/255.0
data=data.reshape(-1,3)

SSE = []
silhouette_score = []
k = []
#簇的数量
colors=[2,3,5,10,16,32,64,128]
for n_clusters in colors:
    cls = MiniBatchKMeans(n_clusters,batch_size=2048).fit(data)
    score1 = cls.inertia_
    SSE.append(score1)

#肘部法则,确定聚类个数
fig, ax1 = plt.subplots(figsize=(10, 6))
 
ax1.scatter(range(1,9), SSE)
ax1.plot(range(1,9), SSE)
ax1.set_xlabel("colors",fontdict={'fontsize':15})
ax1.set_ylabel("SSE",fontdict={'fontsize':15})
ax1.set_xticks(range(1,9))
for i in range(8):
    plt.text(i+1, SSE[i],colors[i])

plt.show()

#运用10个聚类色表示图片
colors_use=10
km = MiniBatchKMeans(colors_use,batch_size=2048) 
km.fit(data)
new_data = km.cluster_centers_[km.predict(data)]   #利用np.array 的整数索引(高级索引知识),用聚类中心点值 代替原来点的值

image_new = new_data.reshape(image.shape)
image_new_convert = np.array(np.round(image_new * 255),dtype='uint8')
io.imsave('colors_use_10.jpg',image_new_convert)

#黑白色表示
new_data =np.array([[255,255,255],[0,0,0]])[kmeans.predict(data)]
image_new = new_data.reshape(image.shape)
image_new_convert = np.array(np.round(image_new * 255),dtype='uint8')
io.imsave('黑白色.jpg',image_new_convert)

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门