JPEG圖像壓縮算法流程詳解
JPEG代表Joint Photographic Experts Group(聯合圖像專家小組)。此團隊創立於1986年,1992年發布了JPEG的標准而在1994年獲得了ISO10918-1的認定。
JPEG是一種有損壓縮。
色彩空間轉換
圖片由RGB
色彩空間轉換到YUV
色彩空間,轉換關系如下
一般來說U,V是有符號的數字,但這里通過加上128,使其變為無符號數,方便存儲和計算
采樣
研究發現,人眼對亮度變換的敏感度比色彩變換的敏感度高。因此,可以認為Y分量比U,V分量更為重要。故采樣時通常會降低U,V
分量的采樣率,這里采用411采樣方式,即Y,U,V
三個分量的取樣比例為4:1:1,其含義為在2*2的單元中,Y
分量采樣4次,U,V
分量各采樣一次。這樣采樣的優點是雖然損失了一定精度,但也在人眼幾乎不可見的前提下減小了數據存儲量。
分塊
DCT變換是對8 * 8的子塊進行處理的,且U,V
分量在2 * 2的單元中采樣一次,故在DCT變換之前將原圖像長寬分別用0補齊到16的倍數。之后再對Y,U,V
三個分量分別分為8*8的塊便進行后續操作。
離散余弦變換
離散余弦變化的公式為
其中
由於已經明確每次進行離散余弦變化的矩陣大小為8*8,故這里不再采用上述方法進行離散余弦變換,而是利用DCT變換矩陣實現DCT變換以降低運算量。
DCT變換矩陣計算公式為
故8*8的DCT變換矩陣
其轉置矩陣
DCT可簡化為T * B * T',其中B為8*8的原矩陣。
實施二維DCT可將圖像的能量集中在極少的幾個系數之上,其他系數相比於這些系數,絕對值要小很多。這些系數大都集中在左上角,即低頻分量區。
數據量子化
量子化是JPEG算法中損失圖像精度的根源, 也是產生壓縮效果的源泉。
人類眼睛在一個相對大范圍區域,辨別亮度上細微差異是相當的好,但是在一個高頻率亮度變動之確切強度的分辨上,卻不是如此地好。這個事實讓我們能在高頻率成分上極佳地降低信息的數量。簡單地把頻率領域上每個成分,除以一個對於該成分的常量就可完成,且接着舍位取最接近的整數。這是整個過程中的主要有損運算。以這個結果而言,經常會把很多更高頻率的成分舍位成為接近0,且剩下很多會變成小的正或負數。
JPEG提供的量子化算法如下
其中G是我們需要處理的圖像矩陣,Q稱作量化系數矩陣 ,round函數是取整函數。JPEG算法提供了兩張標准的量化系數矩陣,分別用於處理亮度數據Y和色差數據U以及V。
標准亮度量化表
標准色差量化表
DCT系數矩陣中的不同位置的值代表了圖像數據中不同頻率的分量,這兩張表中的數據時人們根據人眼對不不同頻率的敏感程度的差別所積累下的經驗制定的,一般來說人眼對於低頻的分量比高頻分量更加敏感,所以兩張量化系數矩陣左上角的數值明顯小於右下角區域。 這樣就使得量化后的矩陣更多地保留高頻信息。
量化后的一個8*8矩陣:
通常一張圖片中的一個8*8矩陣經過上述變化之后,矩陣都如上矩陣一樣,其中的一大部分數據都會變成0,這非常有利於后面數據的壓縮。
編碼
差值編碼和Zig-zag掃描
量化后矩陣左上角的值被稱為直流分量DC,其他63個值被稱為交流分量AC。其中DC不參與Z字形掃描,而是與前一矩陣的DC系數進行差分編碼(DPCM);AC分量則采用Z字形掃描排列並進行游程長度編碼(RLE)。
游程長度編碼(Run-Length Encoding, RLE)
量化AC系數的特點是包含很多連續的0,故使用RLE對其進行編碼。JPEG使用了1個字節的高4位來表示連續的0的個數,而使用其低四位來表示下一個非0系數需要的位數,緊隨其后的是量化AC系數的值。
假設Zig-zag掃描后的一組向量的AC分量為
經RLE壓縮后如下
其中EOB
表示后面都是0。實際上,用(0,0)表示EOB
。若這組數字不以0結束,則不需要EOB
。
Huffman編碼
JEPG壓縮編碼時,通過查表實現霍夫曼編碼器,本次實驗中我使用了ISO/IEC International Standard 10918-1中JPEG推薦的典型霍夫曼表(Typical Huffman tables),我已經將4張表格發表在個人博客,篇幅所限這里就不再給出了。
之所以需要四張Huffman 編碼表是因為,編碼時每個矩陣數據的1個DC值與63個AC值分別使用不同的Huffman 編碼表,而且亮度Y與色度U,V也要使用不同的Huffman 編碼表。
為提高儲存效率,JEPEG里並不直接保存數值,而是將數值按實際值所需要的位數分成16組,如下表所示
Value | Size | Bits |
---|---|---|
0 | 0 | - |
-1, 1 | 1 | 0, 1 |
-3, -2, 2, 3 | 2 | 00, 01, 10, 11 |
-7, -6, -5, -4, 4, 5, 6, 7 | 3 | 000, 001, 010, 011, 100, 101, 110, 111 |
-15, …, -8, 8, …, 15 | 4 | 0000, …, 0111, 1000, …, 1111 |
-31, …, -16, 16, …, 31 | 5 | 0 0000, …, 0 1111, 1 0000, …, 1 1111 |
-63, …, -32, 32, …, 63 | 6 | 00 0000, …, …, 11 1111 |
-127, …, -64, 64, …, 127 | 7 | 000 0000, …, …, 111 1111 |
-255, …, -128, 128, …, 255 | 8 | 0000 0000, …, …, 1111 1111 |
-511, …, -256, 256, …, 511 | 9 | 0 0000 0000, …, …, 1 1111 1111 |
-1023, …, -512, 512, …, 1023 | 10 | 00 0000 0000, …, …, 11 1111 1111 |
-2047, …, -1024, 1024, …, 2047 | 11 | 000 0000 0000, …, …, 111 1111 1111 |
-4095, …, -2048, 2048, …, 4095 | 12 | 0000 0000 0000, …, …, 1111 1111 1111 |
-8191, …, -4096, 4096, …, 8191 | 13 | 0 0000 0000 0000, …, …, 1 1111 1111 1111 |
-16383, …, -8192, 8192, …, 16383 | 14 | 00 0000 0000 0000, …, …, 11 1111 1111 1111 |
-32767, …, -16348, 16348, …, 32767 | 15 | 000 0000 0000 0000, …, …, 111 1111 1111 1111 |
設一個一維化后的亮度的數據塊為
其中第一個數字代表本數據塊DC值與前一數據塊DC值之差為5。
那么RLE壓縮后的data變為
其中EOB = (0,0)。
對data'中每個數對的第二個數v求對應的s值,並將s置於數對中v之前,得到data''
其中第一個數對為DC分量運算得到的結果。
由於假設該以為數據由亮度數據塊變換得來,因此對於DC和AC分量,分別對data''數對中的第一個數字查Huffman DC亮度表和Huffman AC亮度表,再對數對中的第二個數字查上表,即可得到一維數據塊data編碼后的序列。data''查表得結果為
其中的標點是為了方便對照,實際編碼中沒有標點。
壓縮比
最終共用70973bit保存壓縮后的數據,壓縮前的數據大小為256 * 256 * 8+256 * 256/4 * 2 * 8 = 786432bit,故壓縮比為70973/786432 * 100% =9.02% 。
解碼
解碼過程為編碼過程的逆過程,這里不再贅述。
解碼后的圖片與原圖片比較
可以看出,處理后的圖片與原圖片有一定差異,推測差異是在量化和反量化過程中產生的。