实验原理
聚类分析的目标就是在相似的基础上收集数据来分类。聚类源于很多领域,包括数学,计算机科学,统计学,生物学和经济学。
实验数据
实验步骤
- 题目:使用聚类算法进行图片压缩
现在我们获得了一张图片flower.jpg,我们希望使用聚类算法对图像进行压缩,其核心思想是通过聚类将颜色表示数量减少。例如,传统RGB,每个通道0~255(8 bits),则可以表示16777216 (24 bits)种颜色,通过聚类可以减少到16种颜色。- STEP1:完成compress_image函数,该函数实现图片压缩功能,思想是将每个像素作为一个元素进行聚类,然后使用每个类别的质心数值替换原像素数据,以此减少其颜色个数。
该函数参数img是图片传入的接口,因此我们需要知道变量img的数据结构,请自行查看。- 问题一:代码实现,将img结构进行转换即每个像素作为一个元素,使之能符合聚类算法数据输入的要求。完成后创建KMeans聚类模型并进行训练。
- 问题二:代码实现,分别获取每个数据聚类后的label,以及每个label的质心的值cluster_centers_.squeeze。
- 问题三:使用质心的数值代替原数据的label值,那么我们将获得一个新的图像。
提示,使用numpy的choose函数进行进行质心值的代替,reshape函数回复原图片的数据结构,并返回结果。
- STEP2:创建plot_image函数打印图片。
- STEP3:读入图片,设置压缩率,实现压缩。
完整代码
1、导包
import numpy as np
import imageio
from sklearn import cluster
import matplotlib.pyplot as plt
2、定义compress_image函数,压缩图片
# step1
# 定义compress_image函数,压缩图片
def compress_image(img,num_clusters):
X = img.reshape((-1,1))
print("\nX的数据:\n",X)
#创建KMeans聚类模型
kmeans = cluster.KMeans(n_clusters=num_clusters,n_init=4,random_state=5)
kmeans.fit(X)
# 分别获取每个数据聚类后的label,以及每个label的质心
labels = kmeans.labels_
centroids = kmeans.cluster_centers_.squeeze()
# 使用质心的数值代替原始数据的label值,获得一个新图像
# 使用numpy的choose函数进行之心值的代替,reshape函数回复原图片的数据结构
input_image_compressed = np.choose(labels,centroids).reshape(img.shape)
print("\nimage的形状",img.shape)
return input_image_compressed
3、定义函数,打印图片
# step2
# 定义函数,打印图片
def plot_image(img,title):
vmin = img.min()
vmax = img.max()
print("img_vmin:",vmin)
print("img_vmax:",vmax)
plt.figure()
plt.title(title)
# cmap映射
#热图(heatmap)是数据分析的常用方法,
#通过色差、亮度来展示数据的差异、易于理解。
#Python在Matplotlib库中,调用imshow()函数实现热图绘制。
plt.imshow(img,cmap = plt.cm.gray,vmin=vmin,vmax=vmax)
4、主函数
# step3
# 读入图片,设置压缩率,实现压缩
if __name__=='__main__':
#设置图片路径
input_file = r"数据源\flower.jpg"
#设置压缩比
num_bits = 2
if not 1 <= num_bits <=8:
raise TypeError('num_bits应该在[1,8]区间内')
#设置质心个数
num_clusters = np.power(2,num_bits)
#输出压缩比例
compression_rate = round(100*(8.0 - num_bits)/8.0,2)
print ("\nThe size of the image will be reduced by a factor of", 8.0/num_bits)
print ("\nCompression rate = " + str(compression_rate) + "%\n")
#载入图片
input_image = imageio.imread(input_file).astype(np.uint8)
# 调用plot_image函数,输出原始图像
plot_image(input_image, 'Original image')
#归一化,[0,1]之间
input_image = input_image/255
# 调用compress_image函数压缩图像
input_image_compressed = compress_image(input_image, num_clusters)
# 调用plot_image函数,输出压缩后的图像
plot_image(input_image_compressed, 'Compressed image; compression rate = '
+ str(compression_rate) + '%')
plt.show()
运行结果图:
实验问题
问题1、scipy.misc is deprecated and has no attribute imread
解决方案:
(1)安装imageio
!pip install imageio
(2)导包
import imageio
(3)将misc换成imageio
input_image = imageio.imread(input_file).astype(np.uint8)
问题2、Clipping input data to the valid range for imshow with RGB data
解决方案:
(1)对于二维数组(灰度图像),函数会自动将输入数据归一化变换至[0,1],然后显示。
(2)对于三维数组(彩色图像),plt.imshow() 函数并不会自动对输入数据归一化处理,而是对数据取值范围提出要求:如果是float型数据,取值范围应在[0,1];如果是int型数据,取值范围应在[0,255]
归一化处理
input_image = input_image/255