(matlab图像处理)算术编码

I = [2 3 2;
     4 5 7;
     9 6 7];  % 测试数据模拟图像
[m,n] = size(I);
[sym,prob] = SymbolsAndProbabilityStatistics(I);  % 计算符号和概率
% 算术编码
dict = arithmeticdict(sym,prob);  % 初始编码区间
sig = I(:);  % 编码向量
enco = arithmeticenco(sig,dict);  % 编码
fprintf('算术编码为:%16.15f\n',enco);
dsing = arithmeticdeco((enco(1)+enco(2))/2,dict,m,n);  % 解码(取上下区间的平均值)
ide = col2im(dsing,[m,n],[m,n],'distinct');  % 把向量重新转换成图像块
figure;
subplot(121),imshow(I,[]),title('原图');
subplot(122),imshow(ide,[]),title('解压图像');

其中函数如下

% 得到图像的符号和概率
function [sym,prob] = SymbolsAndProbabilityStatistics(I)
    [m,n] = size(I);
    sym = zeros(1);  % 符号数组
    prob = zeros(1);  % 概率
    % 匹配概率
    p = zeros(1,256);
    for i = 1:m
        for j = 1:n
            p(I(i,j)+1) = p(I(i,j)+1)+1;
        end
    end
    % 删除未出现的编码
    num = 1;  % 计数
    for k = 1:256
        if (p(k)~=0)
            sym(num) = k-1;
            prob(num) = p(k);
            num = num+1;
        end
    end
    prob = prob./(m*n);  % 概率
end

% 将符号和区间组成表,区间由概率取得
function dict = arithmeticdict(sym,prob)
    plast = 0;
    dict = cell(length(sym),2);  % 编码表
    for i = 1:length(sym)
        dict{i,1} = sym(i);
        dict{i,2} = [plast plast+prob(i)];
        plast = plast+prob(i);
    end
end

% 编码
function enco = arithmeticenco(sig,dict)
    hight = 1;
    low = 0;
    for i = 1:length(sig)
        for j = 1:length(dict)
            if (sig(i) == dict{j,1})
                range = hight-low;
                hight = low+range*dict{j,2}(2);
                low = low+range*dict{j,2}(1);
            end
        end
    end
    enco = [low hight];
end

% 解码
function dsing = arithmeticdeco(enco,dict,m,n)
    dsing = (-1);
    for p = 1:(m*n)
       for i = 1:length(dict)
           if (enco >= dict{i,2}(1) && enco < dict{i,2}(2))
               dsing = [dsing, dict{i,1}];
               range = dict{i,2}(2)-dict{i,2}(1);
               enco = (enco-dict{i,2}(1))/range;
               break;
           end
       end
    end
    dsing(dsing==-1) = [];
    dsing = dsing';
end

得到的输出如下,第一个行是区间下限,第二行是区间上限

算术编码为:0.096786589931747
算术编码为:0.096786631230544

在这里插入图片描述
查看dict能得到每个符号对应的区间
2 ------------------------ [0,0.222222222222222]
3 ------------------------ [0.222222222222222,0.333333333333333]
4 ------------------------ [0.333333333333333,0.444444444444444]
5 ------------------------ [0.444444444444444,0.555555555555556]
6 ------------------------ [0.555555555555556,0.666666666666667]
7 ------------------------ [0.666666666666667,0.888888888888889]
9 ------------------------ [0.888888888888889,1]

注意

当数据较大,如测试时传入一张200*200的图像,编码的结果就出现了问题,解码后的图像无法识别。原因是数据的精度有限,造成溢出。可使用符号计算或有更高精度的advanpix工具包等其他办法。问题如下

算术编码为:0.816069123170177
算术编码为:0.816069123170177

在这里插入图片描述

发布了39 篇原创文章 · 获赞 48 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_39798423/article/details/105519130
今日推荐