图像压缩——LZW压缩算法
文章首发于我的个人博客
1. LZW基础概念
之前提到的算术编码、霍夫曼编码等技术集中在消除编码的冗余上,而本文要讲的LZW编码是一种针对空间冗余的无误差压缩方法。
LZW算法o又叫“串表压缩算法”,就是通过建立一个将字符串和其对应的记号构成的表(把已经出现过的字符串映射到记号上),用较短的代码来表示较长的字符串来实现压缩。
需要注意的是,LZW算法中字符串和记号的对应关系是在压缩的过程中动态生成的,并且隐含在压缩数据中,解压的时候也是一步一步还原编码并动态生成字典的过程。
2. LZW算法详解
2.1 LZW编码算法
编码器从字符串中不断地读入新的字符,并且将字符或字符串映射到新的记号,以动态地构建编码字典。在编码过程中,我们维护两个变量,即previous_char
(表示目前已有的,但未被编码的字符)和current_char
(表示刚刚读入的字符)。编码算法流程如下
- (1)初始状态,
previous_char
和current_char
都是空的。 - (2)读入新的字符current_char,并于previous合并成新的字符串
p_and_c
(previous_char+current_car) - (3)在编码字典里查找
p_and_c
,如果:p_and_c
在字典里,previous_char = p_and_cp_and_c
不在字典里,将previous_char
的标记输出;在字典中建立p_and_c
的映射;更新previous_char = current_char
。
- (4)返回步骤(2),重复直至读完字符串。
2.2 Example
ababcababac
初始状态字典里有三个默认的映射
String | Symbol |
---|---|
a | 0 |
b | 1 |
c | 2 |
开始编码
previous_char | current_char | p_and_c | p_and_c in dict | Action | output |
---|---|---|---|---|---|
“” | a | a | Y | previous_char = a | - |
a | b | ab | N | 添加映射{‘ab’, 3} previous_char = b | 0 |
b | a | ba | N | 添加映射{‘ba’, 4} | 1 |
a | b | ab | Y | previous_char = ab | - |
ab | c | abc | N | 添加映射{‘abc’, 5} previous_char = c | 3 |
c | a | ca | N | 添加映射{‘ca’, 6} previous_char = a | 2 |
a | b | ab | Y | previous_char = ab | - |
ab | a | aba | N | 添加映射{‘aba’, 7} previsou_char = a | 3 |
a | b | ab | Y | previous_char = ab | - |
ab | a | aba | Y | previous_char = aba | - |
aba | c | abac | N | 添加映射{‘abac’, 8} previous_char = c | 7 |
c | - | - | - | - | 2 |
编码结束,输出结果为0132372
,编码过程中生成的字典为:
String | Symbol |
---|---|
a | 0 |
b | 1 |
c | 2 |
ab | 3 |
ba | 4 |
abc | 5 |
ca | 6 |
aba | 7 |
abac | 8 |
2.2 LZW解码算法
解码器输入的是压缩后的数据。同时,我们将维护两个变量previous_symbol
(目前已有的但未被处理的记号),current_symbol
(当前读入的记号)。算法流程如下
- (1)初始状态,
previous_symbol
和current_symbol
都为空。 - (2)读入第一个记号,并赋给
current_symbol
,并解码直接输出。因为第一个字符为单个字符,一定可以直接解码。 - (3)赋值,
previous_symbol = current_symbol
- (4)在字典里查找
current_symbol
,如果:current_symbol
在字典里:- 将
current_symbol
解码的结果输出 previous_char = dict.get(previous_symbol)
,current_char = dict.get(current_symbol)[0]
。注意,这里current_char
为current_symbol
解码的第一个字符。- 将
p_and_c
添加到新的映射
- 将
current_symbol
不在字典里:previous_char = dict.get(previous_symbol)
,current_char = dict.get(previous_symbol)[0]
。注意,这里current_char
为previous_symbol
解码的第一个字符。- 将
p_and_c
添加到新的映射 - 输出
p_and_c
- 返回步骤(3),直至读完所有记号。
2.4 Example
0 1 3 2 3 7 2
初始状态字典里有三个默认的映射
Symbol | String |
---|---|
0 | a |
1 | b |
2 | c |
开始解码:
首先读取第一个记号,current_symbol = 0
,输出解码结果dict.get(current_symbol)
,即a
赋值previous_symbol = current_symbol
,然后循环读取之后的记号。
previous_symbol | current_symbol | current_symbol in dict | Action | output |
---|---|---|---|---|
0 | 1 | Y | previous_char = a current_char = b p_and_c = ‘ab’ 添加映射{3, ‘ab’} | b |
1 | 3 | Y | previous_char = b current_char = a p_and_c = ‘ba’ 添加映射{4. ‘ba’} | ab |
3 | 2 | Y | previous_char = ab current_char = c p_and_c = ‘abc’ 添加映射{5, ‘abc’} | c |
2 | 3 | Y | previous_char = c current_char = a p_and_c = ca 添加映射{6. ‘ca’} | ab |
3 | 7 | N | previous_char = ab current_char = a p_and_c = aba 添加映射{7, ‘aba’} | aba |
7 | 2 | Y | previous_char = aba current_char = c P_and_c = abac 添加映射{8, ‘abac’} | c |
解码结束,输出结果为ababcababac
。解码过程中生成的字典为
Symbol | String |
---|---|
0 | a |
1 | b |
2 | c |
3 | ab |
4 | ba |
5 | abc |
6 | ca |
7 | aba |
8 | abac |
2.5 代码实现(python)
def encode_init():k = 0char_num_dict = {}for i in range(97,123):char_num_dict[chr(i)] = kk += 1# print(char_num_dict.items())return char_num_dictdef decode_init():k = 0num_char_dict = {}for i in range(97,123):num_char_dict[str(k)] = chr(i)k += 1# print(char_num_dict.items())return num_char_dictdef LZW_encode(strList, char_num_dict):symbol = 26 # 标记previous_char = "" # 已有的,但未被编码的字符current_char = "" # 当前读入的字符p_and_c = ""output = "" # 输出的编码序列for s in strList:current_char = sp_and_c = previous_char + current_char# print(previous_char, s)if char_num_dict.get(p_and_c) != None:previous_char = p_and_celse:output += str(char_num_dict.get(previous_char)) + '-'char_num_dict[p_and_c] = symbolsymbol += 1 previous_char = current_charoutput += str(char_num_dict[s[-1]])print(char_num_dict.items())return outputdef LZW_decode(output, num_char_dict):output_list = output.split('-')print(output_list)symbol = 26previous_symbol = ""current_symbol = ""previous_char = ""current_char = ""decodeList = ""decodeList += num_char_dict.get(output_list[0])previous_symbol = output_list[0] for o in output_list[1:]:current_symbol = o # print(previous_symbol, current_symbol)if num_char_dict.get(current_symbol) != None:decodeList += num_char_dict.get(current_symbol)previous_char = num_char_dict.get(previous_symbol)current_char = num_char_dict.get(current_symbol)[0]num_char_dict[str(symbol)] = previous_char + current_charsymbol += 1 else:previous_char = num_char_dict.get(previous_symbol)current_char = num_char_dict.get(previous_symbol)[0]num_char_dict[str(symbol)] = previous_char + current_charsymbol += 1decodeList += previous_char + current_charprevious_symbol = current_symbol# print(num_char_dict.items())return decodeListif __name__ == '__main__':strList = input("请输入字符序列:").lower()print('字符序列长度:', len(strList))char_num_dict = encode_init()output = LZW_encode(strList, char_num_dict)print(output)num_char_dict = decode_init()# print(num_char_dict.items())decodeList = LZW_decode(output, num_char_dict)print(decodeList)print("编码长度:", len(output) / 2)
图像压缩——LZW压缩算法相关推荐
- LZW压缩算法解码器实现
本文先给出具体的代码实现,懂一些LZW算法理论,基本上如果静下心来,都能看明白解码器的实现.如果不太清楚LZW,可以查看下以前的一篇帖子:http://www.cnblogs.com/jillzhan ...
- 基于xilinx FPGA实现LZW压缩算法
1 LZW算法简介 数据压缩分为有损压缩和无损压缩.有损压缩是对压缩后的数据进行重构 (解压缩 ) ,重构后的数据与原来的数据有所不同,换来了大的压缩比.无损压缩指对压缩后的数据进行重构 ,重构后的数 ...
- 数据压缩课程作业——LZW压缩算法完整仿真代码和分析
前言 关于数字压缩课程的作业记录,附完整代码 一.算法描述 1.1 算法特点 LZW压缩算法是一种无损数据压缩算法.在众多的压缩技术中,LZW算法是一种通用的.性能优良并得到广泛应用的压缩算法,它是一 ...
- lzw压缩 java_java实现的LZW 压缩算法源码 | 学步园
导读:/* * LZW.java * * Created on 01 Dec 2005 * * Implementation of LZW compression/decompression algo ...
- LZW压缩算法原理解析与实现【转载】
LZW算法原理--Wikipedia相关介绍 一个简单的例子 ZW编码 (Encoding) 的核心思想其实比较简单,就是把出现过的字符串映射到记号上,这样就可能用较短的编码来表示长的字符串,实现压缩 ...
- 数字图像处理(八)图像压缩-有损压缩/压缩算法+matlab
有损压缩/压缩算法实验 1.问题及说明 查阅JPEG编码的有关资料,对图像进行JPEG压缩,算法步骤必须包括如下几个部分:图像分块,离散余弦变换,量化,ac和dc系数的Z字形编排. 在输入灰度图像时直 ...
- LZW数据压缩算法的原理分析
1.LZW的全称是什么? Lempel-Ziv-Welch (LZW). 2. LZW的简介和压缩原理是什么? LZW压缩算法是一种新颖的压缩方法,由Lemple-Ziv-Welch 三人共同 ...
- lz78算法c语言,LZW数据压缩算法研究
内容介绍 LZW数据压缩算法研究 46页 3.2万字 摘 要 随着信息化技术的蓬勃发展,日常需要处理或者传输的数据越来越多,数据的压缩也就变得越来越重要了.我们迫切的需要有好的压缩算法来支持我们的数据 ...
- 你发表情包全靠他,GIF压缩算法发明者之一获IEEE最高荣誉奖
点击上方,选择星标或置顶,不定期资源大放送! 阅读大概需要5分钟 Follow小博主,每天更新前沿干货 转载自:量子位 现年90岁的以色列科学家Jacob Ziv,获得了2021年IEEE荣誉奖章(I ...
最新文章
- ubuntu16.04安装opencv3.4.1教程
- 多帧点云拼接的全局ICP算法【附Matlab代码链接】
- 宇宙膨胀背后的故事(卅三):宇宙之有生于无
- Unity5 AssetBundle系列——简单的AssetBundleManager
- yum安装JAVA centos下使用yum安装jdk
- python拼接mysql时遇到unsupported format character ‘?‘ “(0x82f1)“
- Codeforces 1025F Disjoint Triangles (计算几何)
- Java树形转扁平_js把树形数据转成扁平数据
- javascript系列:NaN类型
- aop cache再讨论
- java歌词解析器_设计模式学习(四):基于Builder模式的歌词解析器
- photoshop基础视频教程 [4G]
- 低功耗实例——isolation cell及level shifter的选择
- 牛逼!这个C++跳棋游戏居然可以让你边玩游戏边学编程!
- php 即时通讯插件,四款可以整合到网站的网页版即时通信IM插件系统
- 6月 CSDN 创作者之夜:获奖名单公布
- 基于pion生态的SFU实时音视频发布服务(一)
- 学生信息管理系统python
- 智能电话机器人(AI语音机器人)是什么
- 96张完整PPT清晰解读全球智能制造趋势!