import numpy as npfrom PIL import Image# 载入图片img = np.array(Image.open("./1.png",'r'))print("img(原图):",img.shape)# 第一步:通道分离c_list = [img[...,i] for i in range(img.shape[-1])]def Compress(x,precent,print_shape=True,print=print):"""作用:对面二维矩阵进行压缩x: 二维矩阵precent:保留的奇异值的比例, 例如 0.9即保留前90%的奇异值print_shape和print: 可忽略,只是方便打印shape的辅助手段。"""if print_shape:print = printelse:print = lambda *args,**kwargs:...x = np.array(x)print("x",x.shape)U,Sigma,V_T = np.linalg.svd(x) # 奇异值分解print("U,Sigma,V_T:",U.shape,Sigma.shape,V_T.shape)# 全零矩阵,大小与目标矩阵相同。zeroimg = np.zeros(shape=(U.shape[0],V_T.shape[0]))print("zeroimg:",zeroimg.shape)assert zeroimg.shape == x.shapek = int(len(Sigma)*precent)print("k(选取的奇异值数):",k)sigma_k = np.eye(k) * Sigma[:k]U_k = U[...,:k]V_T_k = V_T[:k,...]print("sigma_k,U_k,V_T_k:",sigma_k.shape,U_k.shape,V_T_k.shape)x_re = zeroimg + U_k@sigma_k@V_T_kx_re = np.clip(x_re,0,255).astype("uint8") # 矩阵数值范围截断为0~255并设值uint8类型print("x_re:",x_re.shape)return x_reimg_list = [img]for i,precent in enumerate([0.1,0.01]):print()# 第二步:对各个通道矩阵进行压缩c_re_list = []for j,x in enumerate(c_list):x_re = Compress(x,precent,print_shape=True if j==0 else False)c_re_list.append(x_re)# 第三步 重建图像img_re = np.stack(c_re_list,-1)print(f"img_re{i}(重建图片{i}):",img_re.shape)img_list.append(img_re)# 可视化import matplotlib.pyplot as pltplt.figure(figsize=(20,20))for i,img in enumerate(img_list,start=1):plt.subplot(1,len(img_list),i)plt.imshow(img)
输出:

