奇异值分解之图片压缩

 

这一篇主要是代码,后面有理论。

import numpy as np
from PIL import Image
img = Image.open("3.png").convert("RGB")
n, m = img.size
pix = img.load()
r, g, b= img.split()
red = np.array(r)
green = np.array(g)
blue = np.array(b)

以上将图像读取并分离为rgb

from numpy.linalg import svd
def chg(pic):
    U, s, VT = svd(pic)
    Sigma = np.zeros( (pic.shape[0], pic.shape[1]) )
    Sigma[:min(pic.shape[0],pic.shape[1]), :min(pic.shape[0],pic.shape[1])] = np.diag(s)
    k=150
    pic_approx = U[:, :k] @ Sigma[:k, :k] @ VT[:k, :]
    return pic_approx

将矩阵分解为U, S, VT

red = chg(red)
green = chg(green)
blue = chg(blue)
red = np.clip(red, 0, 255)
green = np.clip(green, 0, 255)
blue = np.clip(blue, 0, 255)
imageR = Image.fromarray(red.astype('uint8'), 'L')
imageG = Image.fromarray(green.astype('uint8'), 'L')
imageB = Image.fromarray(blue.astype('uint8'), 'L')
Image.merge("RGB",(imageR, imageG, imageB)).show()

原图

压缩后

只使用了前50个奇异值(特征值),压缩了约十倍大小