SVD即奇异值分解(singular value decomposition),是将矩阵分解为奇异向量和奇异值。
每次写相关文章的时候,都会面临一个常见的问题,矩阵是什么?套用平冈和幸的话来说,矩阵即是映射,令矩阵y=Ax,那么矩阵A就是由向量x到向量y的一个映射。从另一个角度看,矩阵又是数的排列。在这里,我们主要介绍的是使用SVD进行图像压缩。因为实际图像各像素点之间具有高度相关的,因此,使用更少的像素去表示整张图像的信息是可行的。但你如果用SVD去压缩随机噪声生成的图片,那就没有什么意义了。
SVD图像压缩的核心思想是,通过较数据量较少的多个矩阵的映射去还原一个数据量更大的数的排列。
在SVD压缩中有
# -*- coding: utf-8 -*-
'''
author@cclplus
date:2020/07/26
'''
import cv2
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
#转为u8类型
def restore1(u, sigma, v, k):
m = len(u)
n = len(v)
a = np.zeros((m, n))
a = np.dot(u[:, :k], np.diag(sigma[:k])).dot(v[:k, :])
# s1 = np.size(u[:, :k])
# s1+= np.size(np.diag(sigma[:k]))
# s1+= np.size(np.diag(v[:k, :]))
# s2 = np.size(a)
# print("压缩率:",s1/s2)
a[a < 0] = 0
a[a > 255] = 255
return np.rint(a).astype('uint8')
def SVD(frame,K=10):
a = np.array(frame)
#由于是彩色图像,所以3通道。a的最内层数组为三个数,分别表示RGB,用来表示一个像素
u_r, sigma_r, v_r = np.linalg.svd(a[:, :, 0])
u_g, sigma_g, v_g = np.linalg.svd(a[:, :, 1])
u_b, sigma_b, v_b = np.linalg.svd(a[:, :, 2])
R = restore1(u_r, sigma_r, v_r, K)
G = restore1(u_g, sigma_g, v_g, K)
B = restore1(u_b, sigma_b, v_b, K)
I = np.stack((R, G, B), axis = 2)
return I
if __name__ == "__main__":
mpl.rcParams['font.sans-serif'] = [u'simHei']
mpl.rcParams['axes.unicode_minus'] = False
frame = cv2.imread("./liuyifei.bmp",-1)
I = SVD(frame,40)
plt.imshow(I)
cv2.imwrite("out.bmp",I)