贴一个博客地址,简单易懂
博客地址https://zhuanlan.zhihu.com/p/29846048
1、代码
import numpy as np
import matplotlib.image as mping
import matplotlib.pyplot as plt
import matplotlib as mpl
def image_svd(n, pic):
a, b, c = np.linalg.svd(pic)
svd = np.zeros((a.shape[0], c.shape[1]))
for i in range(0, n):
svd[i, i] = b[i]
img = np.matmul(a, svd)
img = np.matmul(img, c)
img[img >= 255] = 255
img[0 >= img] = 0
img = img.astype(np.uint8)
return img
if __name__ == '__main__':
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
path = './building.jpg'
img = mping.imread(path)
print(img.shape)
r = img[:, :, 0]
g = img[:, :, 1]
b = img[:, :, 2]
plt.figure(figsize=(50, 100))
for i in range(1, 40):
r_img = image_svd(i, r)
g_img = image_svd(i, g)
b_img = image_svd(i, b)
pic = np.stack([r_img, g_img, b_img], axis=2)
print(i)
plt.subplot(8, 5, i)
plt.title("图像的SVD分解,使用前 %d 个特征值" % (i))
plt.axis('off')
plt.imshow(pic)
plt.suptitle("图像的SVD分解")
plt.subplots_adjust()
plt.show()
2、效果
对于奇异值,它跟我们特征分解中的特征值类似,在奇异值矩阵中也是按照从大到小排列,而且奇异值的减少特别的快,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。也就是说,我们也可以用最大的k个的奇异值和对应的左右奇异向量来近似描述矩阵。