我正在为美国的鹿种类创建一个图像分类模型,目前我正在对这些图像进行主成分分析(PCA),目的是减少它们的内存占用,并在模型运行时减少运行时间。
我知道主成分分析应该能够在不损失太多方差的情况下降低数据集的维度。所以当我注意到通过我的Deer_PCA
函数处理后的所有新的PCA压缩图像都比原始图像大时,我感到有些困惑。原始图像大小为128 KB,而在n_components = 150
下运行后的新压缩图像大小为293 KB。有人知道这是为什么吗?
这是我在函数中处理的图片,请在运行代码前将图片放入一个空文件夹:
这是通过Deer_PCA
函数处理后的新压缩图像:
这是我的代码:
#导入一些包import cv2import os,sysfrom PIL import Imageimport pandas as pdfrom scipy.stats import statsfrom sklearn.decomposition import PCAimport matplotlib.pyplot as pltimport matplotlib.image as mpimg#让我们编写一个函数,对文件夹中的所有图像执行PCA,并输出到一个新文件夹#inpath = 包含图像的文件夹 - 字符串值 #outpath = 我希望新压缩图像保存到的文件夹。- 字符串值#n_comp = 组件数量 - 整数值 def Deer_PCA(inpath, outpath,n_comp): for image_path in os.listdir(inpath): # 创建完整的输入路径并读取文件 input_path = os.path.join(inpath, image_path) print(input_path) w_deer = cv2.cvtColor(cv2.imread(input_path), cv2.COLOR_BGR2RGB) #分割图像 blue_2,green_2,red_2 = cv2.split(w_deer) #缩放通道 w_blue = blue_2/255 w_green = green_2/255 w_red = red_2/255 #对每个通道进行PCA 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) #在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("合并成功") # 创建完整的输出路径 fullpath = os.path.join(outpath, 'PCA_'+image_path) cv2.imwrite(fullpath, img_reduced2*255) print("保存成功\n") #检查图像大小 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('原始图像:',sys.getsizeof(original_image_path))print('PCA图像:',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。
以减少它们的内存占用,并在模型运行时减少运行时间。
请注意,文件大小与模型需要处理的工作量无关。当你从文件中读取图像到内存时,你得到一定数量的像素。模型必须处理所有这些像素。数据在磁盘上占用的空间此时无关紧要。如果你想让模型运行得更快,减少图像中的像素数量,你可以通过子采样来实现。但请确保在重采样后,你仍然能够识别模型需要识别的内容。如果你移除太多像素,你将无法区分鹿和老鼠!