使用 PCA 实现图像压缩

我们知道 PCA 能够对信息(矩阵)进行压缩,图像数据也是矩阵形式,所以 PCA 也能够实现对图像数据压缩。

import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA
import os

if __name__ == '__main__':

    _, axes = plt.subplots(1, 5, figsize=(20, 8))

    data = plt.imread('data/img.webp') / 255
    # 显示原图
    axes[0].imshow(data)
    axes[0].set_title('原图')

    new_img = []
    for index in range(3):
        # 保留图像信息
        transfer = PCA(n_components=0.8)
        chanel = data[:, :, index]
        chanel = transfer.fit_transform(chanel)
        chanel = transfer.inverse_transform(chanel)
        new_img.append(chanel)

    # 显示压缩图
    new_img = np.array(new_img).transpose([1, 2, 0])
    # 将值截断到 0-1 之间
    new_img = np.clip(new_img, 0, 1)
    axes[1].imshow(new_img)
    axes[1].set_title('压缩图')

    for index in range(3):
        axes[2 + index].imshow(new_img[:, :, index])
        axes[2 + index].set_title('通道' + str(index + 1))
    plt.show()


    plt.imsave('data/new_img.webp', new_img)

    print('原图大小:', os.path.getsize('data/img.webp'))
    print('压缩图大小:', os.path.getsize('data/new_img.webp'))

程序输出结果:

原图大小: 37848
压缩图大小: 18120

上面代码中,我们设置保留原始图像 0.8 的信息,输出图像的大小从 37848 变成了 18120。另外,PCA 对象中的 inverse_transform 函数可以将降维后的数据重新映射到原始空间,这是因为 PCA 后的数据是在新的坐标空间中的表示,图像的坐标都是以原始坐标表示的,为了能够正常显示出图像,所以需要这一步的操作。

未经允许不得转载:一亩三分地 » 使用 PCA 实现图像压缩