【skLearn练习】KMeans矢量量化应用 ---- 压缩图片



一、KMeans矢量量化概念

百度百科: 在这里插入图片描述

k-means聚类最重要的应用之一就是非结构数据(图像、声音)上的矢量量化(VQ),所谓的矢量量化就是将数据进行压缩

非结构化数据往往会占用很大的数据空间,在保证数据质量的同时,尽可能的矢量量化数据的大小,或者是简化非结构化数据的结构。KMeans聚类的本质是一种降维运用,但是他与其他的降维算法思维都不同。比如:特征选择的降维是直接选择贡献最大的特征PCA的降维是聚合信息。而矢量化的降维是指在同等样本量上压缩信息的大小,既不改变特征的数目,也不改变样本的数目,也就是不改变数据的维度,只是改变这些特征下的样本上的信息量

返回顶部


二、图片的探索

① 导库

  • 引入基础numpypandasmatplotlib库,用于基本数据处理
  • 引入load_sample_image库,里面提供了样例图片
# -*- coding: utf-8
#  @Time    : 2021/1/9 8:45
#  @Author  : ZYX
#  @File    : 案例_图片探索.py
# @software: PyCharm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_sample_image # 导入图片数据所用的库

② 实例化导入颐和园图片

  • 查看图片基本数据类型
  • 查看图片数据维度
# 实例化导入颐和园图片
china = load_sample_image("china.jpg")
print(china)
#[[[174 201 231]
#  [174 201 231]
#  [174 201 231]
#  ...
#  [250 251 255]
#  [250 251 255]
#  [250 251 255]]
#  ...
print(china.dtype) # uint8 --- 常见的一种图片数据类型
print(china.shape) # (427, 640, 3) 图片一般是三维数据(长度,宽度,像素)
# 图片形成了427*640个像素点,每个像素点中含有3个特征,由这三个特征所组成的颜色,也就是China的值

(427, 640, 3) 图片形状一般是三维数据(长度,宽度,像素)。图片形成了427*640个像素点,每个像素点中含有3个特征,由这三个特征所组成颜色,也就是China的值。

# 该图片中包含了多少中国种不同的的颜色
newimage = china.reshape(427*640,3)
print(newimage)
#[[174 201 231]
# [174 201 231]
# [174 201 231]
# ...
# [ 43  49  39]
# [ 13  21   6]
# [ 15  24   7]]
  ...
df = pd.DataFrame(newimage)
print(df.shape) # (273280, 3) 共有27万多个像素块
df.drop_duplicates(inplace=True)
print(df.shape) # (96615, 3)  只有9万多种颜色

可以看出,虽然这张图片由27万多个像素块组成,但是真正只有9万多种颜色。

返回顶部


③ 可视化图片

# 可视化图片
plt.figure(figsize=(15,15))
plt.imshow(china) # 导入三维数组形成的图片
plt.show()

在这里插入图片描述
返回顶部


三、图片矢量量化

图像探索完毕,我们了解了,图像现在有9W多种颜色。我们希望来试试看,能否使用K-Means将颜色压缩到64种,还不严重损耗图像的质量。为此,我们要使用k-Means来将9W种颜色聚类成64类,然后使用64个簇的质心来替代全部的9W种颜色,记得质心有着这样的性质:簇中的点都是离质心最近的样本点。

为了比较,我们还要画出随机压缩到64种颜色的矢量量化图像。我们需要随机选取64样本点作为随机质心,计算原数据中每个样本到它们的距离来找出离每个样本最近的随机质心,然后用每个样本所对应的随机质心来替换原本的样本。两种状况下,我们观察图像可视化之后的状况,以查看图片信息的损失。

在这之前,我们需要把数据处理成 sklearnMeans中的-类能够接受的数据 — KMeans不接受三维数据作为特征矩阵

① 导包

  • sklearn.metrics.pairwise_distances_argmin 对两个序列中的点进行距离匹配的函数
  • sklearn.datasets.load_sample_image 导入图片数据所用的库
  • sklearn.utils.shuffle 打乱一个有序的序列的函数 ( 洗牌)
# -*- coding: utf-8
#  @Time    : 2021/1/9 9:34
#  @Author  : ZYX
#  @File    : 案例_图片压缩.py
# @software: PyCharm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin # 对两个序列中的点进行距离匹配的函数
from sklearn.datasets import load_sample_image # 导入图片数据所用的库
from sklearn.utils import shuffle # 打乱一个有序的序列的函数 # 洗牌

② 预处理图像数据,适应SKlearn聚合

  • 数据及归一化处理
  • 提取图像格式,便于还原
  • 改变数据维度
# 1.指定簇数
n_cluster = 64
# 2.加载图片
china = load_sample_image("china.jpg")
# plt.imgshow在浮点数上表现优异,在这里对China数据进行转化,并且归一化处理
# 3.归一化处理图片数据
china = np.array(china,dtype=np.float64)/china.max()
# 4.提取图像格式
w,h,d = original_shape = tuple(china.shape)
# 在这里要确保每个像素块是由3个特征组成的 --- rgb三原色
# assert相当于 raise error if not,表示“不为true就报错”
assert d == 3
# 5.改变图片数据结构以适应KMeans
image_reshape_data = np.reshape(china,(w*h,d))

③ KMeans聚类

  • 聚类统计出质心
  • 预测出图片数据集的标签
# 6.数据集过于庞大,先随机抽取1000条进行KMeans聚类,再使用得到的质心去预测整体数据集
sample_data = shuffle(image_reshape_data,random_state=0)[:1000]
k_means = KMeans(n_clusters=n_cluster,random_state=0).fit(sample_data)
# 7.得出质心
centers = k_means.cluster_centers_
print(k_means.cluster_centers_.shape) # (64, 3)
# 8.按照质心预测整体数据集
# labels代表了27万个样本点所对应的簇的质心的索引
labels = k_means.predict(image_reshape_data)
print(labels.shape) # (273280,)

④ 质心替换样本,实现矢量量化

  • 使用质心替换所有的样本
  • 检验
  • 恢复图片数据格式,便于可视化
# 9.使用质心替换所有的样本
image_kmeans = image_reshape_data.copy()
# 10.遍历替换质心数
for i in range(w*h):
    image_kmeans[i] = centers[labels[i]]
# 检验是否替换成功
print(pd.DataFrame(image_kmeans).drop_duplicates().shape) # (64, 3)

# 11.查看矢量量化后的图像
# 11.1 恢复图片结构
image_kmeans = image_kmeans.reshape(w,h,d)
print(image_kmeans.shape) # (427, 640, 3)

⑤ 随机的矢量量化

  • 函数pairwise_distances_argmin(x1,x2,axis) 用来计算x2中的每个样本到x1中的每个样本点的距离,并返回和x2相同形状的,x1中对应的最近的样本点的对应聚类数
'''
随机的矢量量化
'''
# 1.产生随机质心
centroid_random = shuffle(image_reshape_data, random_state=0)[:n_cluster]
print(centroid_random)
# [[0.92156863 0.9254902  0.94509804]
#  [0.37647059 0.37647059 0.14117647]
#   .........
#  [0.40784314 0.48235294 0.12941176]
#  [0.81568627 0.86666667 0.8       ]]

#函数pairwise_distances_argmin(x1,x2,axis)
# 2.用来计算x2中的每个样本到x1中的每个样本点的距离,并返回和x2相同形状的,x1中对应的最近的样本点的对应聚类数
labels_random = pairwise_distances_argmin(centroid_random, image_reshape_data, axis=0)
print(labels_random)  # [55 55 55 ... 52 60 60]
print(labels_random.shape) # (273280,)
print(len(set(labels_random))) # 64

# 3.使用随机质心来替换所有样本
image_random = image_reshape_data. copy()
print(image_random)
# [[0.68235294 0.78823529 0.90588235]
#  [0.68235294 0.78823529 0.90588235]
#  [0.68235294 0.78823529 0.90588235]
#  ...
#  [0.16862745 0.19215686 0.15294118]
#  [0.05098039 0.08235294 0.02352941]
#  [0.05882353 0.09411765 0.02745098]]
for i in range(w*h):
   image_random[i] = centroid_random [labels_random[i]]
# 4.恢复图片的结构
image_random= image_random.reshape(w,h,d)
print(image_random.shape)

⑥ 可视化

plt. figure(figsize=(10,10))
plt. axis('off')
plt. title('Original image (96, 615 colors)')
plt. imshow(china)

plt. figure(figsize=(10,10))
plt. axis('off')
plt. title('Quantized image (64 colors, K-Means)')
plt. imshow(image_kmeans)

plt. figure(figsize=(10,10))
plt. axis('off')
plt. title('Quantized image (64 colors, Random)')
plt. imshow(image_random)

plt. show()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过结果的展示,可以很明显的看出在矢量量化后的照片之间的区别,相比于随机矢量量化,KMeans矢量量化效果明显好,经过随机量化的图片,不管在清晰度、还是在色彩上都有了非常明显的损失。

返回顶部


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑着蜗牛ひ追导弹'

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值