基于SVD的图像压缩

算法简介

 

算法实现

我只是简单处理了一下图像的灰度值,如果要处理RGB值的话,就需要分别进行SVD分解,最后再合起来即可。

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt


def picture_processing(file):  # 图像处理,返回灰度值
    im = Image.open(file)
    im = im.convert('L')   # 转换为灰度图
    #im.save('original_' + file)  # 保存图片
    w, h = im.size
    data = np.zeros((h, w))
    for i in range(w):     # 得到灰度值矩阵
        for j in range(h):
            data[j][i] = im.getpixel((i, j))
    return data


def picture_restore(U, Sigma, VT, k):   # 图像恢复,k为选取的奇异值个数
    sig = np.eye(k) * Sigma[:k]
    new_pic = U[:, :k].dot(sig).dot(VT[:k, :])   # 重构图片
    new_size = U.shape[0] * k + sig.size + k * VT.shape[1]  # 计算SVD图片所需大小
    #new_im = Image.fromarray(new_pic.astype(np.uint8))  # 保存图片
    #new_im.save('pic_' + str(k) + '.jpeg')
    return new_pic, new_size


if __name__ == '__main__':
    file = 'pic.jpeg'
    data = picture_processing(file)
    U, Sigma, VT = np.linalg.svd(data)

    pic_list, size_list = [], []   #图片列表,图片大小列表
    k_list = [1, 10, 50, 100, 300]
    for k in k_list:
        new_pic, new_size = picture_restore(U, Sigma, VT, k)
        pic_list.append(new_pic)
        size_list.append(new_size)

    fig, ax = plt.subplots(2, 3)   # 展示
    ax[0][0].imshow(data)
    ax[0][0].set_title('original picture——size:%d' % data.size)
    for i in range(len(k_list)):
        ax[int((i+1) / 3)][int((i+1) % 3)].imshow(pic_list[i])
        ax[int((i+1) / 3)][int((i+1) % 3)].set_title('k = %d——size:%d' % (k_list[i], size_list[i]))
    plt.show()

 

运行结果

 

posted @ 2019-04-03 11:17  Kayden_Cheung  阅读(1622)  评论(0编辑  收藏  举报
//目录