JPEG图像压缩算法的python实现

摘要

文章在研究JPEG压缩编码对图像数据压缩的基本原理的基础上,设计了JPEG图像压缩算法程序实现流程,利用 Python语言对程序进行了编写,并实现了对压缩质量进行控制,验证了JPEG压缩编码对图像数据压缩的可行性。
用 JPEG压缩软件将图像从原图像中输出并对它进行重建,通过直观比较,发现用 JPEG压缩软件压缩图像对原图像的显示和感官仍然非常好。通过对输出的压缩比等参数的研究,科学地论证了JPEG 压缩编码对图像数据巨大的压缩效果以及良好的压缩质量。

引言

图像等媒体信息的记录、存储正朝着数字化的方向发展。而这些被数字化的图像的数据量之大是非常惊人的。这些大容量的数据无疑对存储器容量、计算机的速度都造成极大的压力。解决这一问题,如果单纯地扩大存储器容量,在存储和处理的时候不仅因为图像数据量大而造成大量问题,同时在图像数据的传输过程中也因为网络带宽的限制而极大的制约着网络多媒体技术的发展。通信网络的飞速发展使数据流量变得越来越大,复杂性也在不断增长,仅仅依靠加大通信干线的流量是不太现实的。但是如果能通过数据压缩手段把信息数据量压缩下来,以压缩的形式存储和传输,既节约了存储空间,又提高了通信干线的传输效率,同时也使计算机能实时处理高质量的音频、视频信息。通过压缩图像数据,其最直接的作用在于,可以降低图像传输所需的带宽,同时不再需要另外的实体设备或存储容量,可以达到更高的传输精度。由此可以看出,对静态图像进行压缩是绝对必要的。
图像压缩编码是在对数字图像进行大量统计分析,在掌握和了解图像信息的统计特性的基础上,充分利用图像本身的相关性强的特点,寻求消除或减少相关性或改变图像信源概率分布不均匀性的方法,以实现图像数据的压缩。

1 JPEG压缩算法基础介绍

1.1 简介

JPEG( Joint Photographic Experts Group)即联合图像专家组,是用于连续色调静态图像压缩的一种标准,文件后缀名为.jpg或.jpeg,是最常用的图像文件格式。其主要是采用预测编码(DPCM)、离散余弦变换(DCT)以及熵编码的联合编码方式,以去除冗余的图像和彩色数据,属于有损压缩格式,它能够将图像压缩在很小的储存空间,一定程度上会造成图像数据的损伤。尤其是使用过高的压缩比例,将使最终解压缩后恢复的图像质量降低,如果追求高品质图像,则不宜采用过高的压缩比例。
JPEG可以用有损压缩方式去除冗余的图像数据,用较少的磁盘空间得到较好的图像品质。而且JPEG是一种很灵活的格式,具有调节图像质量的功能,它允许用不同的压缩比例对文件进行压缩,支持多种压缩级别,压缩比率通常在10;1到40;1,压缩比越大,图像品质就越低;相反地,压缩比越小,图像品质就越高。同一幅图像,用JPEG格式存储的文件是其他类型文件的1/10~1/20,通常只有几十KB,质量损失较小,基本无法看出。JPEG格式压缩的主要是高频信息,对色彩的信息保留较好,适合应用于互联网;它可减少图像的传输时间,支持24位真彩色;也普遍应用于需要连续色调的图像中。[1]

1.2 优缺分析

1.2.1 优点

支持极高的压缩率,因此JPEG图像的下载速度大大加快;
能够轻松地处理16.8M颜色,可以很好地再现全彩色的图像;
在对图像的压缩处理过程中,该图像格式可以允许自由地在最小文件尺寸和最大文件尺寸之间选择;
文件尺寸相对较小,下载速度快,有利于在带宽并不“富裕”的情况下传输。

1.2.2 缺点

并非所有的浏览器都支持将各种JPEG图像插入网页;
压缩时,可能使图像的质量受到损失,因此不适宜用该格式来显示高清晰度的图像。[2]

2 JPEG压缩算法步骤及分析

JPEG压缩算法完整流程图

2.1 图像分割

JPEG算法的第一个步骤是将一张图像分割成 8X8的片段,以便后续对这些片段进行处理,这些片段通过后续的单独处理,使整个压缩过程更为方便。
将图像分为8*8大小的小块

2.2 颜色空间转换

所谓“颜色空间”,是指表达颜色的数学模型,比如我们常见的“RGB”模型,就是把颜色分解成红绿蓝三种分量,这样一张图片就可以分解成三张灰度图,数学表达上,每一个8X8的图案,可以表达成三个8X8的矩阵,其中的数值的范围一般在[0,255]之间,如图所示。
图像的8*8矩阵表示

不同的颜色模型各有不同的应用场景,例如RGB模型适合于像显示器这样的自发光图案,而在印刷行业,使用油墨打印,图案的颜色是通过在反射光线时产生的,通常使用CMYK模型,而在JPEG压缩算法中,需要把图案转换成为YCbCr模型,这里的Y表示亮度(Luminance),Cb和Cr分别表示绿色和红色的“色差值”。
“色差”概念的产生源自电视业,早期的电视机都是黑白两种颜色,那时传送电视信号,仅需传送亮度信号也就是 Y信号。而彩色电视机出现在那以后,人们在 y信号之外又添加两条色差讯号来传输色彩信息,这样的做法就是兼容黑白电视机,黑白电视机只需要处理该讯号中的 Y讯号即可。
根据三基色原理,人们发现红绿蓝三种颜色所贡献的亮度是不同的,绿色的“亮度”最大,蓝色最暗,设红色所贡献的亮度的份额为KR,蓝色贡献的份额为KB,那么亮度为:
在这里插入图片描述

根据经验,KR=0.299,KB=0.114,那么:
在这里插入图片描述

蓝色和红色的色差的定义如下:
在这里插入图片描述

最终可以得到RGB转换为YCbCr的数学公式为:
在这里插入图片描述

后续python程序实现JPEG压缩算法时,考虑到调用numpy库压缩效率将远远超过使用for循环,因此采用上式的矩阵表达形式。
为什么我们把一个看似毫不相关的色彩空间转换算法添加到压缩算法中呢?这并非画蛇添足,在文章开始时提到有损压缩的基本原理,有损压缩首先要做的事情就是“把重要的信息和不重要的信息分开”,YCbCr恰好能做到这一点。由于人眼的构造,图像中的明暗变化对于人眼而言更容易被感知。根据本学期另一门专业选修课程的知识,在视网膜上有两种感光细胞,分别是能观测光线变化的视杆细胞,与能观测色彩的视锥细胞,由于视杆细胞比视锥细胞数目要多,我们更加能够观测出明暗变化的细节。比如说下面这张图:
JPEG图像转为YCbCr图像

可以看出,亮度图的细节更加丰富。JPEG把图像转换为YCbCr图像之后,就可以针对数据得重要程度的不同做不同的处理。这就是为什么JPEG使用这种颜色空间的原因。

2.3 离散余弦变换

离散余弦变换(Discrete cosine transform),简称DCT,是JPEG算法中的核心内容。离散余弦变换属于傅里叶变换的另外一种形式,当要处理的不再是函数,而是一堆离散的数据时,并且这些数据是对称的话,那么傅里叶变化出来的函数只含有余弦项,这种变换称为离散余弦变换。举个例子,有一组一维数据[x0,x1,x2,…,xn-1],那么可以通过DCT变换得到n个变换级数Fi:
在这里插入图片描述

此时原始数据Xi可以通过离散余弦变换变化的逆变换(IDCT)表达出来:
在这里插入图片描述

也就是说,经过DCT变换,可以把一个数组分解成数个数组的和,如果我们数组视为一个一维矩阵,那么可以把结果看做是一系列矩阵的和:
在这里插入图片描述

在JPEG压缩过程中,经过颜色空间的转换,每一个8X8的图像块,在数据上表现为3个8X8的矩阵,紧接着我们对这三个矩阵做一个二维的DCT转换,二维的DCT转换公式为:
在这里插入图片描述

举个例子,比如一个所有数值都一样的矩阵,经过DCT转换后,将所有级数组合成一个新的矩阵:
在这里插入图片描述

可以看到,经过DCT转换,矩阵被全部集中在左上角的直流分量F(0,0)上,其他位置都变成了0。在实际的JPEG压缩过程中,由于图像本身的连贯性,一个8X8的图像中的数值一般不会出现大的跳跃,经过DCT转换会有类似的效果,左上角的直流分量保存了一个大的数值,其他分量都接近于0。我们以Lenna左上角第一块图像的Y分量为例,经过变换的矩阵为:
在这里插入图片描述

数据经过DCT变化后,被明显分成了直流分量和交流分量两部分,为后面的进一步压缩起到了充分的铺垫作用,可以说是整个JPEG中最重要的一步。

2.4 量化

图像经过离散余弦变换,图像数据虽然已经面目全非,但仍然是处于可逆状态,并没有进入有损压缩中有损的那一步。接下来我们看一下数据中的细节是如何被滤去的,经过颜色空间转换和离散余弦变换,每一个8X8的图像块都变成了三个8X8的浮点数矩阵,分别表示Y,Cr,Cb数据。比如以其中某个亮度数据矩阵举例,它的数据如下:
在这里插入图片描述

在可以损失一部分精度的情况下,如何用更少的空间存储这些浮点数?答案是使用量子化(Quantization),简称量化。“量子”这个概念来自于物理学,意思是说连续的能量可以看做是一个个单元体的组合,比如游戏中在处理角色面朝方向时,一般并不是使用0到2π这样的浮点数,而是把方向分成16个区间,用0到16这样的整数来表示,这样只用4个bit就足够了。JPEG提供的量化算法如下:
在这里插入图片描述

其中round函数是取整函数,但考虑到四舍五入,也就是说:
在这里插入图片描述

G是需要处理的图像矩阵,Q称作量化系数矩阵(Quantization matrices),JPEG算法提供了两张标准的量化系数矩阵,分别用于处理亮度数据Y和色差数据Cr以及Cb:
在这里插入图片描述

在这里插入图片描述

以左上角的-415.38为例,对应的量子化系数是16,那么round(-415.38/16)=round(-25.96125)=-26。最终得到的量子化后的结果为:
在这里插入图片描述

可以看到,大部分数据变成了0,这非常有利于后面的压缩存储。有损压缩就是把数据中重要的数据和不重要的数据分开,然后分别处理。DCT系数矩阵中的不同位置的值代表了图像数据中不同频率的分量,这两张表中的数据时人们根据人眼对不不同频率的敏感程度的差别所积累下的经验制定的,一般来说人眼对于低频的分量必高频分量更加敏感,所以两张量化系数矩阵左上角的数值明显小于右下角区域。在实际的压缩过程中,还可以根据需要在这些系数的基础上再乘以一个系数,以使更多或更少的数据变成0,我们平时使用的图像处理软件在生成jpg文件时,在控制压缩质量的时候,就是控制的这个系数,后续在程序实现中也会体现。
2.5 ZigZag编排
在量化之后,8*8的矩阵仍然是二维矩阵,如何调整我们DCT的结果能更高地提升压缩率呢?观察量化后的矩阵,我们发现大量信息都集中在左上角,所以我们采用ZigZag编排:
ZigZag编排顺序示意图

这么做的目的只有一个,就是尽可能把0放在一起,由于0大部分集中在右下角,所以才去这种由左上角到右下角的顺序,经过这种顺序变换,最终矩阵变成一个整数数组。
2.6 RLE编码
行程编码(Run Length Encoding)又称“运行长度编码”或“游程编码”,它是一种无损压缩编码。例如:5555557777733322221111111,这个数据的一个特点是相同的内容会重复出现很多次,那么就可以用一种简化的方法来记录这一串数字,如(5,6)(7,5)(3,3)(2,4)(1,7)即为它的行程编码。行程编码的位数会远远少于原始字符串的位数。举个例子来看一下:57,45,0,0,0,0,23,0,-30,-16,0,0,1,0,0,0,0 ,0 ,0 ,0,…,0,可以表示为:(0,57) ; (0,45) ; (4,23) ; (1,-30) ; (0,-16) ; (2,1) ; EOB。即每组数字的头一个表示0的个数,而且为了能更有利于后续的处理,必须是 4 bit,就是说,只能是 0~15,这是这个行程编码的一个特点。JPEG使用了1个字节的高4位来表示连续“0”的个数,而使用它的低4位来表示编码下一个非“0”系数所需要的位数,跟在它后面的是量化AC系数的数值。其中(0,0)和(15,0)比较特殊,(0,0)代表块结束,(15,0)代表已经有16个连续的0。
由于作业要求中提到可以选择RLE编码或Huffman编码进行压缩,我在后续程序实现中只选择了RLE一种编码方式。

3 成果演示及分析

运行时可以输入质量因子,控制压缩比(压缩比越高,图像质量越差)。

主要实现方法是在量化步骤时,对JPEG亮度量化表和色度量化表乘以一个质量因子Q,改变表内数据。质量因子Q为1时,相当于JPEG标准量化表,质量因子越大,压缩比越大,质量越差;质量因子越小,压缩比越小,质量越好。以Lenna为例:
左为原图,右为质量因子为1时压缩后结果

质量因子为1,相当于JPEG标准量化表压缩结果,程序还计算了压缩比约为8.023013598016913,PSNR(即峰值信噪比)值约为29.634010562060844(PSNR值越高,与原始图像越相似。PSNR高于40dB说明图像质量极好,在30—40dB通常表示图像质量是好的,在20—30dB说明图像质量差,PSNR低于20dB图像不可接受)。

随着质量因子的增大,图像质量逐渐降低,但压缩比也逐渐提高。

5 结语

本文简要分析了jpeg图像压缩算法的基本原理和实现过程,并通过python实现了算法,在保证图片PSNR值在20以上时,可以达到接近90%的压缩率(如果实现Huffman编码,压缩率应该会有进一步地提升)。
但是相较于格式工厂的压缩,我的算法得到的与原图差距仍存在很多问题:压缩速率远低于格式工厂(500KB左右图像大约需要5秒,这已经是我在优化算法中所有可以使用numpy库代替for循环运算之后的结果),部分细节不明显,图像边缘出现失真(尤其是对于图像中出现颜色突变的部分,以及一些低分辨率图像,这个问题较为严重)等问题。
尽管在过程中遇到了许许多多解决了和仍未解决的困难,但通过本次大作业,我更加深入全面地理解了JPEG图像压缩算法的原理,同时也极大地提升了自己的动手能力。相信随着技术的进步,各种压缩方法会越来越多,质量越来越好,得到进一步的发展与应用。

参考文献:

[1] 吴娱.数字图像处理:北京邮电大学出版社,2017:47-48.
[2] 李小平.多媒体技术:北京理工大学出版社,2015:185.
[3] JPEG压缩原理详解:https://www.cnblogs.com/Arvin-JIN/p/9133745.html.
[4] 二维离散余弦变换2D-DCT实战:https://blog.csdn.net/ahafg/article/details/48808443.
[5] ZigZag变换加速,空间换时间做法:https://my.oschina.net/tigerBin/blog/1083549.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/353191.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

图像及图像压缩的研究

一、图片格式、应用场景 1、BMP格式 BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格…

unity图像压缩算法原理

概述 在计算机图形学中,存在许多纹理压缩方案。压缩既减少了纹理内存占用,又降低了使用纹理的带宽要求。本文中,“纹理压缩”与“图像压缩”不同,因为纹理压缩方案的设计允许作为纹理采样的一部分进行有效的随机访问。“图像压缩…

【图像压缩】有损压缩实现无损预测

updating... 1 绪论 一篇很好的结合对比学习与特征压缩的工作。 本文贡献: 1.公式化面向下游预测任务压缩的概念 2.描述了在增强不变性任务上高表现所需要的比特数。 3.提出无监督目标函数训练压缩器近似最优码率。 4.结合zero-shot方法CLIP,在Ima…

基于PCA的图像压缩实现

基于PCA的图像压缩实现 注:该内容为校内课程实验,仅供参考,请勿抄袭! 源码:PPCA-for-Image-Compession 摘要   随着计算机互联网的发展和数据的日益增长,如何高效的处理和传输海量数据成为大数据处理的…

基于深度学习的图像压缩

近年来,深度学习在计算机视觉领域已经占据主导地位,不论是在图像识别还是超分辨重现上,深度学习已成为图片研究的重要技术,但它们的能力并不仅限于这些任务;现在深度学习技术已进入图片压缩领域。下面就说说神经网络在…

图像压缩算法

这里说​十种常用的图像压缩算法 数据压缩是保留相同或绝大部分数据前提下减小文件大小的过程。它的原理是消除不必要的数据或以更高效的格式重新组织数据。在进行数据压缩时,你可以选择使用有损方法或无损方法。有损方法会永久性地擦除掉一些数据,而无…

C#图像压缩相关方法总结

前往我的主页以获得更好的阅读体验C#图像压缩相关方法总结 - DearXuan的主页https://blog.dearxuan.com/2022/02/07/C-%E5%9B%BE%E5%83%8F%E5%8E%8B%E7%BC%A9%E7%9B%B8%E5%85%B3%E6%96%B9%E6%B3%95%E6%80%BB%E7%BB%93/ 前言 本文所描述的所有内容和算法,均未使用任…

Matlab实现图像压缩

文章和代码以及样例图片等相关资源,已经归档至【Github仓库:digital-image-processing-matlab】或者公众号【AIShareLab】回复 数字图像处理 也可获取。 文章目录 目的原理图像压缩原理离散余弦变换(DCT)图像压缩原理行程编码(RLE&#xff09…

图像压缩相关内容简介

历史 图像压缩的研究起源于20世纪40年代。1948年香农的经典论文《通信的数学原理》中首次提到信息率深圳函数的概念,1959年他又建立了率失真理论,从而奠定了信源编码的理论基础。随后伯杰等人有对其进行了深入的研究,并取得了一定的进步&…

移动端做安全测试的重要性

安全性测试的目的是发现危害手机中数据的安全和完整性的错误和缺陷。发现安全错误通常是比较困难的,软件通常功能运行正常但却不安全。 一、软件权限 APP软件权限包括:网络通信、信息发送、自动启动、 媒体录制、读取用户信息、写入用户数据等权限,因关系到用户个人信息和隐私…

cad 打开硬件加速卡_CAD如何根据已知条件设计图形

1、打开CAD,在左下角把极轴追踪打开(鼠标右键点击,选择90度打√)、把对象捕捉打开(鼠标右键点击,选择中点)。 2、然后在操作界面画线,如图我们已知直角边885和750,方法是按长8852、高750来绘制三点定圆弧。先画8852177…

C#ObjectArx Cad将图形范围缩放至指定实体

先上代码&#xff08;亲测可用&#xff09;&#xff1a; /// <summary>/// 定位缩放值指定实体/// </summary>/// <param name"oid"></param>public static void Orientate(ObjectId oid){try{Entity current_entity GetEntity(oid);curren…

CAD图层设置

一、图层介绍 我们可以把图层想象为一张没有厚度的透明纸&#xff0c;各层之间完全对齐&#xff0c;一层上的某一基准点准确地对准其他各层上的同一基准点。用户可以给每一图层指定所用的线型、颜色&#xff0c;并将具有相同线型和颜色的对象放在统一图层&#xff0c;这些图层…

cad打印本计算机未配置,CAD打印的基本设置详细教程

CAD打印的基本设置详细教程 开始画图之前我们就考虑到打印的需要&#xff0c;要用多大纸张&#xff0c;打印比例应该设置成多少&#xff0c;打印后的字高、线宽、颜色应该设置成多少&#xff0c;在绘制图形的时候&#xff0c;这些为打印而做的准备工作必须做好。要想正确地打印…

CAD打印图形、输出图形

打印图形 指定打印范围、打印比例、图纸大小、打印样式、页边距等参数&#xff0c;打印图纸。 1.单击常用工具栏的“打印图形”按钮。 2.在命令行中输入Plot&#xff0c;按回车键。 打印界面如下 &#xff1a; 界面信息 &#xff08;1&#xff09;选择打印机&#xff1a;默…

CAD梦想画图中如何设置图层

图层介绍 我们可以把CAD对象想象成一张没有厚度的透明纸&#xff0c;各层之间完全对齐&#xff0c;一层上的某一基准点准确的对准其它各层上的同一基准点。用户可以给每一图层指定所用的线型、颜色与线宽&#xff0c;并将其相同线型和颜色的对象放在同一图层&#xff0c;这些图…

AUTOCAD——图形单位与图形边界

图形单位 控制长度与角度的显示精度与格式。 1.执行方式 命令行&#xff1a;DDUNITS 菜单栏&#xff1a;格式→单位 “图形单位操作命令位置”界面 执行以上命令后&#xff0c;系统会弹出如下图所示的“图形单位”对话框。 2.选项说明 &#xff08;1&#xff09;长度与角…

OSSIM进行主机漏洞扫描(03)

OSSIM进行主机漏洞扫描方式 按照如图选择&#xff0c;ENVIRONMENT–SCAN JOBS–NEW SCAN JOB进入新增页面 其中各选项含义如下 Job Name:扫描任务名称。 Select Sensor:扫描的嗅探器。 Profile:扫描的类型&#xff0c;包括Deep- Non destructive Full and Slow scan(深入)、D…

Spring Boot 系统初始化器详解

Spring Boot 3.x系列文章 Spring Boot 2.7.8 中文参考指南(一)Spring Boot 2.7.8 中文参考指南(二)-WebSpring Boot 源码阅读初始化环境搭建Spring Boot 框架整体启动流程详解Spring Boot 系统初始化器详解 自定义系统初始化器 Spring Boot 有多种加载自定义初始化器的方法&am…

网络故障管理

网络故障管理是以最快的方式查找、隔离和排除网络故障的过程。故障管理是网络管理的重要组成部分&#xff0c;它通过快速解决故障来最大限度地减少停机时间并防止设备故障&#xff0c;从而确保最佳的网络可用性并防止业务损失。 网络故障监控是故障管理的第一步&#xff0c;因…