Python SVDC(奇異值分解壓縮)

最近,需要補充實驗數據,實現了基於SVD的圖像壓縮算法。奇異值分解能夠有效的降低數據的維數,以本文的圖片爲例,從450維降到149維後,還保留了90%的信息雖然奇異值分解很有效,但是不能濫用,一般情況下要求降維後信息的損失度不能超過5%,甚至是1%.

  • Recently, the experimental data need to be supplemented, and the image compression algorithm based on SVD is implemented.Singular value decomposition can effectively reduce the dimension of data. Take the picture in this paper for example, after reducing the dimension from 450 to 149, 90% of the information is retained. Although singular value decomposition is very effective, it cannot be abused.

讀取後數據格式未轉換,使用imread讀取圖片後,格式爲uint8,發現做矩陣乘積的時候數值明顯不對。後來將其轉換爲mat時修改格式爲float就好了。

  • After reading, the data format is not converted. After reading the image with IMREAD, the format is UINT8, and it is found that the value is obviously wrong when doing matrix product.And then when you convert it to MAT you can just change it to float.

RESULT:

圖像質量評價:

  • image quality eveluation:

SSIM and RMSE 

SVD(SV=40):SSIM:0.937214 RMSE:4.183163

SVD(SV=50):SSIM:0.955571 RMSE:3.217802

CODE:

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

def methods(sigma, u, v, K):         #svd方法的核心(奇異值,左奇異矩陣,右奇異矩陣,奇異值個數)
    uk = u[:, 0:K]                   #構建左奇異矩陣
    sigmak = np.diag(sigma[0:K])     #構建奇異值
    vk = v[0:K,]                     #構建右奇異矩陣
    a  = np.dot(np.dot(uk,sigmak),vk)#返回奇異值壓縮後的矩陣
    a[a < 0] = 0                     #異常數值處理
    a[a > 255] = 255                 #異常數值處理
    return np.rint(a).astype('uint8')#整數化

if __name__ == "__main__":
    A = Image.open("srcimage.bmp", 'r')
    output_path = r'.\Picture'
    if not os.path.exists(output_path):
        os.mkdir(output_path)
    a = np.array(A)   #把圖像轉化爲矩陣
    K = 60            #奇異值的最大個數
    u_r, sigma_r, v_r = np.linalg.svd(a[:, :, 0]) #進行svd分解(返回一個元組)
    u_g, sigma_g, v_g = np.linalg.svd(a[:, :, 1]) #進行svd分解(返回一個元組)
    u_b, sigma_b, v_b = np.linalg.svd(a[:, :, 2]) #進行svd分解(返回一個元組)
    plt.figure(figsize=(10,10), facecolor='w')
    mpl.rcParams['font.sans-serif'] = [u'simHei']
    mpl.rcParams['axes.unicode_minus'] = False
    i = 1
    while i <= 16:
        for k in range(1, K+1):
            print(k)
            R = methods(sigma_r, u_r, v_r, k)
            G = methods(sigma_g, u_g, v_g, k)
            B = methods(sigma_b, u_b, v_b, k)
            I = np.stack((R, G, B), 2)
            Image.fromarray(I).save('%s\\svd_%d.png' % (output_path, k))
            if k in [1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60,65,70]:
                plt.subplot(4, 4, i)
                plt.imshow(I)
                plt.axis('off')
                plt.title(u'奇異值數目:%d' % k)
                i += 1
    plt.show()

 I hope I can help you,If you have any questions, please  comment on this blog or send me a private message. I will reply in my free time.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章