灰度图像的Huffman编码 MATLAB代码

clear all;
close all;
clc;

% src = imread('kids.tif');
src = imread('lenna_RGB.tif');
src_d = rgb2gray(src);

[m, n] = size(src);
src_size = m * n;
gray_level = 256; % 灰度级;

% prob数组保存图像中各灰度出现的概率
prob = [];
for src_value = 0 : (gray_level - 1)
    index = find(src_d == src_value);
    i = src_value + 1;
    prob(i) = length(index) / src_size;
end

% 画出直方图
% stem(0: gray_level-1, prob);
% xlabel('灰度值');
% ylabel('概率');
% title('灰度直方图');

% huffman编码
p = prob;
n = length(p);
q = p;
m = zeros(n-1, n);
for i = 1 : n - 1 
    [q, l] = sort(q);
    m(i,:) = [l(1 : n - i + 1), zeros(1, i - 1)];
    q = [q(1) + q(2), q(3 : n), 1];
end

bre = zeros(n-1, n); 
bre(n-1, 1) = 0 + j; % 虚部表示当前的二进制数的位数,以下类似
bre(n-1, 2) = 1 + j; % 给bre最后一行的前两列赋值
% 通过当前行给上一行的bre赋值,前两列通过m等于为1的值的虚实部赋值,后面等于m大于1得值
% m值为1的数都是上一行两个最小的概率相加得到的
for time = 1 : n-2   % time = 1 : 7
    loc_1 = find(real(m(n-time, :)) == 1); % 找m的行实部为1的返回指数,从最后一行往上找
    prebit = bre(n-time,loc_1);   % prebit等于bre当前行,实部为1的列的值)
    % 给bre往上一行一二列赋值,第一列为prebit实部*2,prebit虚部加1
    % 第二列为prebit实部*2加1,prebit虚部加1
    % 实部乘二代表多加一位,最低位一个赋0,一个赋1;虚部为位数,加一
    bre(n-time-1,1) = (real(prebit)*2 + 0) + j *(imag(prebit)+1); 
    bre(n-time-1,2) = (real(prebit)*2 + 1) + j *(imag(prebit)+1); 
    % 找m的当前行实部大于1的返回指数
    loc_not1 = find(real(m(n-time, :)) > 1);
    % 给bre的上一行,第三列及之后列赋值
    % 等于当前行的实部大于1的值
    bre(n-time-1,3:3+time-1) = bre(n-time,loc_not1);
end

[m1,index] = sort(m(1,:));  % 对m进行排序得到m1(按照灰度值排序),m是对概率进行排序
code = bre(1,index);  % code等于bre按照index排序的第一行
code_data = real(code);
code_bits = imag(code);
disp(['gray level',' ', 'huffman code']);
for i = 1 : length(code)
    disp([num2str(i-1), ' ', num2str(dec2bin(code_data(i)))]);
    disp([num2str(i-1), ' ', num2str(dec2bin(code_data(i),code_bits(i)))]);
end
code_binary = dec2bin(code_data);

%逐点编码
out = [];
for row = 1:m
    for vol = 1:n
        now_gray = src_d(row,vol);
        now_code = code_binary(now_gray+1,:);
        now_bits = code_bits(now_gray+1);
        now_code = now_code(end-now_bits+1:end);
        out = [out, now_code];
    end
end

%计算压缩比
real_bitnum = length(out);
bitnum_no_huffman = src_size * nextpow2(gray_level);
comp_ratio = bitnum_no_huffman / real_bitnum;
Lavg = real_bitnum / src_size;
% Hshannon = (-1) * prob * (log2(prob))';
disp(['Lavg = ', num2str(Lavg)]);
disp(['normal bit num = ', num2str(nextpow2(gray_level))]);
disp(['comp_ratio = ', num2str(comp_ratio)]);
% disp(['Hshannon = ', num2str(Hshannon)]);

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Huffman编码是一种无损压缩算法,可以对灰度图像进行压缩。下面是用Matlab实现灰度图像Huffman编码代码: ```matlab % 读入灰度图像 img = imread('gray_image.jpg'); % 统计像素值出现的频率 histogram = imhist(img); % 计算出现频率不为0的像素个数 num_of_pixels = sum(histogram > 0); % 初始化森林和哈夫曼编码树 forest = cell(num_of_pixels, 1); for i = 1:num_of_pixels forest{i} = struct('value', [], 'prob', [], 'left', [], 'right', []); end % 将像素值和频率存入森林中 j = 1; for i = 1:256 if histogram(i) > 0 forest{j}.value = i - 1; forest{j}.prob = histogram(i) / numel(img); j = j + 1; end end % 构建哈夫曼编码树 while numel(forest) > 1 % 按概率从小到大排序 [~, idx] = sort([forest{:}.prob]); forest = forest(idx); % 取出概率最小的两个节点 left = forest{1}; right = forest{2}; % 合并节点 parent = struct('value', [], 'prob', left.prob + right.prob, 'left', left, 'right', right); % 将父节点加入森林中 forest{2} = parent; forest(1) = []; end % 生成哈夫曼编码表 codes = cell(num_of_pixels, 1); generate_codes(forest{1}, ''); % 对图像进行编码 encoded_img = ''; for i = 1:size(img, 1) for j = 1:size(img, 2) idx = find([forest{:}].value == img(i, j)); encoded_img = [encoded_img, codes{idx}]; end end % 将编码后的字符串写入文件 fid = fopen('encoded_image.txt', 'w'); fwrite(fid, encoded_img, 'ubit1'); fclose(fid); % 生成哈夫曼编码表的函数 function generate_codes(node, code) if ~isempty(node.value) idx = find([node.parent{:}.value] == node.value); codes{idx} = code; else generate_codes(node.left, [code, '0']); generate_codes(node.right, [code, '1']); end end ``` 代码中使用了一个名为`generate_codes`的函数,这个函数用于生成哈夫曼编码表。在函数中,我们首先判断当前节点是否为叶子节点,如果是叶子节点,则在编码表中记录下该像素值对应的哈夫曼编码;否则,我们递归地遍历左子树和右子树,并在编码的末尾加上'0'或'1'。 最后,我们将编码后的字符串写入文件中,便完成了灰度图像Huffman编码。需要注意的是,由于Huffman编码是变长编码,所以我们需要使用`ubit1`格式写入文件,即每个字符只占用1位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值