Python實現奇異值分解(SVD)壓縮圖片

奇異值分解(Singular Value Decomposition 簡稱SVD)是線性代數中的一種重要分解,在很多領域都有着廣泛的應用。這篇文章將通過一個圖像壓縮的例子教你如何在Python中使用SVD實現數據壓縮,並說明其原理。

奇異值分解壓縮的原理

先看一個簡單的例子,如果你想要在網絡上給別人發送一段數據,數據的內容爲

當然,最簡單的方法就是給這個矩陣直接發過去,這是一個5x5的矩陣,你至少需要發送25個數字。

但是我們可以把這個矩陣分解爲兩個矩陣的乘積,這樣只需要發送10個數字。

圖像也可以被視爲矩陣,圖像的每一個點都是由RGB值定義的,所以每個圖像可以被表示爲三個巨型矩陣(分別是R,G,B矩陣)。

但圖像所生成的矩陣顯然不會像上面的例子那樣簡單的就被分解了。想要分解任意矩陣,這就需要用到SVD了。

SVD分解可以被認爲是EVD(Eigen Value Decomposition 特徵值分解)的延伸。特徵值分解將一個矩陣分解爲兩組正交的特徵向量和一個特徵值對角線矩陣。

而特徵值矩陣又是從大到小排列的,特徵值大小的下降速度很快,我們可以通過丟棄一些特徵值來壓縮數據。對於壓縮圖像來說,只要人眼不可察覺便可以認爲是成功的壓縮。

簡單來說,就是通過把一塊大的數據分解爲很多項,通過給數據的每個項的重要程度排序,挑選出一部分最重要的保留,丟棄一部分最不重要的,來實現數據壓縮。

Python實現圖像壓縮

在python中使用SVD算法很容易,直接使用庫函數即可。這裏主要使用numpy庫用來進行矩陣計算,matplotlib用來顯示圖像以及PIL庫用來讀取本地測試圖片。

首先需要把測試圖片導入進來,轉換爲numpy的矩陣。

img=Image.open(,)
a=np.array(img)

 

這裏圖片轉矩陣後的格式實際上是一個圖片長乘寬的矩陣,這個矩陣的每一個項都包含3個數字,分別是R,G,B的值

實現SVD分解

SVD分解只需要一句話即可

u,sigma,v=np.linalg.svd(a[:,:,0])

這裏的SVD分解返回三個執行後返回三個矩陣,分別是u,sigma和v

實現重建函數

def rebuild_img(u,sigma,v,p):
     m=len(u)
     n=len(v)
     a=np.zeros((m,n))
 
     count=(int)(sum(sigma))
     curSum=0
     k=0
 
     while curSum<=count*p:
         uk=u[:,k].reshape(m,1)
         vk=v[k].reshape(1,n)
         a+=sigma[k]*np.dot(uk,vk)
         curSum+=sigma[k]
         k+=1
 
     a[a<0]=0
     a[a>255]=255
    
     return np.rint(a).astype()

重建函數接受4個參數,u,sigma,v即重建矩陣所需的內容,p則爲使用特徵值的比例,我們將通過改變比例p來看使用特徵值比例對畫面的影響。

算法的步驟如下描述:

首先計算出m和n,即圖片矩陣的長和寬,然後創建一個零矩陣a作爲組裝場地。

count是所有特徵值加起來的總和,用於後面計算比例使用

uk和vk就是從參數u和v中取出,改變形式後形成的與當前特徵值對應得一組特徵向量。

然後不斷地從參數中取出uk、vk和sigma,運算後疊加到a上去,直到滿足一定的比例。

最後把所有矩陣內的項取整數退出即可。

數據壓縮實驗

有了分解與重建,現在可以設計數據壓縮試驗了。

這裏我們控制特徵值的使用比例,從0.1到1,每次步進0.1,然後分解重建,看看圖像的顯示情況。

for i in np.arange(0.1,1,0.1):
     u,sigma,v=np.linalg.svd(a[:,:,0])
     R=rebuild_img(u,sigma,v,i)
 
     u,sigma,v=np.linalg.svd(a[:,:,1])
     G=rebuild_img(u,sigma,v,i)
 
     u,sigma,v=np.linalg.svd(a[:,:,2])
     B=rebuild_img(u,sigma,v,i)
 
     I=np.stack((R,G,B),2)
     plt.subplot(330+i*10)
     plt.title(i)
     plt.imshow(I)
 
 plt.show()

爲了展示細節的丟失程度,特地找了一張細節豐富的圖像作爲試驗對象。原圖分辨率1920×724,見圖1.

 

                                                  圖 1    豐富細節的原始圖

圖2爲運行結果

                                                  圖 2     SVD分解後結果圖

可以看到,當sigma比例在0.5及以下時,能夠明顯察覺到圖片被壓縮的痕跡,但當sigma比例超過0.6時,細節的還原就比較好了,當0.7,0.8,0.9時,肉眼幾乎無法發現壓縮痕跡,證明了SVD作爲圖像壓縮算法,在細節丟失方面是可以控制得比較好的。在保持細節的前提下,可以將數據壓縮10%-30%左右。

最後,如果您有python /java /小程序/安卓/linux相關需求,可以通過微信公衆號聯繫我們。

微信公衆號:320科技工作室。

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