s1091537 Homework #5

 

1122 Digital Image Processing Assignment #5 報告

學號:s1091537 姓名:蔡佾家

主題:Run-Length Based Image Compression 影像壓縮練習

專案目標:

    我提出一個基於Run-Length的壓縮方法,對圖檔進行無失真壓縮後儲存成新檔案,並且不使用到現成套件進行檔案編碼、儲存資料。我先改寫課程中Run-Length CodingAbsolute 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進位字串設定為下圖中的格式:

  由於RGB三通道的元素個數必定相同,header部分僅需要記載影像的長與寬即可還原。解碼時,我們只需要將header外的像素值解碼出來,再切分為三等份得到三通道內容,接著按照header聲明的長與寬依序依序填入值,就可以復原影像。除了WidthHeight兩個值是以16 bits編碼(範圍是065535),其餘部分皆已8 bits進行編碼(範圍是0255)。

    以上面的例子來說,經此部分編碼後會變為以下:

3.      使用Huffman Coding壓縮16進位字串

    RLE編碼過後的16進位字串中,0F並不是以相同頻率出現。例如在給定的img1.bmp中,有半張影像的顏色皆為 #00001E,而由於Encoded mode的個數最高為255,這會造成編碼後存在大量的0xFF000xFF1E(代表連續255個像素,值為0x00/0x1E),如此一來,0F1E這幾個字元便會大量出現在字串中。因此,我們可以進行Huffman Coding給予那些最常出現的字元最短的0/1編碼,然後再寫檔為二進位文件,進一步壓縮檔案大小。

4.      確認正確與否

在壓縮完成後,除了計算壓縮率,我也將檔案解碼,並確認與原圖完全相同以保證編碼正確。

成果展示與討論:

1.      個別壓縮率與平均壓縮率:

2.      探討自己編碼與使用套件編碼的差異:

    由於Run-Length陣列中的元素皆是固定以8 bits unsigned int儲存,使得我們必須限制個數不得超過255,而這會造成空間的浪費,導致本專案編碼方式效率較現成套件為低。舉例來說,若遇到700個值為0的像素,在使用現成套件下(沒有個數限制),套件會以自己的一套編碼靈活的儲存[700,0],而若以上述的簡單規則自己進行編碼,則會將資訊拆解為[255,0,255,0,190,0]再編碼儲存。不論是把大整數拆解為小整數再儲存,還是重複儲存多次出現的0,都是空間的浪費。

留言

這個網誌中的熱門文章

[s1101438 Homework #7]

s1093350 Homework #4

[s1101438 Homework #4]