JPEG压缩原理与DCT离散余弦变换——有实际的数据演示

http://blog.csdn.net/newchenxf/article/details/51719597

1 前言

JPEG是joint Photographic Experts Group(联合图像专家组)的缩写,文件后辍名为”.jpg”或”.jpeg”。 
jpg图片可以说是最常见的图片格式了,基本上你的自拍照,要么是png的,要么就是jpeg的了。(有关jpeg和png的区别,请参考我的另一博文【jpeg 与 png 图片格式的区别】) 
但它是一种有损压缩。支持多种压缩级别,压缩比率通常在10:1到40:1之间,压缩比越大,品质就越低;相反地,压缩比越小,品质就越好。

那么,JPEG是如何压缩的呢?靠的就是传说中的DCT(离散余弦变换)。

下图是JPEG压缩/解压缩的流程图。我想你最大的疑问估计就是DCT了。 

2 JPEG压缩流程

2.1 以8x8的图象块为基本单位进行编码

如下图所示。比如一个160x160大小的原始图像,就可以分成20x20个8x8图像块。 
 
每个图像块共64个像素。像素可以用RGB或YUV表示,需要3个byte。所以严格来说,上图3个箭头代表的数据,指的是RGB/YUV的某一个值,比如Y。

2.2 将RGB转换为亮度-色调-饱和度系统(YUV),并重新采样

YUV是什么?它也是一种很不错的图像数据表示方法,特别是在视频领域。 
Y:指颜色的明视度、亮度、灰度值; 
U:指色调; 
V:指饱和度。

YUV是一个统称,其实有很多具体格式,比如YUV420, YUV444, YUV422。 
YUV的某些格式,和RGB比起来,其数据量要少很多。 
比如YUV420,每个像素需要一个Y,每4个像素需要一个U/V,因此一个8*8图像块,数据量只要8x8x3/2 = 96byte。而RGB需要8x8x3 = 192byte。少了一半的数据量。现在很多视频都是YUV420作为色域。 
当然啦,在本次转换,用的是YUV444, 也就是每个像素都有YUV的值。

YUV与RGB可以互相转换。 
Y=0.299R+0.587G+0.114B 
U=0.148R-0.289G+0.473B 
V=0.615R-0.515G-0.1B

2.3 FDCT与IDCT

一个是正变换,一个是逆变换。反正都可以称为离散余弦变换。 
根据8*8的二维DCT定义 
 
其中:0<= u, v < 8 
 
a(v) = a(u) 
 是输入8x8像素的坐标。 
 是输出的8x8变换结果的坐标。

不要把上式看的有多难,也不要被“离散余弦变换”这个词给吓到,其实他没什么(如果你非要去追究,那就打开“信号与系统”的书复习一下吧,我拦不住你哈),上式其实就是一个运算公式而已。 
输入就是8x8的数据矩阵,经过计算,输出还是一个8x8的数据矩阵。 
其实上式可以简化为: 
 
并且A和A转置矩阵都是已知的。所以,说白了,就是个矩阵运算。对程序来说,很简单。

称G(0,0),也就是输出8x8矩阵的(0,0)坐标的值,为直流系数,其他为交流系数。 
之所以称它为直流系数,是因为当u, v = 0时,cos()结果都为0,所以最后结果就是输入矩阵的8x8的每个数值的和,再乘于a(u) x a(v) x 1/4 = 1/8。

当然了,输入数据其实是有3个的,也就是YUV,因此对每个8x8的原始图像数据,需要做3次DCT。

2.4 量化与反量化

定义:将DCT变换后的临时结果,除以各自量化步长并四舍五入后取整,得到量化系数。 
为什么可以量化?! 
因为经过DCT后,数据就不同了,左上方都是大数值,右下方都是小数值。比如左上方都是几十几百的,右下方附近,都是个位数,那么,大数值和小数值就可以分别量化。

在术语里,左上方称为低频数据,右下方称为高频数据。 
你要是不理解,可以这么想,既然G(0,0)都是直流分量了,那频率不就是0?不就是所谓的低频?^^

还是不理解?好吧,那你也可以这么想: 
比如cos(ax),a是常数,x是变量。那么,根据频率f = a/2π,a越大,函数的频率越高。 
看看DCT公式: 
 
u,v 越大,则越在右下方对吧。当计算某个G(u, v)时,x, y是变量,u, v相当于常数,当u/v越大,则频率越高! 
这就是为啥右下方称为高频数据了!

好了,别走偏了,还继续说量化。 
JPEG系统分别规定了亮度分量和色度分量的量化表,色度分量相应的量化步长比亮度分量大。

对量化系数的处理和组织 
思想:JPEG采用定长和变长相结合的编码方法。 
直流系数:通常相邻8*8图象块的DC分量很接近,因此JPEG对量化后的直流分量采用无失真DPCM编码。通常JPEG要保存所需比特数和实际差值。

交流系数:经过量化后,AC分量出现较多的0。JPEG采用对0系数的行程长度编码。而对非0值,则要保存所需数和实际值。 
ZIG-ZAG排序:为使连续的0个数增多,采用Z形编码。 

你要是不理解,看看下面的例子,就知道为啥ZIG-ZAG可以俘获更多的0了!

3 应用举例

3.1 编码

某个图象的一个8*8方块,的亮度值。 

由于一个字节是0~255,为了减小绝对值波动,先把数值移位一下,变成-128~127。 

接着,根据DCT变换公式,各种计算,获得临时结果。 

根据亮度量化表量化后得到的量化系数矩阵 

获得量化结果: 

可见,新的数据,很小,很多是0。正如上文所说,这么多0,完全可以用游程编码,大大缩小数据量。

3.2 解码

先游程编码恢复为 

然后,根据量化表,恢复 

再根据反离散余弦变换的公式: 

结果为: 

再右移127,恢复原始。 

和原始图像的数据相比,基本是一样的,或者近似的!

4 其他

必须再强调的是,JPEG压缩是有损失的,从上面的例子就看出来,输出结果并不是完全等于输入。 
此外,JPEG压缩比例是可以控制的,只不过图像质量会变差。比如 
压缩率:10 

压缩率:50 

JPEG压缩比例,就是通过控制量化的多少来控制。比如,上面的量化矩阵Q,如果我把矩阵的每个数都double一下,那是不是会出现更多的0?!说不定都只有G(0, 0)非0,其他都是0,如果这样,那编码时就可以更省空间啦,N个0只要一个游程编码搞定,数据量超小。但也意味着,恢复时,会带来更多的误差,图像质量也会变差了。

参考: 
https://en.wikipedia.org/wiki/JPEG#Discrete_cosine_transform

时间: 2024-10-03 20:35:26

JPEG压缩原理与DCT离散余弦变换——有实际的数据演示的相关文章

优化IPOL网站中基于DCT(离散余弦变换)的图像去噪算法(附源代码)。

在您阅读本文前,先需要告诉你的是:即使是本文优化过的算法,DCT去噪的计算量依旧很大,请不要向这个算法提出实时运行的苛刻要求. 言归正传,在IPOL网站中有一篇基于DCT的图像去噪文章,具体的链接地址是:http://www.ipol.im/pub/art/2011/ys-dct/,IPOL网站的最大特点就是他的文章全部提供源代码,而且可以基于网页运行相关算法,得到结果.不过其里面的代码本身是重实现论文的过程,基本不考虑速度的优化,因此,都相当的慢. 这篇文章的原理也是非常简单的,整个过程就是进

基于离散余弦变换的同图复制的检测技术

本文是一则学习小结 图像篡改的背景及意义 ??目前图像已经成为人类社会中必不可少的一部分,人们的日常生活中到处都可以见到图像.特别在医学.商业.军事.情报.学术研究.法律和新闻领域中,图像作为原始事件或现象的真实记录,具有信息载体和数字证明的作用.然而人们渐渐发现图像的真实性已经不再可靠了.篡改图像出现的频率越来越大,要分辨出它们也越来越困难. 已知检测技术 数字水印 易损水印,半易损水印和鲁棒水印 水印在图像篡改之前存在 要求所有设备都带有水印装置是不可能的 盲检测技术 不依赖数字水印,是基于

InnoDB 数据表压缩原理与限制

http://liuxin1982.blog.chinaunix.net/uid-24485075-id-3523032.html 压缩理念 通过提高CPU利用率和节约成本,降低数据库容量及I/O负载,从而使数据吞吐率得到显著提高. 压缩原理 压缩表减少了磁盘上数据库的大小,使得用户不必频繁地操作写入和读取便可以访问数据.对于 InnoDB的工作量以及传统的用户表而言(特别是在某些读取密集型的应用中,内存有足够的空间存储常用数据),数据压缩不仅大大减少了数据库所需的存储空间,而且还减少了 I/O

JPEG压缩图像超分辨率重建算法

压缩图像超分辨率重建算法学习 超分辨率重建是由一幅或多幅的低分辨率图像重构高分辨率图像,如由4幅1m分辨率的遥感图像重构分辨率0.25m分辨率图像.在军用/民用上都有非常大应用. 眼下的超分辨率重建方法主要分为3类:基于插值.基于学习.基于重建的方法.现在已经研究得比較多.可是大多数算法都是对普通图像进行研究,针对压缩图像/视频超分辨率重建的研究比較少.近期查阅部分文献.进行了学习.在此做些总结. 相关的文献: 1.Super-resolution from compressed video 2

离散余弦变换(C++实现)

理论部分转载自这篇blog: http://blog.csdn.net/luoweifu/article/details/8214959  该blog给出的是java代码,我用c++将其实现了. 理论: 图像处理中常用的正交变换除了傅里叶变换外,还有其他一些有用的正交变换,其中离散余弦就是一种.离散余弦变换表示为DCT( Discrete Cosine Transformation),常用于图像处理和图像识别等. 一维离散余弦变换 正变换                            

C++实现离散余弦变换(参数为二维指针)

http://www.cnblogs.com/scut-linmaojiang/p/5013590.html 写在前面 到目前为止已经阅读了相当一部分的网格水印等方面的论文了,但是论文的实现进度还没有更上,这个月准备挑选一些较为经典的论文,将其中的算法实现.在实现论文的过程中,发现论文中有用到一些空域转频率域的算法.因此也就想到了实现一下离散余弦变换.虽然本文的代码和网上很多已有的代码很类似,思路都没有太多的差别,但是本文有一个比较重要的改进.具体的说,网上现有DCT算法输入的是一个固定的二维数

压缩原理及无线的一点思考

黑白图像每个像素8bit,彩色24bit(任何颜色都可以由红绿蓝三色组成).JPEG压缩技术,把像素以8*8为单位,以某个基准(如傅里叶基)对像素值(矩阵的系数或向量)进行变换,把大部分的像素值变为0,完成图像的压缩.结果可以理解为,值为0的像素不会在链路上传输,到了解码端再在相应的位置将值为0的像素恢复,节约了带宽,广域网加速器大概也是这个道理. IEEE802.11b或其他标准,都有个频宽,比如2.4-2.483GHz或5.15-5.825GHz.在这个频宽的基础上,划分了十几或更多的信道,

离散余弦变换定义

在处理复数域信号时,离散傅立叶变换能够把它转换至频域,然而在实际中,大部分的信号都是处理实域信号,这样在离散傅立叶变换之后,由于其对称性,导致一半的冗余数据.在时域,信号的虚部为全0.在频域,其实部和虚部分别具有偶对称以及奇对称性.相比而言,离散余弦变换是针对时域信号的处理方法,它能够避免数据的冗余.另外,由于离散余弦变换是从离散傅立叶变换继承而来,它保留了一些离散傅立叶变换的优点. 为了对一个N点的时域信号 进行离散余弦变换操作,首先需要对其进行扩展,扩展至2N个点,使其在时域周期性,如下:

ios mac 对照片进行JPEG压缩

1. 在iOS上可以使用 API UIImageJPEGRepresentation 对照片数据进行JPEG压缩: 我们知道iOS其实是MAC OS 的移植,那么MAC上肯定也有相应的JPEG压缩方法: 在mac上了,找了NSImage的API没有发现直接的JPEG压缩方法: 但是有NSBitmapImageRep,下面来测试一下,iOS和MAC上的JPEG压缩是否一致: 2. 首先用iOS 来压缩一张照片 UIImage *timg = [UIImage imageWithContentsOf