域名不卖,勿扰!

JPEG图像压缩原理

JPEG 是 Joint Photographic Experts Group 的缩写,即 ISO 和 IEC 联合图像专家组,负责静态图像压缩标准的制定,这个专家组开发的算法就被称为 JPEG 算法。使用这个算法压缩的图片就叫做.JPEG/.JPG。

一、JPEG核心原理

JPEG核心原理是利用了人眼对色彩不敏感,且对高频信息不敏感的特性。舍弃了人眼不易察觉到的部分。因此JPEG是有损压缩。

人眼中有两种感光细胞,视杆细胞Rods和视锥细胞Cones。视杆细胞对明暗变化敏感,对颜色不敏感;视锥细胞对颜色敏感。每只眼睛有1亿个视杆细胞,而视锥细胞只有600万个。因此,人眼对图像的明暗程度的感知能力要强的多。视锥细胞还另外分为绿红蓝三种,比例为40:20:1。因此人眼对蓝光极不敏感。这也导致我们不易察觉蓝光对人眼的伤害。

二、JPEG原理详细分析

具体步骤:

  1. DCT (Discrete Cosine Transform 离散余弦变换)
  2. Quantization(量化)
  3. Run Length and Huffman coding(游程编码和霍夫曼编码)

1、颜色空间转换。RGB->YCbCr

        根据三基色原理,人们发现红绿蓝三种颜色所贡献的亮度是不同的,绿色的“亮度”最大,蓝色最暗,设红色所贡献的亮度的份额为KR,蓝色贡献的份额为KB,那么亮度为

        根据经验,未经伽玛校正(计算机色彩空间)的矩阵,KR=0.299,KB=0.114,那么

        蓝色和红色的色差的定义如下

        最终可以得到RGB转换为YCbCr的数学公式为

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

2、色彩下采样。按照4:2:0色度抽样

在 YUV 采样的时候可以对 U、V 分量进行色度采样,在 JPEG 压缩算法采用的是 YUV 4:2:0 的色度抽样方法。Y分量不压缩,UV分量分别压缩到原来的1/4。整张图就变为原来的1/2大小了

YCbCr 4:2:0 subsampling
For the top row, the CbCr signals of only two pixels are recorded. No CbCr signals are recorded from the pixels in the second row.

3、离散余弦变换。DCT(Discrete Cosine Transform)

DCT是针对分量单独去做的,也就是说对于YCbCr的图片,我们先要对Y做一次DCT,然后再对Cb做一次DCT,最后对Cr做一次DCT。

以Y分量为例:
将Y分量的像素点按照8×8的矩阵进行分割每个8×8是一个MCU(最小编码单元),

8×8的原始图像:

推移128后,使其范围变为 -128~127:

使用离散余弦变换,并四舍五入取最接近的整数:

DCT从频率域来解释更容易理解。将这64个像素点按照Y值展开成一条函数曲线F(y),通过DCT,将其离散为64个不同频率的cosine函数。变换后的矩阵不再是亮度矩阵,而是64个基础余弦波的系数矩阵,即64个基础图像的系数矩阵。

4、量化:

量化过程实际上就是对 DCT 系数的一个优化过程。它是利用了人眼对高频部分不敏感的特性来实现数据的大幅简化。量化过程是有损运算,量化是图像质量下降的最主要原因。

量化过程实际上是简单地把频率领域上每个成份,除以一个对于该成份的常数,且接着四舍五入取最接近的整数。

因为人眼对亮度信号比对色差信号更敏感,因此使用了两种量化表:亮度量化值和色差量化值。

使用亮度量化矩阵对前面得到的 DCT 系数矩阵进行量化:

如,使用−415(DC系数)且四舍五入得到最接近的整数

最终,整张表量化后的结果如下:

总体上来说,DCT 变换实际是空间域的低通滤波器。对 Y 分量采用细量化,对 UV 采用粗量化。

量化表是控制 JPEG 压缩比的关键,这个步骤除掉了一些高频量;另一个重要原因是所有图片的点与点之间会有一个色彩过渡的过程,大量的图像信息被包含在低频率中,经过量化处理后,在高频率段,将出现大量连续的零。

5、“Z”字形编排

量化后的数据,有一个很大的特点,就是直流分量相对于交流分量来说要大,而且交流分量中含有大量的0。这样,对这个量化后的数据如何来进行简化,从而再更大程度地进行压缩呢。

这就出现了“Z”字形编排,如图:

对于前面量化的系数所作的 “Z”字形编排结果就是:

底部 −26,−3,0,−3,−3,−6,2,−4,1 −4,1,1,5,1,2,−1,1,−1,2,0,0,0,0,0,−1,−1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 顶部

这样做的特点就是会连续出现多个0,这样很有利于使用简单而直观的行程编码(RLE:Run Length Coding)对它们进行编码。

8×8图像块经过 DCT 变换之后得到的 DC 直流系数有两个特点,一是系数的数值比较大,二是相邻8×8图像块的 DC 系数值变化不大。根据这个特点,JPEG 算法使用了差分脉冲调制编码(DPCM)技术,对相邻图像块之间量化 DC 系数的差值(Delta)进行编码。即充分利用相邻两图像块的特性,来再次简化数据。

即上面的 DC 分量-26,需要单独处理。而对于其他63个元素采用zig-zag(“Z”字形)行程编码,以增加行程中连续0的个数。

6、行程编码

Run Length Coding,行程编码又称“运行长度编码”或“游程编码”,它是一种无损压缩编码。

例如:5555557777733322221111111

这个数据的一个特点是相同的内容会重复出现很多次,那么就可以用一种简化的方法来记录这一串数字,如

(5,6)(7,5)(3,3)(2,4)(l,7)

即为它的行程编码。

行程编码的位数会远远少于原始字符串的位数。

对经过“Z”字形编排过的数据,即可以用行程编码来对其进行大幅度的数据压缩。

我们来用一个简单的例子来详细说明一下:

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
霍夫曼编码中,在 JPEG 有个 EOB(End Of Block) 字段,表示从字段开始后面全为0,然后再根据霍夫曼编码再进行压缩。

即每组数字的头一个表示0的个数,而且为了能更有利于后续的处理,必须是 4 bit,就是说,只能是 0~15,这是的这个行程编码的一个特点。

7、范式 Huffman 编码

直流 DC 系数经过上面的 DPCM 编码,交流 AC 系数经过 RLE 编码后,得到的数据,还可以再进一补压缩。

对zigzag扫描后的RLE进行熵编码,比较典型的是采用huffman编码huffman编码是一种变长编码,也就是高概率出现的码字使用短编码,低概率出现的码字使用长编码。

如果是双平面色彩格式(Y和CrCb)(需要看资料确认是否和平面有关),一般JFIF的Huffman table有4张

Y的DC表

Y的AC表

CrCb的DC表

CrCb的AC表

我们需要使用对应的Huffman table来对RLE进行编码。

对于8*8 block(MCU)来说,最左上角的是DC因子,其余63个都是AC因子,因此在RLE中,第一个元素必然是DC因子,如果这个RLE保存的是Y数据,那么就要用Huffman table(Y DC)来编码,下面讲述一下编码过程

在谈Huffman编码前先要引入一个Catagory Value Table(CVT)

对上面的例子中 RLC 后的结果,对它的存储,JPEG 里并不直接保存这个数值,这样主要是为了提高效率。

还是以(0,57)这个pair为例,需要先将57放到CVT里面,这样就得到57对应的Catagory(组)和bits of value(实际保存值)

57 为第 6 组的,实际保存值为 111001,编码为 (6,111001)。

备注:catagory=6, bits=111001,6表示bits有6位,而bits=111001则是二进制的57。

同理,

57 -> (6, 111001)   
45 -> (6,101101) 
23  ->  (5,10111) 
-30  ->  (5,00001) 
-8  ->  (4,0111) 
1  ->  (1,1)

这个时候前面的例子就变为如下格式:

(0,6),111001 ; (0,6),101101 ; (4,5),10111; (1,5),00001; (0,4) ,0111 ; (2,1),1 ; (0,0)

这样,括号里的数值正好再合成一个字节,高4位是前面0的个数,低4位描述了后面数字的位数;后面被编码的数字表示范围是 -32767..32767。

还是以(0,6),111001 为例,(0,6)中的0放在高4bit,6放在低4bit,组合起来就是一个8bit的 0000 0110 -> 6,然后在Huffman Table找到 码字6 对应的 二进制编码(huffman code),假如这里 6 -> 111000,则 (0,6),111001 最终的编码是 111000 111001

同理,

6 = (0,6) — 111000
6 = (0,6) — 111000
69 = (4,5) (for example) we have 1111111110011001
21 = (1,5) — 11111110110
4 = (0,4) — 1011
33 = (2,1) — 11011
0 = EOB = (0,0) — 1010

所以最终的编码是:

111000 111001  111000 101101  1111111110011001 10111   11111110110  00001  1011 0111   11011 1   1010


参考链接:
https://blog.csdn.net/han2529386161/article/details/109777211
https://zhuanlan.zhihu.com/p/600252083

版权共享,随意转载:云破天开 » JPEG图像压缩原理

评论

6+6=