【Matlab】Huffman编码如何实现数据压缩

Huffman编码可用于数据压缩已经是人所共知的事实。但是具体说到如何实现编码,至少作者在实验中是遇到问题了的!

 

如帖子:http://topic.csdn.net/u/20110221/14/845e3845-1e6d-4900-9e81-66703719a3b4.html 所言:

 

对数值串:

 [22006 22006 44004 87999 175989] --1*5

 

进行huffman编码,下面左列是要编码的数值,右列是编码结果。
22006    [1]
44004    [0 0 1]
87999    [0 0 0]
175989  [0 1]


则原数值列的编码结果为:

[1 1 0 0 1 0 0 0 0 1] -- 1*10

到这里为止应该没什么问题!


在进行压缩比的计算时,必须考虑Matlab(或者其他你处理数据的平台)中数据类型的问题。

比如:【数据类型】【占用存储】【数值范围】

uint8        8bit          0~255

uint16      16bit        0~65525

int8          8bit          -128~127

int16        16bit        -32768~32767

 

 

!matlab中是没有bit类型的,也就是说,即使是编码结果(0-1串),最少也需要占用10*sizeof(uint8) = 80bit.

 

而原数据需要的存储空间为5*sizeof(uint16) = 80bit. 可以看到:完全没有实现数据压缩。

 

当然,作为Huffman编码结果的0-1串如果能实现按位存储,那么毫无疑问地会节省存储空间,比如这里就是10*1bit=10bit.

压缩比为:CR = 80/10 = 8.

 

对于没有按位存储的情况,如Matlab平台,就需要将Huffman编码结果作进一步的处理。

 

我能想到的办法是这样做:

 

% 用Huffman编码字典对给定数据(int16)编码,并进一步编码将结果整理为(uint8)类型 function [ zipped, pad ] = HuffEnco( data, dict ) string = huffmanenco(data, dict); % Huffman编码结果:0-1串 string = uint8(string); % uint8型,1字节 % 补零: 便于每次取8个数的处理 len = length(string); pad = 8-mod(len,8); % 须存储!! if pad>0, % 如果string长度不能被8整除,则在其右端补零直到能被8整除为止 string = [string uint8(zeros(1, pad))]; end % 每8位存储为一个uint8型整数(0~255) cols = length(string) / 8; % 列数 string = reshape(string, 8, cols); % 将string改编成8*cols的矩阵 weights = 2.^(0:7); % 1*8的矩阵 zipped = uint8(weights*double(string)); % 矩阵相乘,得1*cols的矩阵,unit8型

 

解码过程如下:

 

% Huffman解码(对uint8类型数据),结果为int16型 function [ decosig ] = HuffDeco( zipped, pad, dict ) len = length(zipped); string = repmat(uint8(0), 1, len.*8); % 先创建空串 bitindex = 1:8; for index = 1:len % 还原为0-1串 1*N string(bitindex+8.*(index-1)) = uint8(bitget(zipped(index),bitindex)); end string = logical( string(:)' ); len = length(string); string( (len-pad+1) : end ) = []; % 去除pad位置的数 string = double(string); decosig = huffmandeco(string, dict); % Huffman解码

 

 

对给定数据生成Huffman编码字典代码如下:

 

% 由数据源计算Huffman编码所需的编码字典 function [ dict, avglen ] = HuffDict( data ) Min = min(data); Max = max(data); f = histc(data(:), Min:Max); % 求频率,既而求概率P f = f(:)/sum(f); symbols = find(f ~= 0); % 由前面求f可知symbols中字符是升序排列的 p = f(symbols); symbols = symbols + Min - 1; [dict, avglen] = huffmandict(symbols, p); % 求Huffman编码字典、平均码长

 

对示例1*10的0-1串进行二次处理,得到1*2的uint8向量,占用16bit. 则压缩比为80/16=5.

 

总结:

matlab已经有现成的函数实现Huffman编码,即huffmandict/ huffmanenco/ huffmandeco;

为实现压缩比的具体化,必须对编码结果进一步处理;

就计算复杂度而言,解码用时远高过编码,是否有好的优化方案?

 

 

引申:

将小波变换应用于信号压缩,变换结果(一维为向量,二维为矩阵)为占零比较高(可能达到70%以上),在学习《数据结构》的时候就已经知道了稀疏矩阵具有可优化的存储方案。

 

其实,小波压缩的核心一方面在于选择合理的分解层数和小波函数以外,另一个重要的方面就是对小波变换结果,即:对占零比较高的小波变换系数进行编码,编码以后的结果才实现了具体的压缩比,才可用于传输,这类似于本文的研究思路,比较成功的编码方法有SPIHT等。

 

你可能感兴趣的:(【Matlab】Huffman编码如何实现数据压缩)