【Python】基于动态规划和K聚类的彩色图片压缩算法

news2024/10/7 0:03:48
description

引言

当想要压缩一张彩色图像时,彩色图像通常由数百万个颜色值组成,每个颜色值都由红、绿、蓝三个分量组成。因此,如果我们直接对图像的每个像素进行编码,会导致非常大的数据量。为了减少数据量,我们可以尝试减少颜色的数量,从而降低存储需求。

1.主要原理

(一)颜色聚类(Color Clustering):

首先,使用 KMeans 聚类算法将图像中的颜色值聚类为较少数量的颜色簇。聚类的数量由 n_clusters 参数指定。每个像素被归类到与其最接近的聚类中心所代表的颜色簇。颜色聚类的过程大致如下:

  1. 图像转换: 首先,彩色图像被转换为一个包含所有像素颜色值的数据集。每个像素的颜色通常由红、绿、蓝三个分量组成,因此数据集中的每个样本都是一个三维向量,表示一个像素的颜色。
  2. 选择聚类数量: 在应用 KMeans 算法之前,需要确定聚类的数量。这个数量通常由用户指定,通过参数 n_clusters 控制。
  3. 应用 KMeans 算法: 将 KMeans 算法应用于颜色数据集,将颜色值聚类为指定数量的簇。每个簇的质心代表了该簇的平均颜色。
  4. 像素映射: 每个像素的颜色被映射到最接近的簇的质心所代表的颜色。这样,整个图像被转换为由较少数量的颜色值表示的压缩图像。

通过颜色聚类,彩色图像的颜色数量得以减少,从而实现了数据的压缩。压缩后的图像仍然能够保持视觉上的相似性,同时大大降低了存储空间的需求。

(二)动态规划量化(Dynamic Programming Quantization):

接下来,通过动态规划量化算法对颜色进行压缩。这个算法会进一步减少颜色的数量,并尽可能保持图像的质量。参数 max_colors 指定了压缩后图像中的最大颜色数量。算法会尽量选择与原始图像相似的颜色进行保留,以最大程度地保持图像的质量。而在这部分动态规划量化过程大致如下:

  1. 初始化: 首先,初始化状态数组,表示不同颜色数量下的最优颜色组合。通常,初始状态可以是一个空数组或者包含少量颜色的数组。
  2. 状态转移: 根据动态规划的思想,从初始状态开始逐步扩展,计算每个状态下的最优颜色组合。这个过程通常涉及到对每种可能的颜色组合进行评估,并根据优化准则选择最优的组合。
  3. 选择最优解: 最终,选择最优的颜色组合作为压缩后的图像的颜色集合。这个颜色集合将用于替换原始图像中的颜色,从而实现图像的压缩。
  4. 压缩数据保存: 压缩后的图像数据以及相关信息(如原始图像的尺寸、选择的颜色集合等)被保存为 NumPy 数组,并通过 np.savez_compressed() 函数保存到指定路径。

通过动态规划量化,我们能够选择一组颜色,使得压缩后的图像在尽可能减少颜色数量的情况下,仍然能够保持与原始图像相似的视觉效果。这样就实现了对图像数据的进一步压缩。

(三)压缩数据保存:

压缩后的图像数据以及相关信息(如原始图像的尺寸、聚类数、最大颜色数、聚类中心颜色等)被保存为 NumPy 数组,并通过 np.savez_compressed() 函数保存到指定路径。

(四)解压缩过程:

解压缩过程与压缩过程相反。首先加载压缩后的图像数据,然后根据聚类中心颜色替换像素颜色,最后将重构后的图像数据重塑为原始形状,并恢复图像的原始尺寸。

2.彩色图像压缩类

(一)类结构介绍

将上面所述的一个彩色图像的压缩功能整合为一个名为’ColorfulImageCompressor’的类,在这个类中有四个函数,它们的函数名称、接受参数以及介绍如下:

ColorfulImageCompressor类

  • __init__(self, n_clusters, max_colors, resize_factor=0.5): 初始化彩色图像压缩器对象。
  • compress(self, image_path, compressed_file_path): 压缩彩色图像并保存到指定路径。
  • decompress(self, compressed_file_path): 解压缩彩色图像并返回解压缩后的图像对象。
  • _dynamic_programming_quantization(self, image_array): 动态规划量化,将彩色图像颜色量化为指定数量的颜色。

(二)初始化参数

在创建一个彩色图像压缩类的时候需要传入以下三个参数,进行参数的初始化。

  • n_clusters:聚类数,用于 KMeans 算法,指定图像中的颜色数量。
  • max_colors:最大颜色数,用于动态规划量化,指定压缩后图像中的最大颜色数量。
  • resize_factor:缩放因子,用于调整图像尺寸,默认为 0.5,表示将图像尺寸缩小到原始的一半。

(三)函数介绍

(1)compress(self, image_path, compressed_file_path)
  1. 介绍:
    该函数的作用是压缩彩色图像并保存到指定路径。

  2. 参数:
    image_path:原始图像文件路径。
    compressed_file_path:压缩后的图像文件路径。

  3. 函数体:

    def compress(self, image_path, compressed_file_path):
        """
        压缩彩色图像并保存到指定路径。

        参数:
        - image_path:原始图像文件路径。
        - compressed_file_path:压缩后的图像文件路径。
        """
        # 打开图像并转换为 RGB 模式
        image = Image.open(image_path)
        image = image.convert('RGB')

        # 根据缩放因子调整图像大小
        new_size = (int(image.width * self.resize_factor), int(image.height * self.resize_factor))
        image = image.resize(new_size)

        # 将图像转换为 NumPy 数组并重塑为二维数组
        np_image = np.array(image)
        original_shape = np_image.shape
        np_image = np_image.reshape(-1, 3)

        # 使用动态规划量化对图像进行压缩
        compressed_data = self._dynamic_programming_quantization(np_image)

        # 保存压缩后的图像数据到指定路径
        np.savez_compressed(compressed_file_path, np_image=compressed_data['np_image'], original_shape=original_shape, n_clusters=self.n_clusters, max_colors=self.max_colors, center_colors=compressed_data['center_colors'])
(2)decompress(self, compressed_file_path)
  1. 介绍:
    解压缩彩色图像并返回解压缩后的图像对象。
  2. 参数:
    compressed_file_path:压缩后的图像文件路径。
    返回:
    reconstructed_image:解压缩后的图像对象。
  3. 函数体:
    def decompress(self, compressed_file_path):
        """
        解压缩彩色图像并返回解压缩后的图像对象。

        参数:
        - compressed_file_path:压缩后的图像文件路径。

        返回:
        - reconstructed_image:解压缩后的图像对象。
        """
        # 加载压缩后的图像数据
        compressed_data = np.load(compressed_file_path)
        np_image = compressed_data['np_image'].reshape(-1, 3)
        center_colors = compressed_data['center_colors']

        # 根据聚类中心替换像素颜色
        for i in range(self.n_clusters):
            np_image[np_image[:, 0] == i] = center_colors[i]

        # 将重构后的图像数据重塑为原始形状
        original_shape = compressed_data['original_shape']
        reconstructed_image = np_image.reshape(*original_shape).astype('uint8')
        reconstructed_image = Image.fromarray(reconstructed_image, 'RGB')

        # 恢复图像原始尺寸
        original_size = (int(reconstructed_image.width / self.resize_factor), int(reconstructed_image.height / self.resize_factor))
        reconstructed_image = reconstructed_image.resize(original_size)

        return reconstructed_image
(3)_dynamic_programming_quantization(self, image_array)
  1. 介绍:
    动态规划量化,将彩色图像颜色量化为指定数量的颜色。
  2. 参数:
    image_array:图像数据的 NumPy 数组表示。
    返回:
    compressed_data:包含压缩后图像数据及相关信息的字典。
  3. 函数体:
    def _dynamic_programming_quantization(self, image_array):
        """
        动态规划量化,将彩色图像颜色量化为指定数量的颜色。

        参数:
        - image_array:图像数据的 NumPy 数组表示。

        返回:
        - compressed_data:包含压缩后图像数据及相关信息的字典。
        """
        # 使用 KMeans 进行聚类
        kmeans = KMeans(n_clusters=self.n_clusters)
        labels = kmeans.fit_predict(image_array)
        quantized_image = np.zeros_like(image_array)

        # 遍历每个聚类簇
        for i in range(self.n_clusters):
            # 获取当前簇的像素颜色及其出现次数
            cluster_pixels = image_array[labels == i]
            unique_colors, color_counts = np.unique(cluster_pixels, axis=0, return_counts=True)
            
            # 选取出现次数最多的前 max_colors 个颜色作为量化后的颜色
            color_indices = np.argsort(color_counts)[::-1][:self.max_colors]
            quantized_colors = unique_colors[color_indices]

            # 计算聚类中像素与量化后颜色的距离
            distances = np.linalg.norm(cluster_pixels[:, None] - quantized_colors, axis=2)
            quantized_indices = np.argmin(distances, axis=1)

            # 使用量化后颜色替换聚类中的像素颜色
            quantized_image[labels == i] = quantized_colors[quantized_indices]

        # 存储聚类中心颜色
        center_colors = kmeans.cluster_centers_.astype('uint8')

        return {'np_image': quantized_image, 'n_clusters': self.n_clusters, 'max_colors': self.max_colors, 'center_colors': center_colors}

(四)使用说明

# 创建压缩器对象  
compressor = ColorfulImageCompressor(n_clusters=4, max_colors=2, resize_factor=0.5)  
  
# 压缩彩色图像  
image_path = "./img/image2.jpg"  
compressed_file_path = "./npz/compressed_image2_n4_c2.npz"  
compressor.compress(image_path, compressed_file_path)  
  
# 解压缩图像并显示  
reconstructed_image = compressor.decompress(compressed_file_path)  
reconstructed_image.show()  
reconstructed_image.save("./img/reconstructed_image2_n4_c2.jpg")  

3.测试结果

测试图片我们使用的采用的一张818*818分辨率,大小为79.49KB的彩色图片。分别使用不同的聚类数量和颜色数量来进行测试。

descriptiondescription
原始图片聚类数为8,颜色为2的压缩图片

详细运行数据如下表(下面文件名中的n为聚类数,而c为颜色数):

文件名原始大小(KB)压缩后的中间文件大小(KB)解压缩后的图片大小 (KB)
reconstructed_image2_n4_c279.4929.541.7
reconstructed_image2_n4_c479.4949.345.2
reconstructed_image2_n4_c879.4970.951.3
reconstructed_image2_n4_c1679.4994.359.3
reconstructed_image2_n8_c279.4948.348.7
reconstructed_image2_n8_c479.4973.352.5
reconstructed_image2_n8_c879.4910159.1
reconstructed_image2_n8_c1679.4912561.1

结束语

如果有疑问欢迎大家留言讨论,你如果觉得这篇文章对你有帮助可以给我一个免费的赞吗?你们的认可是我最大的分享动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1889597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

thinkphp6/8 验证码

html和后台验证代码按官方来操作 ThinkPHP官方手册 注意: 如果验证一直失败,看看Session是否开启, 打印dump(session_status());结果2为正确的, PHP_SESSION_DISABLED: Session功能被禁用(返回值为0)。…

awtk-web 增加模拟器外壳

界面效果 方法 将 data/simulator.html 拷贝到 app目录下,覆盖index.html将 data/simulator_bg.png 拷贝到 app目录下 动态效果

互联网盲盒小程序的市场发展前景如何?

近几年来,盲盒成为了大众热衷的消费市场。盲盒是一个具有随机性和惊喜感,它能够激发消费者的好奇心,在拆盲盒的过程中给消费者带来巨大的愉悦感,在各种的吸引力下,消费者也愿意为各类盲盒买单。如今,随着盲…

传输线阻抗匹配电阻端接的方式

电路为什么需要端接? 众所周知,电路中如果阻抗不连续,就会造成信号的反射,引起上冲下冲、振铃等信号失真,严重影响信号质量。所以在进行电路设计的时候阻抗匹配是很重要的考虑因素。 对我们的PCB走线进行阻抗控制已经…

Python创建异步任务队列库之Huey使用详解

概要 Huey 是一个简单的 Python 库,用于创建异步任务队列。它的设计目标是简单易用,同时具备强大的功能。Huey 可以轻松地将任务添加到队列中,然后在后台线程中处理这些任务,从而避免阻塞主线程。这使得 Huey 非常适合处理 I/O 密集型或长时间运行的任务。此外,Huey 还支…

Rhino 犀牛三维建模工具下载安装,Rhino适用于机械设计广泛领域

Rhinoceros,这款软件小巧而强大,无论是机械设计、科学工业还是三维动画等多元化领域,它都能展现出其惊人的建模能力。 Rhinoceros所包含的NURBS建模功能,堪称业界翘楚。NURBS,即非均匀有理B样条,是计算机图…

JDK1.8下载、安装与配置完整图文2024最新教程

一、报错 运行Pycharm时,报错No JVM installation found. Please install a JDK.If you already have a JDK installed, define a JAVA_HOME variable in Computer >System Properties > System Settings > Environment Variables. 首先可以检查是否已安装…

如何将 Apifox 的自动化测试与 Jenkins 集成?

CI/CD (持续集成/持续交付) 在 API 测试 中的主要目的是为了自动化 API 的验证流程,确保 API 发布到生产环境前的可用性。通过持续集成,我们可以在 API 定义变更时自动执行功能测试,以及时发现潜在问题。 Apifox 支持…

PMP报考条件是什么?很多人都没读懂...

最近正值8月份考试报名期,想计划考8月份考试的宝子可以准备起来了,下面是报名时间和考试安排 8月考试时间安排: 👉报名时间在7.9日—12日 👉考试时间在8.31日(周六) 一、PMP报名条件是什么&am…

vscode插件的开发过程记录(一)

前言 本文是关于visual studio code软件上自定义插件的开发记录,将从头记录本人开发的过程,虽然网上也有很多文章,但个人在实践的过程还是会遇到不一样的问题,所以记录下来,以便于后期参考。 前期准备: 1、…

基于SpringCloud的智慧养老平台的设计与实现

您好!我是专注于计算机技术研究的码农小野。如果您对CSGO赛事管理系统感兴趣或有相关开发需求,欢迎随时联系我。 Java 数据库 MySQL 技术 SpringCloud, B/S架构 工具 Eclipse, MySQL Workbench, SpringBoot 系统展示 首页 老人管理界面 活动信息…

VBA使用ActiveWindow.Zoom调整页面显示百分比

前言 本节会通过VBA实现自动调整Excel页面显示的百分比功能 Zoom属性 1.调整当前工作表 示例:调整当前sheet显示比例为90% Sub AvtivwWindowZoom() ActiveWindow.Zoom 90 End Sub2.调整其他工作表 当一个Excel文件存在多张工作表Sheet时,又需要调…

这所985院校不保护一志愿,18人不合格被刷!西北农林科技大学计算机考研考情分析!

西北农林科技大学(Northwest A&F University),简称“西农”或“西北农林”,始创于1934年,位于中华人民共和国陕西省杨凌示范区。1999年9月11日由同处杨凌的原西北农业大学、西北林学院、中国科学院水利部水土保持研究所、水利部西北水利科…

Springboot 校园安全通事件报告小程序系统-计算机毕业设计源码02445

Springboot 校园安全通事件报告小程序系统 摘 要 随着中国经济的飞速增长,消费者的智能化水平不断提高,许多智能手机和相关的软件正在得到更多的关注和支持。其中,校园安全通事件报告小程序系统更是深得消费者的喜爱,它的出现极大…

MES系统如何进行数据采集?

在现代化制造业中,MES系统扮演着至关重要的角色。其中,对生产设备进行数据采集是MES系统不可或缺的一部分。数据采集不仅能够实时监控设备的运行状态,还能提供准确的生产数据,帮助企业实现精细化管理和优化生产流程。 通过实时采…

动态规划精品课 2024.6.26-24.7.3

一、斐波那契数列模型 0、第N个泰波那契数 class Solution {public int tribonacci(int n) {// 1. 创建 dp 表// 2. 初始化// 3. 填表// 4. 返回结果// 处理边界情况if (n 0)return 0;if (n 1 || n 2)return 1;int[] dp new int[n 1];dp[0] 0;dp[1] dp[2] 1;for (int i…

GPU云渲染平台到底怎么选?这六点要注意!

随着对高效计算和图像处理需求的增加,GPU云渲染平台成为许多行业的关键工具。尤其是对影视动画制作领域来说,选择一个合适的GPU云渲染平台可以大大提升工作效率。然而,面对市场上众多的选择,如何找到适合自己的GPU云渲染平台呢&am…

【信即是功夫】人皆有良知在心中

良知就是做人、做事的准则,良知就是天理;实实在在地自信 每个人心中都有一个圣人,只因自己不能真的相信,把这个圣人埋没了 良知在每个人心中,无论你如何做,也无法泯灭它。即使身为盗贼的人,他…

8款你不一定知道的良心软件!

AI视频生成:小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/我们使用一些流行的软件的时候,往往会忽略一些功能非常强大的软件,因为这些软件的众 多,都因为看不见而丢失&a…

百度最新升级的产品,我实测了下,好不好用拉出来遛遛

百度一系列产品又又又要上新了?敖丙我作为它的老用户,从内测到现在可以说是一直关注着,听说它有最新进展,我火速端起小板凳和瓜子去围观了下,这不新鲜热乎的实测就来了,好不好用咱拉出来遛遛。。 说起来“…