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等。