clc
clear
close all
I1=imread("sea.jpg");
subplot(1,2,1);imshow(I1),title('原始彩色图像');%原图
I2=rgb2gray(I1);
subplot(1,2,2);imshow(I2),title('原始彩色图像的灰度图像');%原始彩色图像的灰度图
[R,C]=size(I2);
a=I2(:);%1:M*N;
p=zeros(1,256);%获取图像的概率
for i=0:255
p(i+1)=length(find(a==i))/(R*C);
if (p(i+1)==0) %去掉概率为0的像素点
p(i+1)=1*exp(-20);
end
end
[~,n]=size(p)%得到编码个数
HT=zeros(2*n-1,4);%构造霍夫曼树
for i=1:n
HT(i,1)=p(i);
end
HT;%第一列为个数的权重值 1~4列分别为 权重 父节点 左孩子 右孩子
HT0=HT;
%构建霍夫曼树
for i=1:n-1
a=HT0(:,1);
[b,l]=sort(a,'descend');
s=b(n-i+1)+b(n-i);%选取两个最小值进行求和 大 小
HT0(n+i,1)=s;%将求和后的数放进霍夫曼树的父节点上
HT0(l(n-i+1),1)=0;%将两个最小值删除,清零
HT0(l(n-i),1)=0;%将两个最小值删除,清零
HT0(l(n-i+1),2)=n+i;%两个最小值的父节点
HT0(l(n-i),2)=n+i;%两个最小值的父节点
HT0(n+i,3)=l(n-i+1);%父节点的左孩子
HT0(n+i,4)=l(n-i);%父节点的右孩子
%重构霍夫曼树
HT(n+i,1)=s;
HT(l(n-i+1),2)=n+i;
HT(l(n-i),2)=n+i;
HT(n+i,3)=l(n-i+1);
HT(n+i,4)=l(n-i);
end
HT;%去掉分号可查看霍夫曼树
%字符数组,用于生成霍夫曼码
a={;};
for i=1:n
a{1,i}=' ';
end
%霍夫曼编码
for i=1:n
f=i;
while(HT(f,2)~=0)%直到父节点为根结点时,编码完成
q=HT(f,2);%取出叶子结点的父节点的值
if HT(q,3)==f
a{i}=strcat('1',a{i});%若为左孩子,则编为1
else
a{i}=strcat('0',a{i});%若为右孩子,则编为0
end
f=q;%继续寻找父节点的节点
end
end
fprintf('各分布概率的霍夫曼编码为:\n');
for i=1:n
fprintf( '%f的编码为:"%s"\n' ,HT(i,1),a{i});
end
%计算平均码长
l=[];
L=0;
for i=1:n
l(i)=length(a{i});
L=l(i)*HT(i,1)+L;
end
disp( '平均码长为') ;disp(L);
%计算信源熵
Hx=0;
for i=1:n
Hx=-HT(i,1).*log2(HT(i,1))+Hx;
end
disp( '信源熵为') ;disp(Hx);
%计算编码效率
M=Hx/L;
disp('编码效率') ;disp(M);
%计算冗余度
disp('冗余度') ;disp(1-M);