我们知道 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 后的数据是在新的坐标空间中的表示,图像的坐标都是以原始坐标表示的,为了能够正常显示出图像,所以需要这一步的操作。

冀公网安备13050302001966号