s1091537 Homework #5
1122 Digital Image Processing Assignment #5 報告
學號:s1091537
姓名:蔡佾家
主題:Run-Length
Based Image Compression 影像壓縮練習
專案目標:
我提出一個基於Run-Length的壓縮方法,對圖檔進行無失真壓縮後儲存成新檔案,並且不使用到現成套件進行檔案編碼、儲存資料。我先改寫課程中Run-Length Coding的Absolute mode,使其編碼位元減少至僅原始方法的一半,並且header也只儲存最低限度的長與寬以節省空間,接著將其輸出為16進位字串儲存。為了更進一步壓縮大小,我實作Huffman Coding再次壓縮這個16進位字串。結果顯示,平均的壓縮率能夠達到7.20,然而,這個空間效率較現成套件為差(例如直接用NumPy把資訊儲存為.npy等),在後方我也將探討其原因。
開發平台:Microsoft Windows 11, Visual Studio
Code, OpenCV 4.6.0, Python 3.7.9
主要概念說明:
為了簡化說明,我另外使用下面這張小圖片進行一模一樣的編碼,結果如下圖所示,後方將對這張圖做進一步說明。
1.
分離RGB三通道並計算Run-Length陣列
在分離三通道後,我先計算出Run-Length陣列。在Encoded mode中,元素會以[個數,像素值]格式被紀錄下來。例如R通道中,RLE編碼為[9,190],即表示有9個值為190的像素,這部分與課程相同。在Absolute mode中,元素則會被以[0,個數,v1,v2,v3,…]格式被記錄下來,0宣告Absolute mode的開始,個數則聲明後方有幾個像素需要直接指定值,並且值依序為v1,v2,v3,…。由於Absolute mode很可能是連續的(一大片不規則區域),如此編碼可避免課程ppt的方法中,每指定一次像素值都要以0聲明,使空間效率提升一倍。例如在G通道中,RLE編碼為[0,5,10,20,30,…],即表示有5個像素不連續、需要直接指定值,而它們的值分別為10,20,30,…。值得注意的是,陣列中的每個元素都會被編碼為8 bits unsigned int,因此會限制「個數」最大僅能為255。
2. 將Run-Length陣列編碼為16進位字串
我將16進位字串設定為下圖中的格式:
由於R、G、B三通道的元素個數必定相同,header部分僅需要記載影像的長與寬即可還原。解碼時,我們只需要將header外的像素值解碼出來,再切分為三等份得到三通道內容,接著按照header聲明的長與寬依序依序填入值,就可以復原影像。除了Width與Height兩個值是以16 bits編碼(範圍是0到65535),其餘部分皆已8 bits進行編碼(範圍是0到255)。
以上面的例子來說,經此部分編碼後會變為以下:
3.
使用Huffman Coding壓縮16進位字串
經RLE編碼過後的16進位字串中,0到F並不是以相同頻率出現。例如在給定的img1.bmp中,有半張影像的顏色皆為
4.
確認正確與否
在壓縮完成後,除了計算壓縮率,我也將檔案解碼,並確認與原圖完全相同以保證編碼正確。
成果展示與討論:
1.
個別壓縮率與平均壓縮率:
2.
探討自己編碼與使用套件編碼的差異:
由於Run-Length陣列中的元素皆是固定以8 bits unsigned int儲存,使得我們必須限制個數不得超過255,而這會造成空間的浪費,導致本專案編碼方式效率較現成套件為低。舉例來說,若遇到700個值為0的像素,在使用現成套件下(沒有個數限制),套件會以自己的一套編碼靈活的儲存[700,0],而若以上述的簡單規則自己進行編碼,則會將資訊拆解為[255,0,255,0,190,0]再編碼儲存。不論是把大整數拆解為小整數再儲存,還是重複儲存多次出現的0,都是空間的浪費。
留言
張貼留言