图像压缩编码

一、实验目的
1、理解图像编码的概念:
2、掌握霍夫曼编码技术
二、实验内容:
选取一段不少于3000字的英文材料,统计各字符出现的次数,实现HuMiman 编码,以及对编码结果的解码。
三、实验要求:
1)输出每个字符出现的次数和编码,并存储文件(Huffmnan.txt)。2)在 Huffman 编码后,英文文章编码结果保存到文件中(code.dat),编码结果必须是二进制形式,即01的信息用比特位表示,不能用字符“0 和“1表示。
3)实现解码功能

霍夫曼编码(Huffman Coding)和费诺编码(Fano Coding)都是用于数据压缩的变长编码方法,在数字通信、数据存储等领域有广泛应用。

霍夫曼编码

原理

霍夫曼编码基于数据出现的概率来构建最优二叉树(霍夫曼树),出现概率高的数据用较短的编码表示,出现概率低的数据用较长的编码表示,从而实现数据的压缩。

编码步骤
  1. 统计频率:统计输入数据中每个符号出现的频率或概率。
  2. 构建霍夫曼树
    • 将每个符号作为一个单独的节点,节点的权值为该符号的频率。
    • 重复以下步骤,直到所有节点合并为一个根节点:
      • 从节点集合中选取权值最小的两个节点。
      • 创建一个新的内部节点,其权值为这两个节点权值之和,将这两个节点作为新节点的左右子节点。
      • 将新节点加入节点集合,并移除原来的两个节点。
  3. 生成编码表:从根节点开始,向左遍历标记为 0,向右遍历标记为 1,直到到达叶子节点,得到每个符号的霍夫曼编码。
优缺点
  • 优点
    • 是一种最优变长编码,能达到理论上的最小平均编码长度,压缩效率高。
    • 编码过程简单,易于实现。
  • 缺点
    • 需要额外的存储空间来存储霍夫曼树或编码表,以便解码时使用。
    • 对数据的统计特性依赖较大,如果数据的概率分布发生变化,编码效率会降低。

费诺编码

原理

费诺编码也是一种变长编码方法,它通过将符号集合按照概率大小排序,然后递归地将集合分成两个子集,使得两个子集的概率之和尽可能接近,为每个子集分配不同的编码前缀,逐步生成每个符号的编码。

编码步骤
  1. 统计频率:统计输入数据中每个符号出现的频率或概率。
  2. 排序符号:将符号按照概率从大到小排序。
  3. 划分集合
    • 将排序后的符号集合划分为两个子集,使得两个子集的概率之和尽可能接近。
    • 为第一个子集的所有符号编码前缀添加 0,为第二个子集的所有符号编码前缀添加 1。
  4. 递归处理:对每个子集重复步骤 3,直到子集中只有一个符号为止。
优缺点
  • 优点
    • 编码过程相对直观,容易理解。
    • 不需要像霍夫曼编码那样构建复杂的树结构。
  • 缺点
    • 不是最优变长编码,平均编码长度通常比霍夫曼编码长,压缩效率相对较低。
    • 当符号数量较多时,划分集合使得概率之和接近的操作可能会比较复杂。

具体代码如下:

% 读取英文材料
try
    fileID = fopen('english_text.txt', 'r');
    text = fread(fileID, '*char')';
    fclose(fileID);
catch ME
    fprintf('读取文件时出错: %s\n', ME.message);
    return;
end

% 统计各字符出现的次数
uniqueChars = unique(text);
counts = zeros(size(uniqueChars));
for i = 1:length(uniqueChars)
    counts(i) = sum(text == uniqueChars(i));
end

% 构建 Huffman 树和编码表
symbols = 1:length(uniqueChars);
probabilities = counts / sum(counts);
[dict, ~] = huffmandict(symbols, probabilities);

% 输出每个字符出现的次数和编码,并存储到文件 (Huffman.txt)
try
    fileID = fopen('Huffman.txt', 'w');
    for i = 1:length(uniqueChars)
        code = dict{i};
        fprintf(fileID, 'Character: %c, Frequency: %d, Code: ', uniqueChars(i), counts(i));
        for j = 1:length(code)
            fprintf(fileID, '%d', code(j));
        end
        fprintf(fileID, '\n');
    end
    fclose(fileID);
catch ME
    fprintf('写入 Huffman.txt 文件时出错: %s\n', ME.message);
    return;
end

% 将字符转换为对应的符号索引
symbolIndices = zeros(size(text));
for i = 1:length(text)
    index = find(uniqueChars == text(i));
    symbolIndices(i) = index;
end

% 进行 Huffman 编码
encodedData = huffmanenco(symbolIndices, dict);

% 将编码结果保存到文件 (code.dat),以二进制形式
try
    fileID = fopen('code.dat', 'wb');
    fwrite(fileID, encodedData, 'ubit1');
    fclose(fileID);
catch ME
    fprintf('写入 code.dat 文件时出错: %s\n', ME.message);
    return;
end

% 读取编码文件
try
    fileID = fopen('code.dat', 'rb');
    encodedDataRead = fread(fileID, '*ubit1');
    fclose(fileID);
catch ME
    fprintf('读取 code.dat 文件时出错: %s\n', ME.message);
    return;
end

% 将编码数据转换为 double 类型
encodedDataRead = double(encodedDataRead);

% 进行 Huffman 解码
decodedIndices = huffmandeco(encodedDataRead, dict);

% 将解码后的符号索引转换为字符
decodedText = uniqueChars(decodedIndices);

% 验证解码结果
if isequal(decodedText, text)
    disp('解码成功!');
else
    disp('解码失败。');
end    

每个字符的出现次数和对应的 Huffman 编码如下:

编码方法霍夫曼编码费诺编码
编码原理基于概率构建最优二叉树递归划分符号集合
压缩效率高,理论最优相对较低
编码复杂度构建霍夫曼树较复杂相对简单
解码复杂度需要存储霍夫曼树或编码表相对简单
应用场景广泛应用于各种数据压缩领域适用于对编码复杂度要求低、压缩效率要求不高的场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值