SVD图像压缩步骤
对于RGB图像来说,对应三色层,对每一个色层进行SVD分解,得到 U , S , V U, S, V U,S,V矩阵,设利用前K大奇异值进行图像压缩,即有:
r e s u l t = ∑ i = 1 3 U i [ : , 1 : K ] ∗ S [ 1 : K , 1 : K ] ∗ V T [ 1 : K , : ] result = \sum_{i = 1}^{3}U_i[:, 1:K] * S[1:K, 1:K] * V^T[1:K, :] result=i=1∑3Ui[:,1:K]∗S[1:K,1:K]∗VT[1:K,:]
而对于灰度图像来说,只需要完成一层的运算即可。
原图及不同保留度下压缩结果
原图像:
不同保留度下的压缩结果:
Show me the code
导包
import numpy as np
import matplotlib.pyplot as plt
SVD图像压缩模块
def zip_image_by_svd(origin_image, rate = 0.8):
# 显示原图像
plt.figure(figsize= (12, 12))
plt.title("Origin Image")
plt.imshow(origin_image)
plt.show()
print("\n\n======开始压缩======")
# 提前开辟结果存放空间
result = np.zeros(origin_image.shape)
# 对原图像进行SVD分解
u_shape = 0
s_shape = 0
vT_shape = 0
for chan in range(3):
# 对该层进行SVD分解
U, sigma, V = np.linalg.svd(origin_image[:, :, chan])
n_sigmas = 0
temp = 0
# 计算达到保留率需要的奇异值数量
while (temp / np.sum(sigma)) < rate:
temp += sigma[n_sigmas]
n_sigmas += 1
# 构建奇异值矩阵
S = np.zeros((n_sigmas, n_sigmas))
for i in range(n_sigmas):
S[i, i] = sigma[i]
# 构建结果
result[:, :, chan] = (U[:, 0:n_sigmas].dot(S)).dot(V[0:n_sigmas, :])
u_shape = U[:, 0:n_sigmas].shape
s_shape = S.shape
vT_shape = V[0:n_sigmas, :].shape
# 归一化到[0, 1]
for i in range(3):
MAX = np.max(result[:, :, i])
MIN = np.min(result[:, :, i])
result[:, :, i] = (result[:, :, i] - MIN) / (MAX - MIN)
# 调整到[0, 255]
result = np.round(result * 255).astype('int')
# 显示压缩结果
plt.figure(figsize= (12, 12))
plt.imshow(result)
plt.title("Result Image")
plt.show()
# 计算压缩率
zip_rate =(origin_image.size -3 * (u_shape[0] * u_shape[1] + s_shape[0] * s_shape[1] + vT_shape[0] * vT_shape[1])) / (origin_image.size)
print("保留率: ", rate)
print("所用奇异值数量为:", n_sigmas)
print("原图大小: ", origin_image.shape)
print("压缩后用到的矩阵大小:3 x ({} + {} + {})". format(u_shape, s_shape, vT_shape))
print("压缩率为: ", zip_rate)
主函数及其调用
# 定义主函数
def main():
# 读入图像
image_path = '/Users/tantaiyunfei/Desktop/图片/背景图/e32e0ab9393fb231aa3af9a71ac06a07.jpg'
origin_image = plt.imread(image_path)
# 利用自定义SVD图像压缩模块对图像进行压缩
zip_image_by_svd(origin_image, rate = 0.8)
# 主函数调用
if __name__ == "__main__":
main()