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

2022-07-2220:34:17后端程序开发Comments954 views字数 2361阅读模式

DCT是最原始的图像压缩算法,全称为Discrete Cosine Transform,即离散余弦变换。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

刚好小编之前做过图像、视频处理相关的研发工作,对图像处理比较感兴趣,之前也看过利用聚类进行图片颜色压缩的内容,索性就再回顾一下,分享出来供大家参考学习文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

聚类算法本文不再赘述,不会的同学记住核心思想即可:人以类聚,物以群分。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

《三个印度人改变压缩算法,一意孤行整个暑假,却因“太简单”申不到经费》https://mp.weixin.qq.com/s/l3EPCNlE0Ne3wU5YFQ65dg文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

题外话,三角函数中余弦函数运用的比较多,在计算向量(文本、语音向量化)的相似度,这里的离散余弦变换文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

原始图片,4.47MB文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

本文演示的图片数据,均基于该张图片,故宫.jpg文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

颜色压缩效果文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

4032*3024 行=12192768 行,也就是1219万个像素点、1219万个颜色点
压缩为10个颜色点、128个颜色点文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

图片数据介绍文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

大家都知道一个像素可以表示为R(红色 Red)、G(绿色 Green)、B(蓝色 Blue)三个数值组成,照片是一个颜色矩阵,可以理解为每行由指定的像素点排成一行组成,这样由很多行就组合成了一个图片,千万别被高级名词:三维矩阵吓到。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

 文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

我们可以对该图片颜色矩阵进行变换,转换为我们熟悉的二维矩阵,RGB每个颜色是一个特征列,这个矩阵一共有4032*3024 行=12192768 行,也就是1219万个像素点、1219万个颜色点文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

先放第一行的点,再放第二行的点,以此类推,然后每个点展开为3列,这个就是numpy里面矩阵变换时数据的变化规则文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

变换后结果如下图所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

转换为二维矩阵后,是不是和平时分析的数据样式就一样了,这样就可以用来进行聚类,特征列只有3个,分别为R、G、B文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

确定运用的颜色个数(聚类中簇的个数)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

一共有 4032*3024 行=12192768 行 数据,我们要聚为几类呢?我们可以先大概取一些值,比如聚为2类、3类、5类 等等,然后使用肘部法则,来大概确定一个合适的分类数(簇数)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

利用SSE指标,结合肘部法则,可以确定聚为10类时,比较合适文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

然后用这10类的中心点坐标颜色来还原图片,相当于用10种颜色来对图片进行上色,可以看到图片基本与原图一直,除了天空有锯齿外,图片其他的地方完美显示,这时图片大小为 997KB文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

极端情况,聚类为2种颜色文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

由于原图里面蓝色较多,聚为2类时,除了有蓝色,还有暗棕色文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

 文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

脑洞大开,用黑白色表示

由于上面可以用2种颜色来表示,于是脑洞大开,可以用黑色与白色来试试,效果如下图所示,有点类似手绘风格的图片文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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

完整代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html

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)
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/25818.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/25818.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定