原理讲述
人眼的结构
人眼里有两种感光细胞:视杆细胞(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.图像重构
这一步实际上是前面所有步骤的逆过程
- 解游程编码,哈夫曼解码,将得到的值放入 8×8 的区块中
- 将各个值乘以量化表,将所得常数乘以相应的基础图象,将所有结果图像叠加在一起
- 将蓝色红色色度图像放大,将亮度和色度值重新转换为 RGB 色彩空间
关于图像质量
我们可以调整压缩的图像质量 q,如果我们减小压缩质量(提高压缩程度),对应的是量化表的数值增大,也就让结果的新表出现更多的0
JPEG的缺陷及其他
压缩质量的影响
如果压缩质量过小,压缩程度过高,会出现膺点,看起来就像方块边缘的模糊斑点
压缩之后的缺陷
同时JPEG算法会降低图像的精细程度,并且对于高频数据的精度影响会比对低频数据更大
应用场景
JPEG算法对于压缩相机图片表现非常出色,因为自然景色会有很多的精细边缘,而没有一个相机是可以做到完美对焦的,所以很难分辨压缩前后图像的区别
但是对于矢量图形,就会得到相当明显的膺像了