2012-03-12 23 views
4

我試圖使用奇異值分解壓縮給定的圖像。我想我已經擁有了它,直到我注意到我在整個過程中不斷出現垃圾顏色的像素。嘗試壓縮圖像時出現彩色像素(包括圖片)

Garbage pixels

在右上部示出的數字表示迭代次數,其中0是原始圖像。

這是一個常見錯誤?有什麼我失蹤?

我想這可能與我的數學本身有關。我正在使用JAMA,這是一個爲我處理這個問題的java矩陣包。下面是我執行每次迭代:

for (int i = 0; i < k; i++) {  
    Matrix step = (uColumns[i].times(sValues[i])).times(vColumns[i].transpose()); 
    encoded = encoded.plus(step); 
} 

基本上我做(或試圖做)什麼是:

M = M + (s1*u1*v1^t) 

有什麼明顯錯誤與我的實現,或者是錯誤可能由於JAMA執行SVD的方式?從我測試的結果來看,矩陣U和V中的值的符號與Wolframalpha或Matlab生成的行有所不同。

任何幫助表示讚賞。

感謝,

瑞斯蒂昂

+0

我不知道這個庫是否適用於SVD,我曾經在C#中使用過一個,從來沒有在Java中做過這樣的程序,但我認爲它可以只是壓縮結果。您是否將結果與使用類似壓縮方法的其他結果進行比較? – HericDenis 2012-11-05 11:20:53

+0

白色像素是否可以由上溢/下溢引起?例如,最初爲黑色(0)的像素由於有損壓縮而變爲-0.01,該值被舍入爲-1,然後在屏幕上變爲255。 – 2012-11-20 07:36:07

回答

2

這是您的圖片分解成原色:

Lena SVD decomposed to RGB

顯然要轉換的顏色數和數字的顏色以錯誤的方式。您將RGB像素視爲單個數值並將其傳遞給SVD數值過程,但實際上RGB的信息已丟失。

大多數有損圖像壓縮方法通過丟棄低有效位來實現壓縮。但是當你在一個單獨的RGB中使用RGB時,每個R,G和B的低有效位與高有效位交織。當將像素作爲單個數值傳遞時,該信息丟失,並且SVD過程有效地將低顯着性R位解釋爲比高顯着性G位更重要,並且可能試圖完全丟棄所有G和B位,因爲它們完全是因爲它們在「R位之後」存儲。

例如,淺灰色像素(192,192,192)的RGB值爲0xC0C0C0。以1%的錯誤壓縮此值可能會產生,例如,0xC2AE32。從壓縮算法的角度來看,這個值只比原始數據大1%,幾乎不明顯。但將其轉換回RGB(194,174,50)。 R組件確實幾乎相同,但G和B已損壞。這是程序中「垃圾顏色」的來源。分解圖像顯示R分量被正確壓縮,G分量在高壓縮級別變成隨機噪聲,並且B分量總是隨機的。

實現中的另一個問題是散射在黑暗區域的單個亮像素。這些顯然是由數字溢出和下溢造成的。例如,黑色像素(0,0,0)被編碼爲0x000000 = 0;有損壓縮會引入一個小錯誤,可能是正數或負數,並且可能產生-1 = 0xFFFFFFFF;在RGB中它變成(255,255,255),它是白色的。

怎麼辦?

如果您只是測試SVD圖像壓縮並且足夠使用灰度圖像,那麼您應該簡單地從RGB值中取低位字節,範圍從0到255.相應地,顯示結果時或寫入輸出文件,將此值解釋爲灰度,或乘以0x010101以獲得完整的RGB值。

如果需要壓縮的彩色圖像,應分別在R,G和B分量運行SVD算法。這是處理顏色最簡單的方法,但不是最有效的方法。爲了獲得更高的壓縮率和不明顯的僞影,最好將RGB轉換爲Lab(亮度和兩個色度通道);色度可以被壓縮得更多,這就是JPEG的工作方式。

解壓縮圖像時,在計算SVD值之後但在屏幕上顯示或寫入文件之前,將所有結果值(R,G和B)限制在0-255範圍內。這將消除散落的白點。