天天看點

DCT 離散餘弦變換 原理與應用講解

1 前言

JPEG是joint Photographic Experts Group(聯合圖像專家組)的縮寫,檔案後辍名為”.jpg”或”.jpeg”。 

jpg圖檔可以說是最常見的圖檔格式了,基本上你的自拍照,要麼是png的,要麼就是jpeg的了。(有關jpeg和png的差別,請參考我的另一博文【jpeg 與 png 圖檔格式的差別】) 

但它是一種有損壓縮。支援多種壓縮級别,壓縮比率通常在10:1到40:1之間,壓縮比越大,品質就越低;相反地,壓縮比越小,品質就越好。

那麼,JPEG是如何壓縮的呢?靠的就是傳說中的DCT(離散餘弦變換)。

下圖是JPEG壓縮/解壓縮的流程圖。我想你最大的疑問估計就是DCT了。 

DCT 離散餘弦變換 原理與應用講解

2 JPEG壓縮流程

2.1 以8x8的圖象塊為基本機關進行編碼

如下圖所示。比如一個160x160大小的原始圖像,就可以分成20x20個8x8圖像塊。 

DCT 離散餘弦變換 原理與應用講解

每個圖像塊共64個像素。像素可以用RGB或YUV表示,需要3個byte。是以嚴格來說,上圖3個箭頭代表的資料,指的是RGB/YUV的某一個值,比如Y。

2.2 将RGB轉換為亮度-色調-飽和度系統(YUV),并重新采樣

YUV是什麼?它也是一種很不錯的圖像資料表示方法,特别是在視訊領域。 

Y:指顔色的明視度、亮度、灰階值; 

U:指色調; 

V:指飽和度。

YUV是一個統稱,其實有很多具體格式,比如YUV420, YUV444, YUV422。 

YUV的某些格式,和RGB比起來,其資料量要少很多。 

比如YUV420,每個像素需要一個Y,每4個像素需要一個U/V,是以一個8*8圖像塊,資料量隻要8x8x3/2 = 96byte。而RGB需要8x8x3 = 192byte。少了一半的資料量。現在很多視訊都是YUV420作為色域。 

當然啦,在本次轉換,用的是YUV444, 也就是每個像素都有YUV的值。

YUV與RGB可以互相轉換。 

Y=0.299R+0.587G+0.114B 

U=0.148R-0.289G+0.473B 

V=0.615R-0.515G-0.1B

2.3 FDCT與IDCT

一個是正變換,一個是逆變換。反正都可以稱為離散餘弦變換。 

根據8*8的二維DCT定義

DCT 離散餘弦變換 原理與應用講解

 其中:0<= u, v < 8 

DCT 離散餘弦變換 原理與應用講解

 a(v) = a(u) 

DCT 離散餘弦變換 原理與應用講解

是輸入8x8像素的坐标。

DCT 離散餘弦變換 原理與應用講解

是輸出的8x8變換結果的坐标。

不要把上式看的有多難,也不要被“離散餘弦變換”這個詞給吓到,其實他沒什麼(如果你非要去追究,那就打開“信号與系統”的書複習一下吧,我攔不住你哈),上式其實就是一個運算公式而已。

輸入就是8x8的資料矩陣,經過計算,輸出還是一個8x8的資料矩陣。

其實上式可以簡化為:

DCT 離散餘弦變換 原理與應用講解

并且A和A轉置矩陣都是已知的。是以,說白了,就是個矩陣運算。對程式來說,很簡單。

稱G(0,0),也就是輸出8x8矩陣的(0,0)坐标的值,為直流系數,其他為交流系數。 

之是以稱它為直流系數,是因為當u, v = 0時,cos()結果都為0,是以最後結果就是輸入矩陣的8x8的每個數值的和,再乘于a(u) x a(v) x 1/4 = 1/8。

當然了,輸入資料其實是有3個的,也就是YUV,是以對每個8x8的原始圖像資料,需要做3次DCT。

2.4 量化與反量化

定義:将DCT變換後的臨時結果,除以各自量化步長并四舍五入後取整,得到量化系數。 

為什麼可以量化?! 

因為經過DCT後,資料就不同了,左上方都是大數值,右下方都是小數值。比如左上方都是幾十幾百的,右下方附近,都是個位數,那麼,大數值和小數值就可以分别量化。

在術語裡,左上方稱為低頻資料,右下方稱為高頻資料。 

你要是不了解,可以這麼想,既然G(0,0)都是直流分量了,那頻率不就是0?不就是所謂的低頻?^^

還是不了解?好吧,那你也可以這麼想: 

比如cos(ax),a是常數,x是變量。那麼,根據頻率f = a/2π,a越大,函數的頻率越高。 

看看DCT公式: 

DCT 離散餘弦變換 原理與應用講解

u,v 越大,則越在右下方對吧。當計算某個G(u, v)時,x, y是變量,u, v相當于常數,當u/v越大,則頻率越高! 

這就是為啥右下方稱為高頻資料了!

好了,别走偏了,還繼續說量化。 

JPEG系統分别規定了亮度分量和色度分量的量化表,色度分量相應的量化步長比亮度分量大。

對量化系數的處理群組織 

思想:JPEG采用定長和變長相結合的編碼方法。 

直流系數:通常相鄰8*8圖象塊的DC分量很接近,是以JPEG對量化後的直流分量采用無失真DPCM編碼。通常JPEG要儲存所需比特數和實際內插補點。

交流系數:經過量化後,AC分量出現較多的0。JPEG采用對0系數的行程長度編碼。而對非0值,則要儲存所需數和實際值。 

ZIG-ZAG排序:為使連續的0個數增多,采用Z形編碼。 

DCT 離散餘弦變換 原理與應用講解

你要是不了解,看看下面的例子,就知道為啥ZIG-ZAG可以俘獲更多的0了!

3 應用舉例

3.1 編碼

某個圖象的一個8*8方塊,的亮度值。 

DCT 離散餘弦變換 原理與應用講解

 由于一個位元組是0~255,為了減小絕對值波動,先把數值移位一下,變成-128~127。 

DCT 離散餘弦變換 原理與應用講解

 接着,根據DCT變換公式,各種計算,獲得臨時結果。 

DCT 離散餘弦變換 原理與應用講解

 根據亮度量化表量化後得到的量化系數矩陣 

DCT 離散餘弦變換 原理與應用講解

 獲得量化結果:

DCT 離散餘弦變換 原理與應用講解

 可見,新的資料,很小,很多是0。正如上文所說,這麼多0,完全可以用遊程編碼,大大縮小資料量。

3.2 解碼

先遊程編碼恢複為 

DCT 離散餘弦變換 原理與應用講解

 然後,根據量化表,恢複 

DCT 離散餘弦變換 原理與應用講解

 再根據反離散餘弦變換的公式: 

DCT 離散餘弦變換 原理與應用講解

 結果為: 

DCT 離散餘弦變換 原理與應用講解

 再右移127,恢複原始。 

DCT 離散餘弦變換 原理與應用講解

 和原始圖像的資料相比,基本是一樣的,或者近似的!

4 其他

必須再強調的是,JPEG壓縮是有損失的,從上面的例子就看出來,輸出結果并不是完全等于輸入。 

此外,JPEG壓縮比例是可以控制的,隻不過圖像品質會變差。比如 

壓縮率:10 

DCT 離散餘弦變換 原理與應用講解

 壓縮率:50 

DCT 離散餘弦變換 原理與應用講解

JPEG壓縮比例,就是通過控制量化的多少來控制。比如,上面的量化矩陣Q,如果我把矩陣的每個數都double一下,那是不是會出現更多的0?!說不定都隻有G(0, 0)非0,其他都是0,如果這樣,那編碼時就可以更省空間啦,N個0隻要一個遊程編碼搞定,資料量超小。但也意味着,恢複時,會帶來更多的誤差,圖像品質也會變差了。

參考: 

https://en.wikipedia.org/wiki/JPEG#Discrete_cosine_transform