JPG的工作原理

轉載請註明出處:(http://www.jianshu.com/p/934269064bfb)
本篇文章翻譯自谷歌出的優化視頻裏面的光頭佬(Colt McAnlis),原文地址需翻牆, 以下正文:

JPG格式是1992年出現的最先進的圖片壓縮技術之一。此後,它就成爲互聯網圖片的主力。這當然和JPG背後的技術有關,JPG的工作原理異常複雜,它需要深入理解人眼是如何調整對色彩和圖像邊緣的感知。

在研究這些東西前(你也一樣,如果你在閱讀此文),我想把JPG的編碼原理分解成幾部分,這樣我們就可以更好的理解怎麼製作更小的JPG文件。

概要

JPG的壓縮方案被分成幾個步驟,下圖很好的把它們展示出來,我們接下來會對每個步驟作詳細介紹。

1.png

色彩空間轉換

有損數據壓縮的一個關鍵原則是:人類的感知能力沒有計算機的精確。科學證明,人的眼睛只能區分1000萬種不同的顏色。然而,還有很多東西會影響人眼對色彩的感知,明顯的突出色彩錯覺,又或你應該還記得去年這件衣服把互聯網都炸開了。這裏的重點是人眼可以很好的控制它所感知的顏色。

量化是有損壓縮種的一種形式,不過JPG使用的是一種不同的方式:顏色模型。一個色彩空間是一個特定的顏色組織,它的顏色模型代表了這些顏色表示的數學公式。(例如三顏色RGB,或者CMYK)

這個過程的強大之處是,你可以把一個顏色模型轉換成另外一個,這意味着你可以將一個給定顏色的數學表達式轉成一組完全不同的值。

例如,下面這種的顏色,它可以用RGB和CMYK兩張不同的顏色模型指替,它們對於人眼來說是一樣的顏色,但卻可以被表示成不同的數值集。

2.png

將JPG從RGB顏色模型轉換成Y,Cb,Cr顏色模型,包括亮度(Y)、色度藍(CB)和色度紅(CR)。這樣做的原因,是心理視覺實驗(又名:大腦處理如何處理眼睛看到的信息)表明,人眼對亮度色度更敏感,這意味着我們會忽略掉較大的色度變化,而不影響我們對圖片的感知。因此,我們可以在人眼察覺前對CbCr通道使勁的壓縮。

3.png

縮減取樣

YCbCr顏色空間其中一個有趣的細節是,Cb/Cr通道有比較少的顆粒度細節,也就是說它們包含的信息沒有Y通道的多。所以JPG的算法就把Cb和Cr通道的大小縮減到原來的1/4(注意,在具體的處理上會有些細微的差別,但我這裏就不展開了…),這種做法就叫做縮減取樣

有一件很重要的事需要說明,縮減取樣是一個有損壓縮過程(壓縮過後你無法恢復回原來的顏色,只能得到一個近視的值),但對人類視覺皮層的可視化組件的整體影響是最小的。由於我們沒有對亮度(Y)做處理,只對CbCr通道做縮減,所以對人的視覺系統的影響較低。

4.png

圖像分成8x8像素塊

從現在開始,在JPG上做的所有操作都是基於8x8像素塊。這樣做是因爲我們通常認爲8x8像素塊裏沒有太多的差異,即使是很複雜的圖片,局部區域的像素也往往相似,這種相似性有助於之後我們對它壓縮。

在這裏我們需要注意一點,我們要介紹JPG編碼的常見”神器”之一。”色彩滲透”是沿着鋒利邊緣的顏色可以”滲透”到另一邊。這是因爲色度通道,它代表像素的顏色,平均到單個顏色需要4個像素1塊,而有些塊穿過了鋒利邊緣。

離散餘弦變換

到現在爲止,這些步驟都平淡無奇。色彩空間,縮減取樣,分塊處理在圖片數據壓縮領域都是小兒科。但是現在…真正的數學要上場了。

DTC(離散餘弦轉換)的關鍵是,它假設任何一個數字信號都可以被一個餘弦組合函數重建。

例如,如果我們有下面這個座標圖:

5.png

你可以看到它實際上是cos(x)+cos(2x)+cos(4x)相加的結果

6.png

或許更好的展示這個過程,是在一個平面上給定一組餘弦函數來真實的解碼一張圖片。爲了展示這個過程,我貼了互聯網上最驚人之一的GIF圖片:在一個平面上用餘弦函數來編碼一塊8x8像素。

7.gif

上面是一張正在重建的圖片(最左邊那個區域)。每一幀我們都使用右側面版新的基準值,來乘一個權重值(右側區域的文字)來產生圖片(中間區域)。

如你所見,靠着帶權重的不同餘弦值相加,我們可以重構出我們的原圖。(這多屌啊~)

這個的基礎背景知識是離散餘弦變換原理。核心思想是,在不同頻率上,8x8塊都可以由一組權重餘弦變化的和代表。這裏的重點是算出要輸入的餘弦值,和它們的權重。

想要得出”使用什麼餘弦值”是很容易的,經過大量的測試之後,選出一組最好的餘弦值,它們是我們的基礎函數,下圖是形象化的過程。

8.png

而”它們怎麼被加權在一起”的問題也很簡單,直接套用下面的公式。

9.png

我就不介紹這些值得含義了,你可以在這個維基頁面查看它們含義。

每個色彩通道的8x8像素塊都會用上面這個公式和基礎函數生成新的一個8x8矩陣,表示在這個過程中使用的權重。下面是一張表示這個過程的圖片:

10.png

這個矩陣G,用來代表重建圖片的基礎權重(在動畫右側上方的小十進制數)。對於每個基礎餘弦值,我們都將它乘與矩陣裏的權重,然後全部相加,得到我們最終的圖片。

基於這點,我們就不再操作顏色空間而直接處理G矩陣(基礎權重),之後所有的壓縮操作都直接在這個矩陣上做。

這裏的問題是我們現在將字節對齊的整數轉成真實的數字。這樣會很容易膨脹我們的信息(從1byte變成一個float(4個字節))。爲了解決這問題,壓縮得更極致,我們將進入量化階段。

量化

我們不想壓縮浮點數據,它會膨脹我們的信息流,並且不高效。因此,我們要找一種方法來將權重矩陣轉換到0-255這範圍裏。我們可以直接在矩陣裏將最小/最大值(分別是-415.38和77.13)除以這個範圍來得到一個在0-1的值,再將這個值乘以255得到最後的值。

例如:[34.12- -415.38] / [77.13 — -415.38] *255= 232

這樣做可以,但代價是精度會顯著下降。這種縮放將產生一個分佈不均勻的值,其結果是會導致圖片質量的下降。

JPG用了另外一種方法。不同於使用矩陣的範圍來作爲縮放值,JPG用了一個可量化的預矩陣。這種可量化矩陣不需要成爲數據流的一部分,它們可成爲編碼的一部分。

這個例子展示了對於每一張圖片使用的量化因子矩陣:

11.png

現在我們使用Q和G矩陣,來計算我們的量化DCT係數矩陣:

12.png

例如,用G矩陣的[0,0]=-415.37和Q[0,0]=16這兩個數字:

13.png

得到最後的矩陣是:

14.png

你看現在這個矩陣多變成多簡單,它現在包含了大量的小整數或者0,這會有助於壓縮。

簡單點說,我們把這個過程分別應用在Y,CbCr通道,這樣我們需要兩個不同的矩陣,一個是Y通道,另一個是C通道:

15.png

量化壓縮有兩種重要的方式:
1. 限制可用範圍的權重,減少數字的位數和替換它們。
2. 將大部分的權重變成同一個數字或者0,提高第三步壓縮,熵編碼。

這樣的量化方式主要來源於JPEG。因爲圖像的右下方往往有最大的量化因子,JPEG傾向於將這些圖像組合。量化因子矩陣可以通過改變JPEG的’質量值’直接控制。(稍後介紹)

壓縮

現在我們可以回到整數世界了,將目光轉移到對顏色塊做有損壓縮階段。當看我們的轉化數據,你應該會注意到一些有趣的現象:

16.png

從左上角到右下角,0出現的數量急速上升。但主行和主列的順序並不理想,因爲這些0都交織在一起,而不是放在一起。

相反,我們可以從左上角開始以Z字形來回穿梭直到右下角的方式遍歷整個矩陣。

17.png

我們的亮度矩陣的順序變成:

−26,−3,0,−3,−2,−6,2,−4,1,−3,1,1,5,1,2,−1,1,−1,2,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

一旦數據變成這個格式,下一步就簡單了:按順序執行RLE,然後對結果進行統計編碼(霍夫曼/算術/ANS)。

Boom.你的數據塊變成JPG編碼了。

理解質量參數

現在你已經理解JPG文件是怎樣創建的,是該重新審視圖片質量參數這個概念了,你通常會在PhotoShop導出JPG圖片時會看到。(或在其他地方)

這個參數我們稱之爲q,是一個從1到100的整數。你應該把q當作一個測量圖片質量的值:q越大表示圖片的質量越高,當然文件就越大。

這個質量值用在量化階段,用來縮放合適的量化因子。因此對於每個基準權重,量化階段現在類似於* round(Gi,k / alpha*Qi,k)。*

其中alpha符號用來當作質量參數。

20.gif

當alpha或Q[x,y]越大(當alpha的值越大那麼q參數的值就越小),更多信息是丟失,文件就越小。

所以,如果你想要靠更多的視覺假象來得到一張更小的圖片,那麼你可以在到處圖片階段設置一個更小的質量值。

19.png

注意上圖,那張質量爲1的圖片裏,我們可以清晰的看到在成塊階段和量化階段的痕跡。

更重要的是質量參數大小取決於具體的圖片。由於每張圖片都是唯一的,它們都有不同的展示效果,那麼Q值也是唯一的。

總結

由於你已經理解了JPG的算法工作原理,一些事情就變得清晰了:

  1. 要獲取每張圖片正確的質量值,重要是在視覺效果和文件大小之間做權衡
  2. 因爲這個過程是基於塊的,僞影發生在塊效應或”振鈴效應”
  3. 因爲處理的塊彼此不互相混合,JPG通常會忽略壓縮大片相似塊。順便說一下,WebP格式比較擅長解決這種問題。

如果你想要自己處理這麼多東西,那麼這個1000行不到文件可以幫你搞定這些問題。

PS:由於本文涉及到的數學算法比較多,本人水平有限,如有譯錯,請留言討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章