背景
圖像壓縮是一種減少圖像文件大小的技術,旨在在保持視覺質量的同時降低存儲和傳輸成本。隨著數字圖像的廣泛應用,圖像壓縮在多個領域如互聯網、移動通信、醫學影像和衛星圖像處理中變得至關重要。
技術總覽
當下圖像壓縮JPEG幾乎一統天下,本文主要依據其原理,進行解析。
工作流總覽
- 顏色空間(YUV)下采樣
- 分塊DCT
- 依據量化表進行DCT量化
- zigzag掃描
- RLE編碼
- Huffman編碼
- 上述過程反向進行,解壓縮
顏色空間下采樣
關于YUV空間一些基礎知識:
https://zhuanlan.zhihu.com/p/587189669https://zhuanlan.zhihu.com/p/587189669其中Y空間也稱灰度空間,直方圖均衡化、灰度拉伸等操作就是基于這個空間進行的,很多時候,為了圖像處理的簡潔,經常在該空間上進行操作。
將顏色空間RGB轉化為YUV之后,由于人眼主要對Y(亮度)敏感,而對UV空間不敏感,所以可以對UV空間進行下采樣,(這里對UV空間體積分別縮小到原來的1/4),以512 * 512尺寸的RGB圖片為例。僅一步顏色空間下采樣,存儲空間就壓縮為了原本的?
(512*512 + 256*256 + 256*256)/ 512*512*3 = 1/2
分塊DCT
關于dct的一些相關知識??
https://zhuanlan.zhihu.com/p/85299446https://zhuanlan.zhihu.com/p/85299446dct將空域轉化成等價的頻域, 在頻域中,人眼對高頻的信息不敏感,那么如果略去高頻,保留低頻,則實現了圖像的有損壓縮。
dct僅僅是一步變換而已,并不對圖像構成壓縮,真正起到壓縮效果的是量化 + 編碼(也即接下來兩步)
為何分塊?
全局dct當然可以完成任務,并且壓縮效果依舊十分優異。但分塊后的好處是明顯的
從空間上來說:有固定分塊更容易研究量化表,讀者仔細思考就會發現,對于任意尺寸的dct二維數組,去用函數生成量化表是困難的,但是如果行業定下一個固定的dct二維數組尺寸,大家就可以盡情研究這個條件下什么樣的量化表效果會比較好。
從時間上來說:進行分塊后,計算的總體時間比整體計算快很多。在此之外,對于8*8分塊的dct,也有很多研究其快速算法的,ANN算法就是其中典例。
DCT矩陣量化
這一步的根本目標就是把DCT的高頻部分消去。
具體的計算步驟為,DCT矩陣的元素處以量化矩陣的對應位置元素
讀者的困惑應該大多在于量化表的生成。 關于這一點,對于任意M*N尺寸的圖片,其量化表可以設計一個指數函數去表達, 其中k的值應當偏小,對于512 * 512的lena圖來說,筆者嘗試值為0.4效果較佳。當然,如果真使用冪函數,記得在最外加上1,防止在0位置除0
????????
Zigzag掃描
JPEG圖像壓縮探索_zigzag掃描(原創)-CSDN博客文章瀏覽閱讀2k次。文章詳細介紹了DCT變換后如何使用zigzag掃描算法將圖像數據從高頻到低頻有序地轉化為一維數據,以便于后續的霍夫曼編碼等操作。該方法允許在不知原始二維數據邊長的情況下,將二維數據轉換為一維并能恢復原狀。文中還提供了Java代碼示例來實現這一過程。https://blog.csdn.net/cjzjolly/article/details/129158254
借上方博客圖一用,zigzag掃描順序如上圖所示,其中“掃描”的目的是為了把二維數組轉一維數組,方便進一步編碼壓縮,采用“zigzag”順序的理由是,這樣掃描讓盡可能多的‘0’ 靠在了一起,為隨后的RLE編碼提供基礎。
RLE編碼
關于該編碼,下邊這篇講的挺不錯。
https://zhuanlan.zhihu.com/p/1892905961586405848https://zhuanlan.zhihu.com/p/1892905961586405848經過RLE之后,就把重復很多的0給去除了 (其實這一點的效用和Huffman編碼稍微有點打架,因為如果沒有RLE,在量化后DCT矩陣的Huffman編碼中,最主要能節省的空間就是重復的0)
Huffman編碼
Huffman編碼的知識??
Huffman 編碼原理詳解(代碼示例)_霍夫曼解碼原理-CSDN博客文章瀏覽閱讀2.9w次,點贊19次,收藏47次。本文介紹了Huffman編碼的基本原理,包括路徑長度、帶權路徑長度等概念,并詳細闡述了Huffman樹的構造過程及其編碼實現。通過實例展示了如何選擇最優二叉樹以獲得最短編碼。https://blog.csdn.net/qinglongzhan/article/details/80982067關于該編碼壓縮空間的機理:
我們知道一個int在存儲空間占用4個字節 32位, 但是如果使用編碼的方式以字節流存入,則根本用不了32位,在解碼的時候只需保留Huffman的編碼表即可。
在調試這一段代碼的實踐中筆者其實廢了挺多力氣,因為按字節流存入,再讀取的時候由于不清楚大端讀還是小端讀導致調試的一頭霧水。
解碼過程
整體的解碼過程,按上方流程反過來走一遍即可達成完整解碼的效果。