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

python · 浏览次数 : 24

小编点评

本文介绍了一种彩色图像压缩方法,主要包括颜色聚类和动态规划量化两个核心原理。通过对图像中的颜色进行聚类和量化,实现了对图像数据的有效压缩。 1. **颜色聚类**:该方法首先使用KMeans聚类算法将图像中的颜色值聚类为较少数量的颜色簇。通过调整聚类数量和颜色数量,可以在降低存储需求的同时保持图像质量。 2. **动态规划量化**:通过动态规划量化算法进一步减少颜色的数量,同时尽量保持图像质量。该算法会根据原始图像的颜色分布,选择最接近的颜色进行保留。 3. **类结构介绍**:本文提出了一种名为'ColorfulImageCompressor'的类,该类包含了四个主要函数:`__init__`, `compress`, `decompress`, 和 `_dynamic_programming_quantization`。这些函数分别负责初始化压缩器对象、压缩图像、解压缩图像和执行动态规划量化。 4. **使用说明**:通过创建一个彩色图像压缩类的实例,设置聚类数、颜色数量和缩放因子等参数,即可对彩色图像进行压缩和解压缩操作。 5. **测试结果**:文章还提供了使用不同聚类数量和颜色数量的测试结果,展示了该方法在不同条件下的压缩性能。 总体而言,本文提出的彩色图像压缩方法通过结合颜色聚类和动态规划量化技术,实现了对图像数据的有效压缩,同时在保持图像质量的同时显著降低了存储需求。

正文

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的彩色图片。分别使用不同的聚类数量和颜色数量来进行测试。

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

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

文件名 原始大小(KB) 压缩后的中间文件大小(KB) 解压缩后的图片大小 (KB)
reconstructed_image2_n4_c2 79.49 29.5 41.7
reconstructed_image2_n4_c4 79.49 49.3 45.2
reconstructed_image2_n4_c8 79.49 70.9 51.3
reconstructed_image2_n4_c16 79.49 94.3 59.3
reconstructed_image2_n8_c2 79.49 48.3 48.7
reconstructed_image2_n8_c4 79.49 73.3 52.5
reconstructed_image2_n8_c8 79.49 101 59.1
reconstructed_image2_n8_c16 79.49 125 61.1

结束语

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

与【Python】基于动态规划和K聚类的彩色图片压缩算法相似的内容:

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

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

Groovy初学者指南

Groovy是一种基于Java平台的动态编程语言,它结合了Python、Ruby和Smalltalk等语言的特性,同时与Java无缝集成

【manim动画教程】--目录(完结)

manim是一个生成数学教学视频的动画引擎。 它用编程的方式创建精美的数学动画,让数学更加易懂。 本教程简单介绍了 manim 的基本使用方式,基于 v0.17.2 版本 manim 安装 manim是基于python语言开发的开源框架,是由 3blue1brown 开发的。 本来是他们自己用来制作

声音好听,颜值能打,基于PaddleGAN给人工智能AI语音模型配上动态画面(Python3.10)

借助So-vits我们可以自己训练五花八门的音色模型,然后复刻想要欣赏的任意歌曲,实现点歌自由,但有时候却又总觉得少了点什么,没错,缺少了画面,只闻其声,却不见其人,本次我们让AI川普的歌声和他伟岸的形象同时出现,基于PaddleGAN构建“靓声靓影”的“懂王”。 PaddlePaddle是百度开源

【manim】之滚动字幕

概要 manim 是一个做数学视频的 python 库,这个库功能非常强大。具体可以参考官方介绍:https://github.com/ManimCommunity/manim/ 它本身只是封装数学相关的几何体和一些基础动画,所以,制作视频时,需要进一步封装更复杂的动画来满足视频的要求。最近做的一个

SICP:元循环求值器(Python实现)

元语言抽象就是建立新的语言。它在工程设计的所有分支中都扮演着重要的角色,在计算机程序设计领域更是特别重要。因为这个领域中,我们不仅可以设计新的语言,还可以通过构造求值器的方式实现这些语言。对某个程序设计语言的求值器(或者解释器)也是一个过程,在应用于这个语言的一个表达式时,它能够执行求值这个表达式所要求的动作。接下来我们将要讨论如何关于在一些语言的基础上构造新的语言。在这篇博客里,我们将用Pyth

[python] 基于PyWaffle库绘制华夫饼图

华夫饼图Waffle chart是一种独特而直观的图表,用于表示分类数据。它采用网格状排列的等大小方格或矩形,每个方格或矩形分配不同的颜色或阴影来表示不同的类别。这种可视化方法有效地传达了每个类别在整个数据集中的相对比例。本文介绍如何使用基于Python的PyWaffle库绘制华夫饼图。PyWaff

python轻量级性能工具-Locust

Locust基于python的协程机制,打破了线程进程的限制,可以能够在一台测试机上跑高并发 性能测试基础 1.快慢:衡量系统的处理效率:响应时间 2.多少:衡量系统的处理能力:单位时间内能处理多少个事务(tps) 性能测试根据测试需求最常见的分为下面三类 1 负载测试load testing 不断

Python按条件筛选、剔除表格数据并绘制剔除前后的直方图

本文介绍基于Python语言,读取Excel表格文件数据,以其中某一列数据的值为标准,对于这一列数据处于指定范围的所有行,再用其他几列数据的数值,加以数据筛选与剔除;同时,对筛选前、后的数据分别绘制若干直方图,并将结果数据导出保存为一个新的Excel表格文件的方法~

核对不同文件夹所含内容的差异并提取缺失内容:Python代码

本文介绍基于Python语言,以一个大文件夹作为标准,对另一个大文件夹所包含的子文件夹或文件加以查漏补缺,并将查漏补缺的结果输出的方法~