JPEG压缩算法讲解

0 阅读4分钟

原理讲述

人眼的结构

人眼里有两种感光细胞:视杆细胞(Rod Cell,用于感知亮度) & 视锥细胞(Cone Cell,用于感知颜色和色度)

而Rods的数量要远远多于Cones,于是人眼对图像的明暗程度(亮度)的感知程度要强得多(相对的,对色度的感知要弱得多)

1.色彩空间转换 Color Space Conversion

每个像素由三个颜色 Red,Green,Blue 组成,每个值为 0~255

根据这三个值根据不同的权重分别算出三个新的值:亮度、蓝色色度、红色色度,缩写为 Y, Cb, Cr

这个过程是可逆的,并且转换过程中没有删除任何数据

2.色彩缩减取样 Chrominance Downsampling

这一步会将色度分量层上的像素按照 2×2像素求均值然后缩小图像,将4个像素组成的区块缩小为只占一个像素的空间

这样人眼不宜感知的红蓝色度信息的量缩减为原来的四分之一,而亮度保持不变,这样图像的大小已经变为原来的一半了

  • Before: 1 + 1 + 1 = 3.0
  • After: 1/4 + 1/4 + 1 = 1.5

要注意在进行完这一步之后,红蓝色度的图像会放大到原来尺寸,然后重新进行RGB的计算(逆运算)

3.离散余弦变换 Discrete Cosine Transform

以亮度图层为例(Cr, Cb也会经历同样的过程),8×8像素作为一个区块,每个像素用0255表示其亮度,减去128改变各个亮度数值,取值范围变成了 -128127

接下来这一步非常重要,我们需要一组同样8×8的基础图象,来组合重建这个64像素区块

这一步相当于我们用64个基础积木来拼成这个区块中的所有像素,就像拼乐高那样!

当然这一步还并没有做到对图像的压缩过程,但是下一步 Quantization 可以!

4.量化 Quantization

人眼不擅长感知图像中的高频率元素

通过 DCT,我们得到了一个对应各个基础图形的使用数字表,然后我们自己构建一个量化表(Quantization Table),将两个表进行相处,并将每个结果四舍五入为最接近的整数,得到一个新表

这个量化表右下角的数值较高(对应的就是基础图形表中右下角的高频数据)

而数值较小的左上角是人眼更以区分的样式所在

得到这个新表之后我们发现只有几个数字和大量的0

这样我们就扔掉了人眼无法感知的高频数据

针对色度,使用了另一个数值更大的量化表格,因此结果表中的0甚至更多

5. 游程编码 & 哈夫曼编码 Run Length and Huffman Encoding

在这一步通过游程编码,将通过Quantization之后的新表编码,这样我们发现游程编码之后的结果比编码所有的0~255的数字实现了明显的压缩

最后进行哈夫曼编码,完成了图像的压缩

6.图像重构

这一步实际上是前面所有步骤的逆过程

  1. 解游程编码,哈夫曼解码,将得到的值放入 8×8 的区块中
  2. 将各个值乘以量化表,将所得常数乘以相应的基础图象,将所有结果图像叠加在一起
  3. 将蓝色红色色度图像放大,将亮度和色度值重新转换为 RGB 色彩空间

关于图像质量

我们可以调整压缩的图像质量 q,如果我们减小压缩质量(提高压缩程度),对应的是量化表的数值增大,也就让结果的新表出现更多的0

JPEG的缺陷及其他

压缩质量的影响

如果压缩质量过小,压缩程度过高,会出现膺点,看起来就像方块边缘的模糊斑点

压缩之后的缺陷

同时JPEG算法会降低图像的精细程度,并且对于高频数据的精度影响会比对低频数据更大

应用场景

JPEG算法对于压缩相机图片表现非常出色,因为自然景色会有很多的精细边缘,而没有一个相机是可以做到完美对焦的,所以很难分辨压缩前后图像的区别

但是对于矢量图形,就会得到相当明显的膺像了