Python 使用聚类算法对图像进行颜色压缩,附上完整代码,
DCT是最原始的图像压缩算法,它的全称是Discrete Cosine Transform,即离散余弦变换。
无独有偶,小编此前做过图像视频处理相关的研发工作,对图像处理更感兴趣。之前也看到过利用聚类来压缩图像颜色,所以简单回顾一下,分享给大家参考和学习。
聚类算法本文不再详细介绍。不知道怎么做的人只要记住核心思想即可:人以群分,物以群分。 ?离散余弦变换
原图,4.47MB
本文展示的图像数据全部基于此图,故宫.jpg故宫
色彩压缩效果4203*420 = 12192768条线,即1219万个像素和1219万个色点 ,所有这些都可以介绍为R表示的图像数据(红色)、G(绿色)和 B(蓝色)。该图像是一个颜色矩阵。可以理解为每一行都是由排成一行的指定像素组成,如此多的行组合起来就可以了,当你得到图像时,不要害怕这个高级术语:三维矩阵。 我们可以对图像颜色矩阵进行变换,将其转换为我们知道的二维矩阵。每个 RGB 颜色都是一个特征列。这个矩阵一共有4032*3024行=12192768行,也就是1219万个像素,1219万个颜色点 先把点放在第一行,然后把点放在第二行,以此类推,然后将每个点展开为 3 列。这是 numpy 矩阵变换时的数据变化规则 变换后的结果如下图: 转换为二维矩阵后,数据风格会不会和平常一样分析?用于聚类,只有3个特征列,分别是R、G、B 确定要使用的颜色数量(簇中簇的数量) 总共有 4032*3024 行 = 12192768 行数据。我们将把它分为多少个类别?我们可以先粗略地取一些值,比如分为2类、3类、5类等,然后利用肘部法则粗略地确定一个合适的类别数(簇数) 使用SSE指数,结合肘部规则,分为10类比较合适 然后使用这10个类别的中心坐标颜色来恢复图像,相当于使用10种颜色对图像进行着色,可以看到图像与原图基本一致。除了锯齿状的天空之外,图像的其他部分都显示得很完美。目前图像大小为 997KB 极端情况下簇为 2 种颜色 因为原始图像中蓝色较多。分成2类的时候,除了蓝色,还有深棕色 上面可以用颜色是有代表性的,所以我的想象力很广阔。你可以尝试一下黑白搭配。效果如下图,有点让人想起手绘风格的图片 完整代码
被压缩为10个色点和128个色点压缩效果
图像颜色矩阵
颜色矩阵变换
确定类别数量
10 个类别
第2类
太有想象力了,用黑白来表达
黑白
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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。