JPEG簡介
JPEG 是Joint Photographic Experts Group(聯(lián)合圖像專家小組)的縮寫,是第一個國際圖像壓縮標準。JPEG圖像壓縮算法能夠在提供良好的壓縮性能的同時,具有比較好的重建質量,被廣泛應用于圖像、視頻處理領域。人們日常碰到的“.jpeg”、‘’.jpg“等指代的是圖像數(shù)據經壓縮編碼后在媒體上的封存形式,不能與JPEG壓縮標準混為一談。
JPEG優(yōu)缺點
優(yōu)點:攝影作品或寫實作品支持高級壓縮。
利用可變的壓縮比可以控制文件大小。支持交錯(對于漸近式JPEG文件)。廣泛支持Internet標準。
缺點:有損耗壓縮會使原始圖片數(shù)據質量下降。
當您編輯和重新保存JPEG文件時,JPEG會混合原始圖片數(shù)據的質量下降。這種下降是累積性的。JPEG不適用于所含顏色很少、具有大塊顏色相近的區(qū)域或亮度差異十分明顯的較簡單的圖片。
JPEG壓縮標準
JPEG(Joint Photographic Experts Group)是一個由ISO/IEC JTC1/SC2/WG8和CCITT VIII/NIC于1986年底聯(lián)合組成的一個專家組,負責制定靜態(tài)的數(shù)字圖像數(shù)據壓縮編碼標準。迄今為止,該組織已經指定了3個靜止圖像編碼標準,分別為JPEG、JPEG-LS和JPEG2000。這個專家組于1991年前后指定完畢第一個靜止圖像壓縮標準JPEG標準,并且成為國際上通用的標準。JPEG標準是一個適用范圍很廣的靜態(tài)圖像數(shù)據壓縮標準,既可用于灰度圖像又可用于彩色圖像。
JPEG專家組開發(fā)了兩種基本的靜止圖像壓縮算法,一種是采用以離散余弦變換(Discrete Cosine Transform, DCT)為基礎的有損壓縮算法,另一種是采用以預測技術為基礎的無損壓縮算法。使用無損壓縮算法時,其壓縮比比較低,但可保證圖像不失真。使用有損壓縮算法時,其算法實現(xiàn)較為復雜,但其壓縮比大,按25:1壓縮后還原得到的圖像與原始圖像相比較,非圖像專家難于找出它們之間的區(qū)別,因此得到了廣泛的應用。
JPEG有4種工作模式,分別為順序編碼,漸近編碼,無失真編碼和分層編碼,他們有各自的應用場合,其中基于順序編碼工作模式的JPEG壓縮系統(tǒng)也稱為基本系統(tǒng),該系統(tǒng)采用單遍掃描完成一個圖像分量的編碼,掃描次序從左到右、從上到下,基本系統(tǒng)要求圖像像素的各個色彩分量都是8bit,并可通過量化線性地改變DCT系統(tǒng)的量化結果來調整圖像質量和壓縮比。下面介紹圖像壓縮采用基于DCT的順序模式有損壓縮算法,該算法下的JPEG壓縮為基本系統(tǒng)。
JPEG壓縮基本系統(tǒng)編碼器
JPEG壓縮是有損壓縮,它利用了人的視覺系統(tǒng)的特性,將量化和無損壓縮編碼相結合來去掉視覺的冗余信息和數(shù)據本身的冗余信息?;诨鞠到y(tǒng)的JPEG壓縮編碼器框圖如圖1所示,該編碼器是對單個圖像分量的處理,對于多個分量的圖像,則首先應將圖像多分量按照一定順序和比例組成若干個最小壓縮單元(MCU),然后同樣按該編碼器對每個MCU各個分量進行獨立編碼處理,最終圖像壓縮數(shù)據將由多個MCU壓縮數(shù)據組成。
圖1 JPEG壓縮編碼器結構框圖
JPEG壓縮主要步驟如下:
?。?)圖像壓縮預處理;
?。?)正向離散余弦變換(FDCT);
?。?)DCT系數(shù)量化;
?。?)編碼
JPEG圖像壓縮算法流程詳解
在實際應用中,JPEG圖像編碼算法使用的大多是離散余弦變換、Huffman編碼、順序編碼模式。這樣的方式,被人們稱為JPEG的基本系統(tǒng)。這里介紹的JPEG編碼算法的流程,也是針對基本系統(tǒng)而言?;鞠到y(tǒng)的JPEG壓縮編碼算法一共分為11個步驟:顏色模式轉換、采樣、分塊、離散余弦變換(DCT)、Zigzag 掃描排序、量化、DC系數(shù)的差分脈沖調制編碼、DC系數(shù)的中間格式計算、AC系數(shù)的游程長度編碼、AC系數(shù)的中間格式計算、熵編碼。下面,將一一介紹這11個步驟的詳細原理和計算過程。
(1)顏色模式轉換
JPEG采用的是YCrCb顏色空間,而BMP采用的是RGB顏色空間,要想對BMP圖片進行壓縮,首先需要進行顏色空間的轉換。YCrCb顏色空間中,Y代表亮度,Cr,Cb則代表色度和飽和度(也有人將Cb,Cr兩者統(tǒng)稱為色度),三者通常以Y,U,V來表示,即用U代表Cb,用V代表Cr。RGB和YCrCb之間的轉換關系如下所示:
Y = 0.299R+0.587G+0.114B
Cb = -0.1687R-0.3313G+0.5B+128
Cr = 0.5R=0.418G-0.0813B+128
一般來說,C 值 (包括 Cb Cr) 應該是一個有符號的數(shù)字, 但這里通過加上128,使其變?yōu)?位的無符號整數(shù),從而方便數(shù)據的存儲和計算。
R = Y+1.402(Cr-128)
G = Y-0.34414(Cb-128)-0.71414(Cr-128)
B = Y+1.772(Cb-128)
?。?)采樣
研究發(fā)現(xiàn),人眼對亮度變換的敏感度要比對色彩變換的敏感度高出很多。因此,我們可以認為Y分量要比Cb,Cr分量重要的多。在BMP圖片中,RGB三個分量各采用一個字節(jié)進行采樣,也就是我們常聽到的RGB888的模式;而JPEG圖片中,通常采用兩種采樣方式:YUV411和YUV422,它們所代表的意義是Y,Cb,Cr三個分量的數(shù)據取樣比例一般是4:1:1或者4:2:2(4:1:1含義就是:在2x2的單元中,本應分別有4個Y,4個U,4個V值,用12個字節(jié)進行存儲。經過4:1:1采樣處理后,每個單元中的值分別有4個Y、1個U、1個V,只要用6個字節(jié)就可以存儲了)。這樣的采樣方式,雖然損失了一定的精度但也在人眼不太察覺到的范圍內減小了數(shù)據的存儲量。當然,JPEG格式里面也允許將每個點的U,V值都記錄下來;
(3)分塊
由于后面的DCT變換是是對8x8的子塊進行處理的,因此,在進行DCT變換之前必須把源圖象數(shù)據進行分塊。源圖象中每點的3個分量是交替出現(xiàn)的,先要把這3個分量分開,存放到3張表中去。然后由左及右,由上到下依次讀取8x8的子塊,存放在長度為64的表中,即可以進行DCT變換。注意,編碼時,程序從源數(shù)據中讀取一個8x8的數(shù)據塊后,進行DCT變換,量化,編碼,然后再讀取、處理下一個8*8的數(shù)據塊。
JPEG 編碼是以每8x8個點為一個單位進行處理的。 所以如果原始圖片的長寬不是 8 的倍數(shù), 都需要先補成8的倍數(shù), 使其可以進行一塊塊的處理。將原始圖像數(shù)據分為8*8的數(shù)據單元矩陣之后,還必須將每個數(shù)值減去128,然后一一帶入DCT變換公式,即可達到DCT變換的目的。圖像的數(shù)據值必須減去128,是因為DCT公式所接受的數(shù)字范圍是-128到127之間。
?。?)離散余弦變換
DCT(Discrete Cosine Transform,離散余弦變換),是碼率壓縮中常用的一種變換編碼方法。任何連續(xù)的實對稱函數(shù)的傅里葉變換中只含有余弦項,因此,余弦變換同傅里葉變換一樣具有明確的物理意義。DCT是先將整體圖像分成N*N的像素塊,然后針對N*N的像素塊逐一進行DCT操作。需要提醒的是,JPEG的編碼過程需要進行正向離散余弦變換,而解碼過程則需要反向離散余弦變換。
正向離散余弦變換計算公式:
這里的N是水平、垂直方向的像素數(shù)目,一般取值為8。8*8的二維像素塊經過DCT操作之后,就得到了8*8的變換系數(shù)矩陣。這些系數(shù),都有具體的物理含義,例如,U=0,V=0時的F(0,0)是原來的64個數(shù)據的均值,相當于直流分量,也有人稱之為DC系數(shù)或者直流系數(shù)。隨著U,V的增加,相另外的63個系數(shù)則代表了水平空間頻率和垂直空間頻率分量(高頻分量)的大小,多半是一些接近于0的正負浮點數(shù),我們稱之為交流系數(shù)AC。DCT變換后的8*8的系數(shù)矩陣中,低頻分量集中在矩陣的左上角。高頻成分則集中在右下角。
這里,我們暫時先只考慮水平方向上一行數(shù)據(8個像素)的情況時的DCT變換,從而來說明其物理意義。如下圖所示:
原始的圖像信號(最左邊的波形)經過DCT變換之后變成了8個波,其中第一個波為直流成分,其余7個為交流成分。
可見圖像信號被分解為直流成分和一些從低頻到高頻的各種余弦成分。而DCT系數(shù)只表示了該種成分所占原圖像信號的份額大小。顯然,恢復圖像信息可以表示為下面的式子:
F(n) = C(n)*E(n),這里,E(n)是一個基底,C(n)是DCT系數(shù),F(xiàn)(n)則是圖像信號;如果考慮垂直方向的變化,那就需要一個二維的基底。大學里面的信號處理,傅里葉變換等課程上也講過,任何信號都可以被分解為基波和不同幅度的諧波的組合,而DCT變換的物理意義也正是如此。
由于大多數(shù)圖像的高頻分量比較小,相應的圖像高頻分量的DCT系數(shù)經常接近于0,再加上高頻分量中只包含了圖像的細微的細節(jié)變化信息,而人眼對這種高頻成分的失真不太敏感,所以,可以考慮將這一些高頻成分予以拋棄,從而降低需要傳輸?shù)臄?shù)據量。這樣一來,傳送DCT變換系數(shù)的所需要的編碼長度要遠遠小于傳送圖像像素的編碼長度。到達接收端之后通過反離散余弦變換就可以得到原來的數(shù)據,雖然這么做存在一定的失真,但人眼是可接受的,而且對這種微小的變換是不敏感的。
?。?)Zigzag掃描排序
DCT 將一個 8x8 的數(shù)組變換成另一個 8x8 的數(shù)組。 但是內存里所有數(shù)據都是線形存放的, 如果我們一行行的存放這 64 個數(shù)字, 每行的結尾的點和下行開始的點就沒有什么關系, 所以 JPEG 規(guī)定按如下圖中的數(shù)字順序依次保存和讀取64 個DCT的系數(shù)值。
這樣數(shù)列里的相鄰點在圖片上也是相鄰的了。不難發(fā)現(xiàn),這種數(shù)據的掃描、保存、讀取方式,是從8*8矩陣的左上角開始,按照英文字母Z的形狀進行掃描的,一般將其稱之為Zigzag掃描排序。如下圖所示:
?。?)量化
圖像數(shù)據轉換為DCT頻率系數(shù)之后,還要進行量化階段,才能進入編碼過程。量化階段需要兩個8*8量化矩陣數(shù)據,一個是專門處理亮度的頻率系數(shù),另一個則是針對色度的頻率系數(shù),將頻率系數(shù)除以量化矩陣的值之后取整,即完成了量化過程。當頻率系數(shù)經過量化之后,將頻率系數(shù)由浮點數(shù)轉變?yōu)檎麛?shù),這才便于執(zhí)行最后的編碼。不難發(fā)現(xiàn),經過量化階段之后,所有的數(shù)據只保留了整數(shù)近似值,也就再度損失了一些數(shù)據內容。在JPEG算法中,由于對亮度和色度的精度要求不同,分別對亮度和色度采用不同的量化表。前者細量化,后者粗量化。
下圖給出JPEG的亮度量化表和色度量化表,該量化表是從廣泛的實驗中得出的。當然,你也可以自定義量化表。
這兩張表依據心理視覺閥制作, 對 8bit 的亮度和色度的圖象的處理效果不錯。量化表是控制 JPEG 壓縮比的關鍵,這個步驟除掉了一些高頻量, 損失了很多細節(jié)信息。但事實上人眼對高頻信號的敏感度遠沒有低頻信號那么敏感。所以處理后的視覺損失很小,從上面的量化表也可以看出,低頻部分采用了相對較短的量化步長,而高頻部分則采用了相對較長的量化步長,這樣做,也是為了在一定程度上得到相對清晰的圖像和更高的壓縮率。另一個重要原因是所有的圖片的點與點之間會有一個色彩過渡的過程,而大量的圖象信息被包含在低頻率空間中,經過DCT處理后, 在高頻率部分, 將出現(xiàn)大量連續(xù)的零。
?。?)DC系數(shù)的差分脈沖調制編碼
8*8的圖像塊經過DCT變換之后得到的DC系數(shù)有兩個特點:
?。?)系數(shù)的數(shù)值比較大;
?。?)相鄰的8*8圖像塊的DC系數(shù)值變化不大;
根據這兩個特點,DC系數(shù)一般采用差分脈沖調制編碼DPCM(Difference Pulse Code Modulation),即:取同一個圖像分量中每個DC值與前一個DC值的差值來進行編碼。對差值進行編碼所需要的位數(shù)會比對原值進行編碼所需要的位數(shù)少了很多。假設某一個8*8圖像塊的DC系數(shù)值為15,而上一個8*8圖像塊的DC系數(shù)為12,則兩者之間的差值為3。
?。?)DC系數(shù)的中間格式計算
JPEG中為了更進一步節(jié)約空間,并不直接保存數(shù)據的具體數(shù)值,而是將數(shù)據按照位數(shù)分為16組,保存在表里面。這也就是所謂的變長整數(shù)編碼VLI。即,第0組中保存的編碼位數(shù)為0,其編碼所代表的數(shù)字為0;第1組中保存的編碼位數(shù)為1,編碼所代表的數(shù)字為-1或者1.。。.。。,如下面的表格所示,這里,暫且稱其為VLI編碼表:
前面提到的那個DC差值為3的數(shù)據,通過查找VLI可以發(fā)現(xiàn),整數(shù)3位于VLI表格的第2組,因此,可以寫成(2)(3)的形式,該形式,稱之為DC系數(shù)的中間格式。
(9)AC系數(shù)的行程長度編碼(RLC)
量化之后的AC系數(shù)的特點是,63個系數(shù)中含有很多值為0的系數(shù)。因此,可以采用行程編碼RLC(Run Length Coding)來更進一步降低數(shù)據的傳輸量。利用該編碼方式,可以將一個字符串中重復出現(xiàn)的連續(xù)字符用兩個字節(jié)來代替,其中,第一個字節(jié)代表重復的次數(shù),第二個字節(jié)代表被重復的字符串。例如,(4,6)就代表字符串“6666”。但是,在JPEG編碼中,RLC的含義就同其原有的意義略有不同。在JPEG編碼中,假設RLC編碼之后得到了一個(M,N)的數(shù)據對,其中M是兩個非零AC系數(shù)之間連續(xù)的0的個數(shù)(即,行程長度),N是下一個非零的AC系數(shù)的值。采用這樣的方式進行表示,是因為AC系數(shù)當中有大量的0,而采用Zigzag掃描也會使得AC系數(shù)中有很多連續(xù)的0的存在,如此一來,便非常適合于用RLC進行編碼。
例如,現(xiàn)有一個字符串,如下所示:
57,45,0,0,0,0,23,0,-30,-8,0,0,1,000.。。.。
經過RLC之后,將呈現(xiàn)出以下的形式:
(0,57) ; (0,45) ; (4,23) ; (1,-30) ; (0,-8) ; (2,1) ; (0,0)
注意,如果AC系數(shù)之間連續(xù)0的個數(shù)超過16,則用一個擴展字節(jié)(15,0)來表示16連續(xù)的0。
?。?0)AC系數(shù)的中間格式
根據前面提到的VLI表格,對于前面的字符串:
?。?,57) ; (0,45) ; (4,23) ; (1,-30) ; (0,-8) ; (2,1) ; (0,0)
只處理每對數(shù)右邊的那個數(shù)據,對其進行VLI編碼: 查找上面的VLI編碼表格,可以發(fā)現(xiàn),57在第6組當中,因此,可以將其寫成(0,6),57的形式,該形式,稱之為AC系數(shù)的中間格式。
同樣的(0,45)的中間格式為:(0,6),45;
?。?,-30)的中間格式為:(1,5),-30;
?。?1)熵編碼
在得到DC系數(shù)的中間格式和AC系數(shù)的中間格式之后,為進一步壓縮圖象數(shù)據,有必要對兩者進行熵編碼。JPEG標準具體規(guī)定了兩種熵編碼方式:Huffman編碼和算術編碼。JPEG基本系統(tǒng)規(guī)定采用Huffman編碼(因為不存在專利問題),但JPEG標準并沒有限制JPEG算法必須用Huffman編碼方式或者算術編碼方式。
Huffman編碼:對出現(xiàn)概率大的字符分配字符長度較短的二進制編碼,對出現(xiàn)概率小的字符分配字符長度較長的二進制編碼,從而使得字符的平均編碼長度最短。Huffman編碼的原理請參考數(shù)據結構中的Huffman樹或者最優(yōu)二叉樹。
Huffman編碼時DC系數(shù)與AC系數(shù)分別采用不同的Huffman編碼表,對于亮度和色度也采用不同的Huffman編碼表。因此,需要4張Huffman編碼表才能完成熵編碼的工作。具體的Huffman編碼采用查表的方式來高效地完成。然而,在JPEG標準中沒有定義缺省的Huffman表,用戶可以根據實際應用自由選擇,也可以使用JPEG標準推薦的Huffman表。或者預先定義一個通用的Huffman表,也可以針對一副特定的圖像,在壓縮編碼前通過搜集其統(tǒng)計特征來計算Huffman表的值。
下面我們舉例來說明8*8圖像子塊經過DCT及量化之后的處理過程:
假設一個圖像塊經過量化以后得到以下的系數(shù)矩陣:
15 0 -1 0 0 0 0 0
-2 -1 0 0 0 0 0 0
-1 -1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
顯然,DC系數(shù)為15,假設前一個8*8的圖像塊的DC系數(shù)量化值為12,則當前DC系統(tǒng)同上一個DC系數(shù)之間的差值為3,通過查找VLI編碼表,可以得到DC系數(shù)的中間格式為(2)(3),這里的2代表后面的數(shù)字(3)的編碼長度為2位;之后,通過Zigzag掃描之后,遇到第一個非0的AC系數(shù)為-2,遇到0的個數(shù)為1,AC系數(shù)經過RLC編碼后可表示為(1,-2),通過查找VLI表發(fā)現(xiàn),-2在第2組,因此,該AC系數(shù)的中間格式為(1,2)-2;
其余的點類似,可以求得這個8*8子塊熵編碼的中間格式為
?。―C)(2)(3);AC(1,2)(-2),(0,1)(-1),(0,1)(-1),(0,1)(-1),(2,1)(-1),(EOB)(0,0)
對于DC系數(shù)的中間格式(2)(3)而言,數(shù)字2查DC亮度Huffman表得到011,數(shù)字3通過查找VLI編碼表得到其被編碼為11;
對于AC系數(shù)的中間格式(1,2)(-2)而言,(1,2)查AC亮度Huffman表得到11011,-2通過查找VLI編碼表得到其被編碼為01;
對于AC系數(shù)的中間格式(0,1)(-1)而言,(0,1)查AC亮度Huffman表得到00,數(shù)字-1通過查找VLI編碼表得到其被編碼為0;
對于AC系數(shù)的中間格式(2,1)(1)而言,(2,1)查AC亮度Huffman表得到11100,數(shù)字-1通過查找VLI編碼表得到其被編碼為0;
對于AC系數(shù)的中間格式(0,0)而言,查AC亮度Huffman表得到1010;
因此,最后這個8*8子塊亮度信息壓縮后的數(shù)據流為01111,1101101,000,000,000,111000,1010??偣?1比特,其壓縮比是64*8/31=16.5,大約每個像素用半個比特。
評論