作業說明:
Run-Length Encoding 影像壓縮練習
執行環境:
- Arch Linux x86_64
- Python 3.9.2
- Python venv
- OpenCV 4.5.1
實作方式:
- compress
- split image to R/G/B planes
- flatten plane into 1d array (column major and row major)
- preform rle on 1d array to get (value, length) pairs
- encode pipeline of values
- differential encoding.
- fold it and then add 1.
- Elias gamma encoding.
- save length (length should not be zero)
- length from 1 to 3 save in 2 bits.
- length from 4 to 15 save in 6 bits.
- length > 15 save in 14, 22, 38, 70 bits if ceil(log2(length -15)) less or equal than 8, 16, 32, 64, respectively.
- save the smaller compress result for each plane (column major or row major)
- for each plane write column major or row major as flag in header of file (1 bit)
- add header(size of image)
- write data to file
first two bits: 00 if length > 3 else just save length
third to sixth bits: 0 to 3 represent type of length if length > 15 else just save length
0000: uint8 0001: uint16 0010: uint32 0011: uint64
remaining bits: save length - 15
example:
3 : 11
5 : 00 0101
83 : 00 0000 01000100
268 : 00 0000 11111101
23786 : 00 0001 01011100 11011011
- uncompress
- read header
- decode values
- read length
- reconstruct 1d array
- reshape
- merge R/G/B channels
執行結果:
如下圖
壓縮率分別為 15.09, 11.00, 15.01
平均壓縮率為 13.70
執行時間均為約一至二秒左右
png 壓縮率分別為 10.89, 7.77, 11.09
png 平均壓縮率為 9.91
壓縮之檔案
壓縮率計算
解壓縮驗證
執行時間 (total)
png 檔案大小
png 壓縮率計算
問題討論:
經過壓縮後的檔案仍然可以被deflate壓縮30%
代表仍有重複冗餘
有想解決但每個 row 做 BWT 壓縮率會降低
整張圖一起做記憶體會不足
想使用 MED 做 predictive encoding 但是 numpy 無法 vectorize 可能會很慢
MTF 在比較新的研究中已經被拿掉
Huffman encoding 沒有看得懂的實作
LZ77 跟 RLE 的性質太像
對長度做 differential encoding 反而會降低壓縮率
因此最後就只對數值做 differential encoding 後接 Elias gamma encoding
比尚未壓縮數值的版本 平均壓縮率從 8.3 進步到 13.7
參考資料:
Python, fast compression of large amount of numbers with Elias Gamma - stackoverflow(Elias Gamma 實作程式碼取自此)
沒有留言:
張貼留言