您的位置:首页 > 其它

信息论的编码

2015-12-24 08:26 344 查看

香农编码

function c = shannon(p)

% p = [0.2 0.15 0.15 0.1 0.1 0.1 0.1 0.1]

% shannon(p)

[p , index] = sort(p) ;%让p中的元素升序排列

p = fliplr(p) ;% 让p中的元素倒序排列

n = length(p) ;%计算p中元素的个数

pa = 0 ; %累加概率的计算

for i = 2:n

    pa(i) = pa(i - 1) + p(i - 1) ;  

end

k = ceil(-log2(p)) ; %对子信息量的向上取整,计算的是码长

c = cell(1,n) ;

for i = 1:n

    c{i} = '' ;

    tmp = pa(i) ;

    for j = 1:k(i)

        tmp = tmp * 2 ;

        if tmp >= 1

            tmp = tmp -1 ;

            c{i}(j) ='1' ;

        else

            c{i}(j) ='0' ;

        end

    end

end

c = fliplr(c) ;

c(index) = c ;

 

fano编码

functionc = fano(p)
% p= [0.25 0.25 0.20 0.15 0.10 0.05]
% c= fano(p)
n =size(p , 2) ;
%已经编码完成
if n ==1
    c= cell(1,1);
    c{1}= '' ;
    return
end
[p ,index] = sort(p);%按概率排序
p =fliplr(p) ;
total= sum(p) ;%总概率
acc= 0 ;%累积概率
flag= 0 ;%是否到达尾部的标志
for i =1:n-1
    newacc= acc + p(i) ;
    if abs(total- 2 * newacc) >= abs(total - 2 * acc)
        flag= 1 ;
        break;   
    end
    acc= newacc ;
end
if ~flag
    i= n ;
end
split= i ;
%从分界点对两边的码递归做fano
c1 =fano(p(1:split-1)) ;
c2 =fano(p(split:n)) ;
c =cell(1,n) ;
%添加前缀0,1
for i =1:split-1
    c{i}= strcat('0' , c1{i}) ;
end
for i =split:n
    c{i}= strcat('1' , c2{i - split + 1} ) ;
end
%将顺序调整回去
c =fliplr(c) ;
c(index)= c ;
 

2.霍夫曼编码

function c = huffman(p)

% p = [0.2 0.15 0.15 0.1 0.1 0.1 0.1 0.1]

n = size(p , 2) ;%给出p中元素个数

if n == 1 %信源是不是缩减到一个元素,若if为真

    c = cell(1,1) ;

    c{1} = '' ;%开始回溯

    return    

end

[p1 , i1] = min(p) ;%把p中最小元素给p1,i1记录p1的位置

index = [(1:i1-1) , (i1+1:n)] ;%找到第一个最小概率并剔除

p = p(index) ;

n = n - 1 ;

[p2 , i2] = min(p) ;

index2 = [(1:i2-1) , (i2+1:n)] ;

p = p(index2);

i2 = index(i2) ;

index = index(index2) ;

p(n) = p1 + p2 ; %在信源中添加新符号概率为最小概率相加

c = huffman(p) ; %递归调用huffman函数,进一步的进行信源缩减,直到信源元素为一

c{n+1} = strcat(c{n} , '1') ;

c{n} = strcat(c{n} , '0') ;

index = [index , i1 , i2] ;

c(index) = c ;%在回溯过程中重新建立编码

 

3. 游程编码

 

image1=imread('C:\Program Files\MATLAB71\work\1\girl.jpg'); %读入图像

imshow(image1);       %显示原图像(右图)

 

% 以下程序是将原图像转换为二值图像

image2=image1(:);  %将原始图像写成一维的数据并设为 image2

image2length=length(image2); % 计算image2的长度

 for i=1:1:image2length  % for 循环,目的在于转换为二值图像

if     image2(i)>=127

image2(i)=255;

else   image2(i)=0;

end

end

image3=reshape(image2,146,122); % 重建二维数组图像,并设为image3

figure,imshow(image3);%(右图)

 

% 以下程序为对原图像进行游程编码,压缩

X=image3(:);  %令X为新建的二值图像的一维数据组

x=1:1:length(X);   % 显示游程编码之前的图像数据

 figure,

plot(x,X(x));

 

j=1;

image4(1)=1;

for z=1:1:(length(X)-1)  % 游程编码程序段

if  X(z)==X(z+1)

image4(j)=image4(j)+1;

else

data(j)=X(z);  % data(j)代表相应的像素数据

j=j+1;

image4(j)=1;

end

end

data(j)=X(length(X));    % 最后一个像素数据赋给data

image4length=length(image4);  % 计算游程编码后的所占字节数,记为image4length

y=1:1:image4length ;          % 显示编码后数据信息

figure,

plot(y,image4(y));

 

CR=image2length/image4length;   % 比较压缩前于压缩后的大小

 

% 下面程序是游程编码解压

 l=1;

for m=1:image4length

    for n=1:1:image4(m);

        rec_image(l)=data(m);

        l=l+1;

     end

    end

u=1:1:length(rec_image);       % 查看解压后的图像数据

figure,plot(u,rec_image(u));

rec2_image=reshape(rec_image,146,122); % 重建二维二维图像数组

figure,imshow(rec2_image);          % 显示解压恢复后的图像

 

 

 

 

 

 

平均码长  编码效率

 

functionf = acl(p , c)
%f =acl(p,c)
%p:probability, c:code
%return :average code length
 
c =fano(p);
4000
f =0 ;
r =0 ;
for i =1:length(p)
    f= f + p(i) * length(c{
i
});   
end
for i =1:length(p)
    r= r - p(i)* log2(p(i)) ;   
end
H =r
L =f
P =H/L
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: