设计任务、目的和要求
- 设计任务:对一幅图像进行LZW编码和解码
- 目的:熟悉Python编程实现LZW编解码,加深对LZW编码和解码原理及实现过程的理解
- 要求:根据上课所学LZW原理独立实现对图像的编解码
总体方案设计
系统运行环境:Python3.x
编程软件平台:Python自带的IDLE
编码算法基本思想:
起初,构造信源字符序列的编码码本(字典)每个字符序列对应一个索引值。压缩过程中 ,动态更新码本(字典)。每当压缩扫描图像时,字典中发现一个没有出现过的字符序列,就把该字符序列存到字典中。用字典的索引值作为这个字符序列的代码,替换原图中的字符序列。下次再碰到相同字符序列,就用字典索引值代替字符序列。压缩结果,除压缩图像外,不需保留压缩过程中形成的字典,只是解压缩时,临时恢复此字典
编码规则
- 设:S为输入字符串变量;R为临时变量。
- 判断“RS”是否存在于字符串表(字典)中
- 如果字典表中存在“RS”?
- 编码不输出任何结果 ,且令:R = RS ;
- 如果字典表中不存在“RS”?
- 更新字典,在字典表末尾为“RS”添加索引;
- 编码输出为R在字符串表中索引,令R =S
解码规则
- 设:S为输入字符串变量;R为临时变量 。
- 读入第一个码字“S”,解码输出其在字典中对应的字符串值,且令 R = S。
- 读入下一码字“S”,判断“S”是否在字典中,如果字典中存在“S”?
- 更新字典,将“R字串”和“S字串第一个字符”
- 构成新串,添加字典末尾;
- 解码输出S字串值;并且,令 R = S ;
- 如果字典中不存在“S”?
- 将“R字串”和“R字串第一个字符”构成新串,
- 添加字典末尾;
- 解码输出该新串;并且,令R =S。
算法流程图设计
代码实现
import matplotlib.pyplot as plt #导入第三方库
import matplotlib.image as image #导入第三方库
import numpy as np #导入第三方库
plt.rcParams["font.sans-serif"] = "SimHei" # 修改字体的样式可以解决标题中文显示乱码的问题
plt.rcParams["axes.unicode_minus"] = False # 该项可以解决绘图中的坐标轴负数无法显示的问题
img = image.imread('D:/PANDA.bmp') #读取图片
##编码函数的定义
def Encode(img):
plt.subplot(121) #设置子图
plt.title('原始图像')
shape=img.shape
plt.imshow(img,cmap='gray') #显示原始图像,便于对比
img1=img.flatten() #图像序列化
dict1=dict(zip(np.array(range(256),dtype='str'),range(256))) #构建初始化字符串表
dict1['LZW_CLEAR']=len(dict1) #构建初始化字符串表
dict1['LZW_EOI']=len(dict1) #构建初始化字符串表
result=[] #定义编码结果存放位置
R= '' #初始化R
result.append(dict1['LZW_CLEAR']) #读取开始字符
for S in img1: #依次读入每个待编码数据
if R=='': #第一次读
temp=str(S)
else:
temp=R +'-'+ str(S) #构成RS
if temp in dict1.keys():
R=temp #RS在字典中,就令R=RS
else:
dict1[temp]=len(dict1) #RS不在字典中,更新字典
result.append(dict1[R]) #RS不在字典中,输出R索引
R = str(S) #RS不在字典中,就令R=S
result.append(dict1[R]) #将最后一个R输出
result.append(dict1['LZW_EOI']) #输出结束符
return result,shape #返回输出结果,编码完成
##解码函数的定义
def Decode(code_stream,shape):
img="" #解码结果放在img字符串中
S = code_stream.pop(0) #读取开始字符
values=[str(x)+'-' for x in range(S)] #构建初始化字典的索引
dict1=dict(zip(range(S),values)) #构建初始化字典
dict1[len(dict1)]='LZW_CLEAR' #构建初始化字典
dict1[len(dict1)]='LZW_EOI' #构建初始化字典
R='' #临时变量R
for i in range(len(code_stream)): #循环读入码流
S=code_stream.pop(0) #取第一个码字
if S in dict1.keys(): #如果S在字典中
if R=='':
img+=(dict1[S]) #数据为第一个码字
R=S #R=S
else:
head=dict1[S].split('-')
temp=dict1[R]+head[0]+'-' #构建RS
dict1[len(dict1)]=temp #更新字典
img+=(dict1[S]) #输出S
R=S #R=S
else: #如果S不在字典中
head=dict1[R].split('-')
temp=dict1[R]+head[0]+'-' #构建RS
dict1[len(dict1)]=temp #更新字典
img+=(temp) #输出RS
R=S #R=S
img=img.rstrip('-LZW_EOI') #去掉输出的-LZW_EOI
img=np.array(img.split('-'),dtype=int) #输出结果类型转换
img=img.reshape(shape) #输出结果变为原始图像形状
plt.subplot(122) #设置第二个子图
plt.title('解码重构图像')
plt.imshow(img,cmap='gray') #绘制解码输出图像,便于对比
##调用函数
code,shape=Encode(img) #对输入图像编码
Decode(code,shape) #通过编码结果进行解码
plt.show()
运行结果
测试图片