在Python中使用K-Means聚类和PCA主成分分析进行图像压缩(一)

简介: 在Python中使用K-Means聚类和PCA主成分分析进行图像压缩(一)

各位读者好,在这片文章中我们尝试使用sklearn库比较k-means聚类算法和主成分分析(PCA)在图像压缩上的实现和结果。压缩图像的效果通过占用的减少比例以及和原始图像的差异大小来评估。图像压缩的目的是在保持与原始图像的相似性的同时,使图像占用的空间尽可能地减小,这由图像的差异百分比表示。图像压缩需要几个Python库,如下所示:

# image processing
from PIL import Image
from io import BytesIO
import webcolors
# data analysis
import math
import numpy as np
import pandas as pd
# visualization
import matplotlib.pyplot as plt
from importlib import reload
from mpl_toolkits import mplot3d
import seaborn as sns
# modeling
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import MinMaxScaler

探索图像

640.png

每个颜色通道的图像图像中的每个像素都可以表示为三个0到255之间的8位无符号(正)整数,或缩放为三个0到1之间的无符号(正)浮点数。这三个值分别指定红色,绿色,蓝色的强度值,这通常称为RGB编码。在此文章中,我们使用了220 x 220像素的lena.png,这是在图像处理领域广泛使用的标准测试图像。

ori_img = Image.open("images/lena.png")
ori_img

640.png


原始图像

X = np.array(ori_img.getdata())
ori_pixels = X.reshape(*ori_img.size, -1)
ori_pixels.shape

图像储存方式是形状为(220、220、3)的3D矩阵。前两个值指定图像的宽度和高度,最后一个值指定RBG编码。让我们确定图像的其他属性,即图像大小(以千字节(KB)为单位)和原色的数量。

def imageByteSize(img):
     img_file = BytesIO()
     image = Image.fromarray(np.uint8(img))
     image.save(img_file, 'png')
     return img_file.tell()/1024
ori_img_size = imageByteSize(ori_img)
ori_img_n_colors = len(set(ori_img.getdata()))

 

lena.png的原始图像大小为86 KB,并具有37270种独特的颜色。因此,我们可以说lena.png中的两个像素具有相同的精确RGB值的可能性很小。

接下来,让我们计算图像的差异作为压缩结果的基准。

640.png

ori_img_total_variance = sum(np.linalg.norm(X - np.mean(X, axis = 0), axis = 1)**2)

我们得到方差为302426700.6427498。但是我们无法解释方差本身的价值。我们稍后将在K-Means聚类中使用它。


k-means聚类

640.png

具有三个聚类中心的二维k-means聚类图像

算法

k-means聚类是一种常用的无监督学习算法,用于将数据集划分为k个聚类中心,其中k必须由用户预先指定。该算法的目标是将现有数据点分类为几个集群,以便:

  1. 同一集群中的数据尽可能相似
  2. 来自不同集群的数据尽可能不同

每个集群由聚类中心表示,聚类中心是聚类数据点的平均值。这是算法:

  1. 用户指定集群数k
  2. 从数据集中随机选择k个不同的点作为初始聚类中心
  3. 将每个数据点分配给最近的聚类中心,通常使用欧几里得距离
  4. 通过取属于该集群的所有数据点的平均值来计算新聚类中心
  5. 重复步骤3和4,直到收敛为止,即聚类中心位置不变

请注意,结果可能并不理想,因为它取决于随机的初始化。

理念

我们的原始图像包含数千种颜色。我们将利用K-Means聚类算法来减少颜色数量,因此它仅需要存储一定数量的RGB值。我们将减小图像尺寸使其更有效率地进行储存。我们可以将像素值视为具有(宽度×高度)观察值和3个与RGB值相对应的特征的数据帧。对于lena.png,我们将具有220×220(48400)个观测值和3个特征。

因此,我们可以可视化三维图中的每个像素。这是前220个像素,代表原始图像中的第一行像素。

640.png

像素值的三维图

简单的例子

在我们对颜色数k使用各种值进行迭代之前,让我们使用k = 2来了解我们的目的。到本节末,我们希望图像只有2种颜色。首先,我们创建一个KMeans对象,该对象适合我们的原始像素X。

kmeans = KMeans(n_clusters = 2,
                 n_jobs = -1,
                 random_state = 123).fit(X)
kmeans_df = pd.DataFrame(kmeans.cluster_centers_, columns = ['Red', 'Green', 'Blue'])


然后我们将RGB值转换为其英文颜色名称:

def closest_colour(requested_colour):
     min_colours = {}
     for key, name in webcolors.CSS3_HEX_TO_NAMES.items():
         r_c, g_c, b_c = webcolors.hex_to_rgb(key)
         rd = (r_c - requested_colour[0]) ** 2
         gd = (g_c - requested_colour[1]) ** 2
         bd = (b_c - requested_colour[2]) ** 2
         min_colours[(rd + gd + bd)] = name
     return min_colours[min(min_colours.keys())]
def get_colour_name(requested_colour):
     try:
         closest_name = actual_name = webcolors.rgb_to_name(requested_colour)
     except ValueError:
         closest_name = closest_colour(requested_colour)
     return closest_name
kmeans_df["Color Name"] = list(map(get_colour_name, np.uint8(kmeans.cluster_centers_)))
kmeans_df


当我们指定2为n_clusters参数值时,我们得到两个聚类中心。下一步,我们可以通过聚类中心来表示该群集中的每个像素值。因此,在压缩图像中将只有两个像素值。

def replaceWithCentroid(kmeans):
     new_pixels = []
     for label in kmeans.labels_:
         pixel_as_centroid = list(kmeans.cluster_centers_[label])
         new_pixels.append(pixel_as_centroid)
     new_pixels = np.array(new_pixels).reshape(*ori_img.size, -1)
     return new_pixels
new_pixels = replaceWithCentroid(kmeans)


我们的聚类步骤已经完成,让我们看一下压缩图像的结果。

def plotImage(img_array, size):
     reload(plt)
     plt.imshow(np.array(img_array/255).reshape(*size))
     plt.axis('off')
     return plt
plotImage(new_pixels, new_pixels.shape).show()

640.png

只有两种颜色的压缩图片

K-Means仅使用两种颜色成功地保留了lena.png的形状。在视觉上,我们可以比较原始图像相似与压缩图像是否相似。但是,我们如何用程序做到这一点?让我们介绍一组评估压缩图像的指标:

  1. 在群集平方和(WCSS)中,测量群集中所有点与其群集中心的欧几里德距离平方的总和。
  2. 在群集的平方和(BCSS)之间,测量所有聚类中心之间的欧几里得距离平方的总和。
  3. 解释方差,衡量压缩图像效果可以通过压缩图像解释原始图像的百分比。如果将每个像素视为一个单独的群集,则WCSS等于0。因此,Exparined Variance = 100%。
  4. 图像大小,以千字节为单位,以评估缩小/压缩性能。
def calculateBCSS(X, kmeans):
     _, label_counts = np.unique(kmeans.labels_, return_counts = True)
     diff_cluster_sq = np.linalg.norm(kmeans.cluster_centers_ - np.mean(X, axis = 0), axis = 1)**2
     return sum(label_counts * diff_cluster_sq)
WCSS = kmeans.inertia_
BCSS = calculateBCSS(X, kmeans)
exp_var = 100*BCSS/(WCSS + BCSS)
print("WCSS: {}".format(WCSS))
print("BCSS: {}".format(BCSS))
print("Explained Variance: {:.3f}%".format(exp_var))
print("Image Size: {:.3f} KB".format(imageByteSize(new_pixels)))

WCSS: 109260691.314189BCSS: 193071692.34763986Explained Variance: 63.861%Image Size: 4.384 KB

图像大小从86 KB大幅下降到4.384 KB,但是要注意的是,压缩图像解释原始图像的能力达到63.861%。我们期望比这更高的解释方差百分比。接下来,我们将重复上述过程并改变𝑘来实现此目标。

目录
相关文章
|
2月前
|
缓存 Rust 算法
从混沌到秩序:Python的依赖管理工具分析
Python 的依赖管理工具一直没有标准化,主要原因包括历史发展的随意性、社区的分散性、多样化的使用场景、向后兼容性的挑战、缺乏统一治理以及生态系统的快速变化。依赖管理工具用于处理项目中的依赖关系,确保不同环境下的依赖项一致性,避免软件故障和兼容性问题。常用的 Python 依赖管理工具如 pip、venv、pip-tools、Pipenv、Poetry 等各有优缺点,选择时需根据项目需求权衡。新工具如 uv 和 Pixi 在性能和功能上有所改进,值得考虑。
93 35
|
2月前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python实现基于矩阵分解的长期事件(MFLEs)时间序列分析
在现代数据分析中,高维时间序列数据的处理和预测极具挑战性。基于矩阵分解的长期事件(MFLEs)分析技术应运而生,通过降维和时间序列特性结合,有效应对大规模数据。MFLE利用矩阵分解提取潜在特征,降低计算复杂度,过滤噪声,并发现主要模式。相比传统方法如ARIMA和深度学习模型如LSTM,MFLE在多变量处理、计算效率和可解释性上更具优势。通过合理应用MFLE,可在物联网、金融等领域获得良好分析效果。
74 0
使用Python实现基于矩阵分解的长期事件(MFLEs)时间序列分析
|
2月前
|
数据采集 数据可视化 数据挖掘
金融波动率的多模型建模研究:GARCH族与HAR模型的Python实现与对比分析
本文探讨了金融资产波动率建模中的三种主流方法:GARCH、GJR-GARCH和HAR模型,基于SPY的实际交易数据进行实证分析。GARCH模型捕捉波动率聚类特征,GJR-GARCH引入杠杆效应,HAR整合多时间尺度波动率信息。通过Python实现模型估计与性能比较,展示了各模型在风险管理、衍生品定价等领域的应用优势。
317 66
金融波动率的多模型建模研究:GARCH族与HAR模型的Python实现与对比分析
|
18天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【蘑菇识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
蘑菇识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了9种常见的蘑菇种类数据集【"香菇(Agaricus)", "毒鹅膏菌(Amanita)", "牛肝菌(Boletus)", "网状菌(Cortinarius)", "毒镰孢(Entoloma)", "湿孢菌(Hygrocybe)", "乳菇(Lactarius)", "红菇(Russula)", "松茸(Suillus)"】 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,
75 11
基于Python深度学习的【蘑菇识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
|
2月前
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
133 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
2月前
|
数据可视化 算法 数据挖掘
Python时间序列分析工具Aeon使用指南
**Aeon** 是一个遵循 scikit-learn API 风格的开源 Python 库,专注于时间序列处理。它提供了分类、回归、聚类、预测建模和数据预处理等功能模块,支持多种算法和自定义距离度量。Aeon 活跃开发并持续更新至2024年,与 pandas 1.4.0 版本兼容,内置可视化工具,适合数据探索和基础分析任务。尽管在高级功能和性能优化方面有提升空间,但其简洁的 API 和完整的基础功能使其成为时间序列分析的有效工具。
87 37
Python时间序列分析工具Aeon使用指南
|
2月前
|
机器学习/深度学习 运维 数据可视化
Python时间序列分析:使用TSFresh进行自动化特征提取
TSFresh 是一个专门用于时间序列数据特征自动提取的框架,支持分类、回归和异常检测等机器学习任务。它通过自动化特征工程流程,处理数百个统计特征(如均值、方差、自相关性等),并通过假设检验筛选显著特征,提升分析效率。TSFresh 支持单变量和多变量时间序列数据,能够与 scikit-learn 等库无缝集成,适用于大规模时间序列数据的特征提取与模型训练。其工作流程包括数据格式转换、特征提取和选择,并提供可视化工具帮助理解特征分布及与目标变量的关系。
93 16
Python时间序列分析:使用TSFresh进行自动化特征提取
|
18天前
|
监控 算法 安全
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
35 10
|
2月前
|
数据采集 缓存 API
python爬取Boss直聘,分析北京招聘市场
本文介绍了如何使用Python爬虫技术从Boss直聘平台上获取深圳地区的招聘数据,并进行数据分析,以帮助求职者更好地了解市场动态和职位需求。
|
3月前
|
数据可视化 算法 数据挖掘
Python量化投资实践:基于蒙特卡洛模拟的投资组合风险建模与分析
蒙特卡洛模拟是一种利用重复随机抽样解决确定性问题的计算方法,广泛应用于金融领域的不确定性建模和风险评估。本文介绍如何使用Python和EODHD API获取历史交易数据,通过模拟生成未来价格路径,分析投资风险与收益,包括VaR和CVaR计算,以辅助投资者制定合理决策。
143 15

热门文章

最新文章