svd图像压缩代码

# -*- coding: utf-8 -*-
"""
Created on Mon Jan 10 16:51:39 2022

@author: Liu_Jun_Desktop
"""

import numpy as np
from PIL import Image
import xlrd
import openpyxl 
import xlwt
import pandas as pd
import matplotlib.pyplot as plt
def load_image(filepath):#下载图像
    im = Image.open(filepath)
    return np.array(im)
def svd(A):#进行奇异值分解
    return np.linalg.svd(A)

def rebuildsvd(U, S, V):#根据计算的奇异值重建图像
    r = len(S)
    return np.dot(U[:,:r] * S, V[:r,:])
def setZeros(U, S, V, k):#将三个矩阵的无关值置零
    r = len(S)
    for i in range(k, r):
        U[:, i] = 0
        S[i] = 0
        V[i, :] = 0
    return U, S, V

def total_variation(S, k):#总变化率求解
    return np.sum(S[:k]) / np.sum(S)
def generate_sheet_names():#生成文件名
    list = []
    for j in range(3):
         list.append(str(j)+"通道U矩阵")
         list.append(str(j)+"通道S矩阵")
         list.append(str(j)+"通道V矩阵")   
    return list

def img_process(img, k):  # 图像处理
    img2 = np.zeros_like(img)
    tv = 1.0
    sheetname=generate_sheet_names() 
    for c in range(img.shape[2]):
        A = img[:,:,c]#三个通道分别进行依次计算
        U, S, V = svd(A)
        tv *= total_variation(S,k)
        U, S, V = setZeros(U,S,V,k)
        if c==0:
            U_matrix0=pd.DataFrame(U)
            S_diag1=pd.DataFrame(np.diag(S))
            V_matri2=pd.DataFrame(V)
        elif c==1:
            U_matrix3=pd.DataFrame(U)
            S_diag4=pd.DataFrame(np.diag(S))
            V_matri5=pd.DataFrame(V)
        else:
            U_matrix6=pd.DataFrame(U)
            S_diag7=pd.DataFrame(np.diag(S))
            V_matri8=pd.DataFrame(V)
        if k==4**2 and c==2:
            with pd.ExcelWriter('奇异矩阵.xlsx') as writer:
                    U_matrix0.to_excel(writer, sheet_name=sheetname[0])
                    S_diag1.to_excel(writer, sheet_name=sheetname[1])
                    V_matri2.to_excel(writer, sheet_name=sheetname[2])
                    U_matrix3.to_excel(writer, sheet_name=sheetname[3])
                    S_diag4.to_excel(writer, sheet_name=sheetname[4])
                    V_matri5.to_excel(writer, sheet_name=sheetname[5])
                    U_matrix6.to_excel(writer, sheet_name=sheetname[6])
                    S_diag7.to_excel(writer, sheet_name=sheetname[7])
                    V_matri8.to_excel(writer, sheet_name=sheetname[8])
                    writer.save()        
        img2[:,:,c] = rebuildsvd(U, S, V)
    return img2, tv
def compression_ratio(A, k):#图像压缩率计算
    denominator = A.shape[0] * A.shape[1] * A.shape[2]
    nominator = (A.shape[0] *np.sqrt(k) +np.sqrt(k)* A.shape[1] + k) * A.shape[2]
    return 1 - (nominator/denominator)
if __name__=="__main__":#代码测试
    filepath = 'lena_std.jpg'
    lenna = load_image(filepath)
    plt.imshow(lenna)
    U,S,V=np.linalg.svd(lenna[:,:,0])
    print("奇异值分解前的lenna,U,S,V维度:")
    print(lenna.shape)
    print(U.shape)
    print(S.shape)
    print(V.shape)
    print('S的值如下:')
    # S_diag=np.diag(S)
    df=pd.DataFrame(S)
    df.to_excel('原始奇异值矩阵.xlsx',sheet_name='未进行奇异值\
                分解的0通道S对角矩阵0',index=False) 
    plt.figure(figsize=(20,10))
    plt.subplot(141)
    img, variance = img_process(lenna, 4)
    ratio = compression_ratio(lenna, 4)
    plt.imshow(img)
    plt.title('{:.2%} / {:.2%}'.format(variance, ratio))
    
    plt.subplot(142)
    img, variance = img_process(lenna, 4 **2)
    ratio = compression_ratio(lenna, 4 **2)
    plt.imshow(img)
    plt.title('{:.2%} / {:.2%}'.format(variance, ratio))
    
    plt.subplot(143)
    img, variance = img_process(lenna, 4 **3)
    ratio = compression_ratio(lenna, 4 **3)
    plt.imshow(img)
    plt.title('{:.2%} / {:.2%}'.format(variance, ratio))
    
    plt.subplot(144)
    img, variance = img_process(lenna, 4**4)
    ratio = compression_ratio(lenna,4**4)
    plt.imshow(img)
    plt.title('{:.2%} / {:.2%}'.format(variance, ratio))

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值