(matlab image processing) arithmetic coding

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('解压图像');

The function is as follows

% 得到图像的符号和概率
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

The output is as follows, the first line is the lower limit of the interval, the second line is the upper limit of the interval

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

Insert picture description here
Check dictto see the interval corresponding to each symbol
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]

note

When the data is large, such as a 200 * 200 image passed in during the test, there is a problem with the encoding result, and the decoded image cannot be recognized. The reason is that the accuracy of the data is limited, causing overflow. Other methods such as symbolic calculation or advanpix toolkit with higher accuracy can be used. Questions are as follows

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

Insert picture description here

Published 39 original articles · Like 48 · Visitors 40,000+

Guess you like

Origin blog.csdn.net/qq_39798423/article/details/105519130