博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对一幅BMP格式的灰度图像进行二元霍夫曼编码和译码
阅读量:5308 次
发布时间:2019-06-14

本文共 5028 字,大约阅读时间需要 16 分钟。

对一幅BMP格式的灰度图像进行二元霍夫曼编码和译码

信息论的实验终于结束了,才开始写python,写的比较乱,仅供参考


主要思想

霍夫曼编码关键在于树的构造,其构造要达到的目的为权重越大越靠近叶子结点,权重越小越靠近根,即使出现次数越多的值的码长越短。

构造时每次去权重最小的两个点合并为一个点n,这两个点为点n的左右子结点,这两个点的权重的和为结点n的权重,然后重复上述操作直至剩下一个点。如:

 

 

程序说明

1、还原程序直接将图像大小写死了为256* 256

2、程序中编码效率的计算为信源熵除以平均码长
3、了解了python中的pillow库
Image.open(图像)打开图像
getpixel((x,y))得到图像x,y处像素值
Image.fromarry(数组,astype('uint8')).convert('L')将一个数组还原为图像,其中L表示灰度图
show()展示图像
save()保存图像
4、统计一个列表中各数值的个数

#需要导入from collections import Counterc = Counter()for num in list:    c[num] = c[num] + 1#list为一个列表,比如list=[11,11,22,22,22,33],则运行结果c={11:2,22:3,33:1}

5、np.arrry(矩阵)可以将矩阵变为数组

需要导入import numpy as np
程序还原时发现图像是镜像的,不知哪有问题,后来干脆把得到的二维数组转置一下,发现可以
转置有两种方法:
(1)T: 数组.T
(2)reshape:np.reshape(数组)

编码程序

import osimport mathfrom PIL import Imagefrom collections import Counter#定义树的结构class BinaryTree:    def __init__(self,weight,name=None):        self.name=name        self.weight = weight        self.leftChild = None        self.rightChild = None#读取图像,将像素存入一个列表im_listimage_name=input('请输入需要编码的图像')im = Image.open(image_name)width = im.widthheight = im.heightim_list = []for x in range(width):    raw_list = []    for y in range(height):        pixel = im.getpixel((x, y))        raw_list.append(pixel)    im_list.extend(raw_list)sum=len(im_list)#计算像素个数总和#统计各像素的的个数,将像素及对应次数存入字典cc = Counter()for num in im_list:    c[num] = c[num] + 1sum_v=[]#各像素的概率H=0#信源熵for i in range(0,256):    if i in c:        sum_v.append(c[i]/sum)        H=H+c[i]/sum*math.log(sum/c[i],2)    else:        sum_v.append(0)#先将字典c中的各对元素转化为Binarytree类,即将各对元素变为结点,并存到Node列表中node=[]for i in  range(0,len(c)):    temp_key=min(c,key=c.get)    temp_num=c[temp_key]    node.append(BinaryTree(temp_num,temp_key))    del c[temp_key]#对表内元素按照权重排序的函数def sort_weight(elem):    return elem.weightnode.sort(key=sort_weight)#构造哈夫曼树while len(node)!=1:    small_1=node.pop(0)    small_2=node.pop(0)    newnode=BinaryTree(0)    newnode.weight=small_1.weight+small_2.weight    newnode.rightChild=small_1    newnode.leftChild=small_2    node.append(newnode)    node.sort(key=sort_weight)tree=node.pop(0)#进行编码huffcode={}#最后像素和所对应的的字典都存放在这里bin_str=[]#想当于一个栈结构,用于存放编码bin_str.append('')#迭代遍历函数def coding (tree):    Left(tree)    Right(tree)    bin_str.pop(-1)#左树遍历def Left(tree):    tree1=tree.leftChild    bin_str.append(bin_str[-1] + '0')    if tree1.name!=None:        huffcode[tree1.name] = bin_str.pop(-1)        return    coding(tree1)#右树遍历def Right(tree):    tree2 = tree.rightChild    bin_str.append(bin_str[-1] + '1')    if tree2.name != None:        huffcode[tree2.name]=bin_str.pop(-1)        return    coding(tree2)#对各像素编码,并将得到的编码表写入文件coding(tree)filehuff=open('huffcode.txt',mode='w')filehuff.write(str(huffcode))#对图像进行编码,并将编码写入文件imcode.txtim_code=[]while len(im_list)!=0 :    im_code.append(huffcode[im_list.pop(0)])filecode=open('imcode.txt',mode='w')filecode.write(str(im_code))print('编码成功!')sum_l=[]#各像素码长for i in range(0,256):    if i in huffcode:        sum_l.append(len(huffcode[i]))    else:        sum_l.append(0)L=0#平均码长while(len(sum_l)!=0):    L=sum_l.pop(0)*sum_v.pop(0)+Lprint('编码效率为')print(H/L)

还原程序

import osimport reimport numpy as npfrom PIL import Image#定义树的结构class BinaryTree:    def __init__(self,name=None):        self.name=name        self.leftChild = None        self.rightChild = None#得到哈夫曼编码表,保存为一个列表file=open('huffcode.txt')c={}for each_word in file:    a=re.split(r'[\{\}\:\,\'\s+]+', each_word)a.pop(0)a.pop(-1)#构造哈夫曼编码的树def encode(nodeser,tree_leave,strlen,str_len):    if str[strlen] == '0':        if str_len==1:            nodeser.leftChild=tree_leave            return        elif nodeser.leftChild==None:            newnode=BinaryTree()            nodeser.leftChild =newnode        encode(nodeser.leftChild,tree_leave,strlen+1,str_len-1)    else:        if str_len == 1:            nodeser.rightChild = tree_leave            return        elif nodeser.rightChild == None:            newnode = BinaryTree()            nodeser.rightChild = newnode        encode(nodeser.rightChild, tree_leave, strlen + 1, str_len - 1)    returntree=BinaryTree()while len(a)!=0:    name=a.pop(0)    str=a.pop(0)    tree_leave=BinaryTree(name)    encode(tree,tree_leave,0,len(str))#读取经过哈夫曼编码后的图片的文档file2=open('imcode.txt')for each_word in file2:    im=re.split(r'[\[\]\,\'\s+]+', each_word)im.pop(0)im.pop(-1)strcode=''#先转化为一串01串while len(im)!=0:    strcode=strcode+im.pop(0)tree_copy=treereimg=[]#遍历树,得到相对应的像素值for i in range(0,len(strcode)):    if strcode[i]=='0':        tree_copy=tree_copy.leftChild    else:        tree_copy=tree_copy.rightChild    if tree_copy.name!=None:        reimg.append(tree_copy.name)        tree_copy=tree#变为二维列表存储reimage=[]for i in range(0,256):    reimage.append([])    for j in range(0,256):        reimage[i].append(reimg.pop(0))#变为数组形式,并转置iii=np.array(reimage)iii=iii.T#变为图像image=Image.fromarray(iii.astype('uint8')).convert('L')#展示并保存为dd.bmpimage.show()image.save('dd.bmp')

运行结果

对如下图像编码(大小为256* 256,因为不能上传bmp图像,所以示例如下)

得到的两个文件,一个是像素值与编码的对应关系,一个为图像的编码结果

转载于:https://www.cnblogs.com/Qi-Lin/p/10924728.html

你可能感兴趣的文章
2018-2019-1 20189215《Linux内核原理与分析》第五周作业
查看>>
ubuntu 16.04 忘记root密码的处理方法
查看>>
Linux下错误的捕获:全局变量errno和strerror()
查看>>
js return无效,表单自动提交
查看>>
verilog case 语句合并问题
查看>>
python3.4 使用BeautifulSoup问题
查看>>
ASCII、Unicode和UTF-8等常见字符编码格式介绍
查看>>
英文自动换行的解决方法
查看>>
python-列表解析、字典解析、集合解析
查看>>
作为互联网初创公司,应该具备的条件(一):概述
查看>>
安卓ROOT工具汇总
查看>>
大臣的旅费
查看>>
20180101
查看>>
查看SQL SERVER Job details
查看>>
ts关键还是js 因为要编译成js
查看>>
南阳56
查看>>
基于android studio的快捷开发(将持续更新)
查看>>
《构建之法》阅读笔记03
查看>>
理解多线程中的ManualResetEvent(C#)
查看>>
.Net实现微信公众平台开发接口(二) 之 “获取access_token”
查看>>