本文利用了SVD,对图片进行了压缩测试。直接给出源码,注释写的都很清楚,压缩比例自己可以随意调整。
import numpy as np
from numpy import linalg
from PIL import Image
img = Image.open("C:\\Users\\Paul\\Desktop\\frag.jpg")
# 转为灰度图,并将灰度图转换为ndarray
gray_img = img.convert('L')
img_array = np.array(gray_img)
# m: 左奇异矩阵,sig: 奇异值对角阵,v: 右奇异矩阵
m,sig,v = np.linalg.svd(img_array)
sig = np.eye(sig.shape[0]) * sig
# 计算奇异值能量分布
sum_sig_list = []
s = 0.0
for i in range(sig.shape[0]):
s += sig[i][i]
sum_sig_list.append(s)
# 选择最优的奇异值个数, ratio控制阈值
i = 0
ratio = 0.3
while i < sig.shape[0]:
r = sum_sig_list[i] / sum_sig_list[-1]
if r >= ratio:
print("%.2f : %.2f" % (sum_sig_list[i], sum_sig_list[-1]))
i += 1
break
i += 1
print("%d, %.2f" % (i, sum_sig_list[i]))
sub_m = m[:,:i] # 左奇异矩阵的前i列
sub_sig = sig[:i,:i] # 对角阵的前i行和前i列组成的对角阵
sub_v = v[:i,:] # 右奇异矩阵的前i行
# 压缩图片
compr_img_array = np.dot(np.dot(sub_m, sub_sig), sub_v)
compr_img = Image.fromarray(compr_img_array).convert("RGB")
compr_img.save("C:\\Users\\Paul\\Desktop\\compress_frag_30_precent.jpg", "JPEG")
print("%f" % (np.sum(compr_img_array) / np.sum(img_array)))
原图如下
压缩比为0.9的图片如下
压缩比为0.7的图片如下
压缩比为0.5的图片如下