1. 程式人生 > >JPEG壓縮原理與DCT離散余弦變換——有實際的數據演示

JPEG壓縮原理與DCT離散余弦變換——有實際的數據演示

數據表示 分享 nbsp http edi 公式 進行 基本上 那是

http://blog.csdn.net/newchenxf/article/details/51719597

1 前言

JPEG是joint Photographic Experts Group(聯合圖像專家組)的縮寫,文件後輟名為”.jpg”或”.jpeg”。
jpg圖片可以說是最常見的圖片格式了,基本上你的自拍照,要麽是png的,要麽就是jpeg的了。(有關jpeg和png的區別,請參考我的另一博文【jpeg 與 png 圖片格式的區別】)
但它是一種有損壓縮。支持多種壓縮級別,壓縮比率通常在10:1到40:1之間,壓縮比越大,品質就越低;相反地,壓縮比越小,品質就越好。

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

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

2 JPEG壓縮流程

2.1 以8x8的圖象塊為基本單位進行編碼

如下圖所示。比如一個160x160大小的原始圖像,就可以分成20x20個8x8圖像塊。
技術分享
每個圖像塊共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定義
技術分享
其中:0<= u, v < 8
技術分享
a(v) = a(u)
技術分享 是輸入8x8像素的坐標。
技術分享 是輸出的8x8變換結果的坐標。

不要把上式看的有多難,也不要被“離散余弦變換”這個詞給嚇到,其實他沒什麽(如果你非要去追究,那就打開“信號與系統”的書復習一下吧,我攔不住你哈),上式其實就是一個運算公式而已。
輸入就是8x8的數據矩陣,經過計算,輸出還是一個8x8的數據矩陣。
其實上式可以簡化為:
技術分享


並且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公式:
技術分享
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形編碼。
技術分享
你要是不理解,看看下面的例子,就知道為啥ZIG-ZAG可以俘獲更多的0了!

3 應用舉例

3.1 編碼

某個圖象的一個8*8方塊,的亮度值。
技術分享

由於一個字節是0~255,為了減小絕對值波動,先把數值移位一下,變成-128~127。
技術分享

接著,根據DCT變換公式,各種計算,獲得臨時結果。
技術分享

根據亮度量化表量化後得到的量化系數矩陣
技術分享

獲得量化結果:
技術分享

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

3.2 解碼

先遊程編碼恢復為
技術分享

然後,根據量化表,恢復
技術分享

再根據反離散余弦變換的公式:
技術分享

結果為:
技術分享

再右移127,恢復原始。
技術分享

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

4 其他

必須再強調的是,JPEG壓縮是有損失的,從上面的例子就看出來,輸出結果並不是完全等於輸入。
此外,JPEG壓縮比例是可以控制的,只不過圖像質量會變差。比如
壓縮率:10
技術分享

壓縮率:50
技術分享

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

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

JPEG壓縮原理與DCT離散余弦變換——有實際的數據演示