📜  使用MATLAB进行算术编码和解码

📅  最后修改于: 2021-04-16 06:06:05             🧑  作者: Mango

算术编码是在无损数据压缩中使用的一种熵编码。通常,代表字符串字符,例如单词“ hey”,以利用每个字符固定数目的位。

在最直接的情况下,每个符号出现的概率是相等的。例如,考虑三个符号A,B和C的集合,每个符号都容易发生。直截了当的块编码将为每个符号要求2位,这是无效的,因为很少使用位变体之一。
换句话说,A = 00,B = 01和C = 10,但是11未使用。越来越有效率的安排是说这三个符号是在基数3中作为有理数的连续符号,其中每个数字都代表一个符号。例如,排列“ ABBCAB”可能变为0.011201。在算术编码中作为激励因素[0,1)。后续阶段是使用足够精确的固定引导配对数对这个三进制数进行恢复,例如0.00101100102-这仅为10位。鉴于存在大量有效的设定计算以转换主观准确数字为基础的事实,因此对于长距离布置而言,这是可以实现的。

说完这些,算术编码器可以为符号和概率的某种随机排列提供接近理想的输出(理想值为–似然度P的每个符号的log2P位)。利用算术编码的压缩算法将决定数据的结构-从根本上期望在消息的符号中可以找到哪些示例。该预测越精确,输出将越接近理想。

说完所有的事情,除了绝对的最后,编码过程的每个过程都是等效的。编码器基本上只考虑三位信息:应该编码的以下符号。当前跨度(在编码过程的最开始,将stretch设置为[0,1],但会有所变化)该模型允许在此阶段可以想到的每个不同符号的概率(如参考)先验,更高要求或通用的模型意味着这些概率在每个级数中实际上并不是相等的。)编码器将当前跨度隔离为子跨度,每个跨度相对于该符号的可能性而言只代表少量的当前跨度在当前设置中。与接近于编码的真实符号相关的任何延伸都变成在后续阶段中使用的跨度。在什么符号的总和已经被编码的时候,随后的跨度就清楚地识别出传递它的符号的排列。任何正在使用的具有相似的最后跨度和模型的个人都可以重新制作符号序列,这很有可能比没有进入编码器来实现最后的拉伸。无论如何,传输最后一段并不重要。重要的是传输该跨度中存在的一个分区。具体地说,重要的是要传输足够的数字位(以任何基数为单位),以使以这些数字开头的所有划分都落到最后一段。这将确保后续代码是前缀代码。

编码方式

% input string
str = 'GeeksforGeeks';
fprintf('The entered string is : %s\n', str);
  
% length of the string
len = length(str);
fprintf('The length of the string is : %d\n', len);
  
% get unique characters from the string
u = unique(str);
fprintf('The unique characters are : %s\n', u);
  
% length of the unique characters string
len_unique = length(u);
fprintf('The length of unique character string is : %d\n', len_unique);
  
% General lookup table
  
% get zeros of length of unique characters
z = zeros(1, len_unique);
p = zeros(1, len_unique);
  
for i = 1 : len_unique
  
   % in 'z' variable we will find the 
   % occurrence of each characters from 'str'  
   z(i) = length(findstr(str, u(i)));
  
   % in 'p' variable we will get 
   % probability of those occurrences
   p(i) = z(i) / len;
end
display(z);
display(p);
  
% in 'cpr' variable we will get the cumulative 
% summation of 'p' from '1' till last value of 'p'
cpr = cumsum(p);
  
% in 'newcpr' variable we are taking 
% 'cpr' from '0' till last value of 'p' 
newcpr = [0 cpr];
  
display(cpr);
display(newcpr);
  
% make table till 'len_unique' size
for i = 1 : len_unique
  
   % in first column we are then 
   % placing 'newcpr' values
   interval(i, 1) = newcpr(i);
  
   % in second column we are 
   % placing 'cpr' values
   interval(i, 2) = cpr(i);
end
  
% Displaying the lookup table
display('The lookip table is : ')
display(interval);
  
% Encoder Table
  
low = 0;
high = 1;
for i = 1 : len
   for j = 1 : len_unique
  
       % if the value from 'str'
       % matches with 'u' then
       if str(i) == u(j);
           pos = j;
           j = j + 1;  
  
           % displaying the matched length 
           % of unique characters
           display(pos);
  
           % getting the tag value 
           % of the matched character
           range = high - low;
           high = low + (range .* interval(pos, 2));
           low = low + (range .* interval(pos, 1));
           i = i + 1;
           break
       end
   end
end
  
% displaying tag value
tag = low;
display(tag);

输出 :

The entered string is : GeeksforGeeks
The length of the string is : 13
The unique characters are : Gefkors
The length of unique character string is : 7

z =

     2     4     1     2     1     1     2


p =

    0.1538    0.3077    0.0769    0.1538    0.0769    0.0769    0.1538


cpr =

    0.1538    0.4615    0.5385    0.6923    0.7692    0.8462    1.0000


newcpr =

         0    0.1538    0.4615    0.5385    0.6923    0.7692    0.8462    1.0000

The lookip table is : 

interval =

         0    0.1538
    0.1538    0.4615
    0.4615    0.5385
    0.5385    0.6923
    0.6923    0.7692
    0.7692    0.8462
    0.8462    1.0000


pos =

     1


pos =

     2


pos =

     2


pos =

     4


pos =

     7


pos =

     3


pos =

     5


pos =

     6


pos =

     1


pos =

     2


pos =

     2


pos =

     4


pos =

     7


tag =

    0.0409

解码

str = '';
  
for i = 1 : len
   for j = 1 : len_unique
       
       % If tag value falls between a certain 
       % range in lookup table then
       if tag > interval(j, 1) && tag < interval(j, 2)
           pos = j;
           tag = (tag - interval(pos, 1)) / p(j);
  
           % Geeting the matched tag 
           % value character
           decoded_str = u(pos);
  
           % String concatenating 
           % 'decoded_str' into 'str'
           str = strcat(str, decoded_str);
           break
       end
   end
end
  
% Displaying final decoded string
disp(str)

输出 :

GeeksforGeeks