为什么执行PCA后图像文件的大小增加了?

Why does the size of the image file increase after I performed PCA?

我正在为美国的鹿类创建一个图像分类模型,我目前正在对这些图像执行 PCA 以减少它们的内存大小并减少模型的 运行 时间至此。

我知道主成分分析应该在不放弃太多方差的情况下减少数据集的维度。因此,当我注意到通过我的 Deer_PCA 函数 运行 的所有新 PCA 压缩图像都比原始图像大时,我有点困惑。原始图像为 128 KB,在 运行 在 n_components = 150 处压缩后新压缩图像为 293 KB。有谁知道为什么会这样?

这是我在函数中 运行 图片,在 运行 代码之前将图片放在一个空文件夹中:

这是通过 Deer_PCA 函数 运行 压缩后的新压缩图像:

这是我的代码:

#import some packages

import cv2
import os,sys
from PIL import Image
import pandas as pd

from scipy.stats import stats
from sklearn.decomposition import PCA

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

#Let's write a function to perform PCA on all the images in the folder and output it to a new folder

#inpath = folder containing the image - string value 
#outpath = which folder do I want the new compressed image saved to. - string value
#n_comp = number of components - int value

        
def Deer_PCA(inpath, outpath,n_comp):
    for image_path in os.listdir(inpath):

        # create the full input path and read the file
        input_path = os.path.join(inpath, image_path)
        print(input_path)
        
        w_deer = cv2.cvtColor(cv2.imread(input_path), cv2.COLOR_BGR2RGB)

        #split image
        blue_2,green_2,red_2 = cv2.split(w_deer)

        #scale channels
        w_blue = blue_2/255
        w_green = green_2/255
        w_red = red_2/255

        #PCA on each channel
        pca_b2 = PCA(n_components=n_comp)
        pca_b2.fit(w_blue)            
        trans_pca_b2 = pca_b2.transform(w_blue)

        pca_g2 = PCA(n_components=n_comp)
        pca_g2.fit(w_green)
        trans_pca_g2 = pca_g2.transform(w_green)

        pca_r2 = PCA(n_components=n_comp)
        pca_r2.fit(w_red)
        trans_pca_r2 = pca_r2.transform(w_red)

        #merge channels after PCA
        b_arr2 = pca_b2.inverse_transform(trans_pca_b2)
        g_arr2 = pca_g2.inverse_transform(trans_pca_g2)
        r_arr2 = pca_r2.inverse_transform(trans_pca_r2)

        img_reduced2 = (cv2.merge((b_arr2, g_arr2, r_arr2)))
        
        print("Merge Successful")

        # create the full output path
        fullpath = os.path.join(outpath, 'PCA_'+image_path)
        cv2.imwrite(fullpath, img_reduced2*255)
        
        print("Successfully saved\n")
        
#Check the image sizes 

original_image_path = '/Users/matthew_macwan/Downloads/CIS/I_Class_Deer/mule_deer_doe/mule deer doe_1.jpeg'

PCA_compressed_image_path = '/Users/matthew_macwan/Downloads/CIS/I_Class_Deer/mule_deer_doe/PCA_mule deer doe_1.jpeg'

print('Original Image:',sys.getsizeof(original_image_path))

print('PCA Image:',sys.getsizeof(PCA_compressed_image_path))

这里有些误会。当你像这样对单个图像进行 PCA 时,它会将每一列(或行,不确切知道)作为一个观察值。然后它将图像减少到 150 行(或列),确实减少了数据量,并且可能还减少了这些数据中包含的信息量。

但随后您从 PCA 重建原始图像,获得与原始图像大小相同的数组,并将其保存为 JPEG。您要存储的数据点并不少。图像总体上可能包含较少的信息,但信息减少的方式与 JPEG 减少信息的方式不同,因此 JPEG 算法不太可能受益,它不太可能能够用更少的字节保存那些数据。

您的输出 JPEG 明显大于输入可能是由于 PCA 更改实际上使 JPEG 算法变得更难,或者是由于 JPEG 算法的质量设置(或两者的组合)。降低 JPEG 压缩的质量设置是缩小 JPEG 文件的最佳方法。

如果要使用 PCA 压缩图像文件,则必须保存 PCA 基向量和投影到这些向量中的图像。我怀疑这是压缩图像的有效方法。

压缩图像的一种完全不同的方法是获取大量图像,通过将所有样本值放在一行中将每个图像变成一个向量,然后将 PCA 应用于该集合。 PCA 基向量形成一个“字典”,现在每个图像都由这些基向量的线性组合表示,这意味着您只需要存储权重,每个基向量一个值。再说一次,不能保证这是有效的,我这样说是为了说明 PCA 是如何工作的。您能做的最好的事情就是坚持使用众所周知且经过测试的图像压缩方法,例如 JPEG 和 JPEG2000。


to reduce their memory size and reduce the run time of the model when I get to that point.

请注意,文件大小与模型必须完成的工作量无关。当您将文件中的图像读入内存时,您会获得一定数量的像素。该模型必须处理所有这些像素。在这一点上,数据在磁盘上占用了多少 space 是无关紧要的。如果你想让模型更快,减少图像中的像素数量,你可以通过二次采样来做到这一点。但请确保在重采样后您仍然可以识别模型需要识别的任何内容。如果去掉太多像素,你就分不清鹿和老鼠了!