SVD应用于图像压缩 Python代码测试

目录

  • 前言
  • 代码
  • 实验结果

前言

  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)

实验结果

  原图
SVD应用于图像压缩 Python代码测试_第1张图片
  取四十个特征值
SVD应用于图像压缩 Python代码测试_第2张图片
  此时需保存的数据不到前者的百分之10,由此可以看出,SVD压缩带来的效果是十分可观的。

你可能感兴趣的:(矩阵论,OpenCV,python,SVD)