Java教程

影像算法解析——JPEG 压缩算法

本文主要是介绍影像算法解析——JPEG 压缩算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

影像算法解析——JPEG 压缩算法

如云般飘过

如云般飘过

调色师 / 剪辑师 / Mac重度用户/ 摄影爱好者

309 人赞同了该文章

由于视频是由一帧帧图像构成的,研究视频编码首先先要研究图像编码。这篇文章就详细说一下 JPEG 是如何压缩一个图像的。

先简单介绍一下 JPEG(Joint Photographic Experts Group,联合图像专家小组):此团队创立于1986年,其于1992年发布的 JPEG 标准在1994年获得了 ISO 10918-1 的认定,成为了图片压缩标准。

JPEG 压缩为有损压缩,下面介绍一下它的压缩算法。

1 RGB 到 YUV 进行4:2:0色度抽样

首先 JPEG 文件是由 YUV 的色彩空间来表示颜色的,YUV 中 Y 表示明亮度(Luma),U 和 V 表示色度(Chrominance)和浓度(Chroma),UV 分量同时表示色差。

因为人眼对亮度的差异敏感度高于对色彩的变化。考虑到这种感知能力,允许降低色度以及浓度的带宽。YUV 的色彩空间更容易压缩 U、V 分量。

1.1 RGB 到 YUV 的转换 - 无损

RGB 转化 YUV 的公式(经过 PAL制式 CRT伽玛校正)如下:

Y = 0.299R’ + 0.587G’ + 0.114B'

U = -0.147R’ - 0.289G’ + 0.436B'

V = 0.615R’ - 0.515G’ - 0.100B'

未经伽玛校正(计算机色彩空间)的矩阵表示:

 

1.2 色度抽样-有损

在 YUV 采样的时候可以对 U、V 分量进行色度采样,在 JPEG 压缩算法采用的是 YUV 4:2:0 的色度抽样方法。

4:2:0 并非无 V 分量,它对于每行扫描的像素来说,只有一中色度分量以 2:1 的抽样率储存,相邻行储存不同的色度分量。可以理解为奇数行采样 U,YUV 4:2:0;偶数行采样 V,YUV 4:0:2。

YUV 4:2:0 的码流为:

Yo0 Uo0 Yo1 Yo2 Uo2 Yo3
Ye0 Ve0 Ye1 Ye2 Ve2 Ye3

映射成的四个像素为:

[Yo0 Uo0 Ve0] [Yo1 Uo0 Ve0] [Yo2 Uo2 Ve2] [Yo3 Uo2 Ve2]
[Ye0 Uo0 Ve0] [Ye1 Uo0 Ve0] [Ye2 Uo2 Ve2] [Ye3 Uo2 Ve2]

YUV 4:2:0 的色度抽样率为 4:1,至此经历第一次压缩。

2 离散余弦变化(DCT)- 无损

做好色彩空间转换和 YUV 4:2:0 色彩抽样后,将输入的图片分割成 8*8 像素的单元格。对每个单元格进行离散余弦变化。

以下面的图片作为例子,下图为 8*8 的只有 Y 分量的图形,其中亮度值为矩阵中的值:

数据来自 Wikipedia [1]

由于 DCT 变化需要定义域对称,在做 DCT 变化之前要先将矩阵中的数值左移 128,使得值域落在 -128~127:

 

到此,DCT 变化的准备工作已经完成。在进行 DCT 变化之前,先说一下 DCT 的原理

信号学中,如果一个信号长度为8字节,则可以用8个不同频率的余弦波去表示它,形成频域编码。在图像中也是如此。

在 JPEG 算法中,图像被分为了 8*8 的像素组,每个像素组用自己的离散余弦变化进行频域编码。

顺带说一句,为什么选用 8*8 的像素组。采用比 8*8 更大的像素组,会大幅增加 DCT 的运算量,且编码质量也不会明显提升;采用比 8*8 更小的像素组会导致分组增多降低精度。所以8*8 的像素组是效率最优的结果。

这些像素组可以被 8*8 个余弦波精确表示,如下图所示有64个基本余弦波:

余弦波

这64个余弦波,可以组合成任意 8*8 的图形。我们只要用系数(系数表示每个单独的余弦波对整体图像所做的贡献)对这64个余弦波进行加权,就可以表示出任何的图形。

这个过程就是离线余弦变化,JPEG 中使用的是 DCT II 的公式。

根据 DTC II 的公式:

 

可以得出该图像在频域上的系数(经过取整,取值范围 -1024~1023):

经过 DCT 转换后的频率系数矩阵分别对应64个余弦波在 8*8 图形中的权重。可以看出,左上部分低频区的系数比较大,右下高频区的系数较小。鉴于人眼对高频区的识别不敏感,所以在下面量化部分可以舍弃一些高频区的数据。这里的 DCT 变化还没开始压缩。

  • 注1:左上角第一个数为直流系数,代表特定像素组的一般强度,其余为交流系数。
  • 注2:此处的系数矩阵与亮度矩阵无对应关系。

3 量化 - 有损

在 DCT 变化后,舍弃高频区数据的过程称为量化。有两份量化表可供选择,分别为亮度量化表和色度量化表:

 

上表分别为亮度量化表和色彩量化表,表示 50% 的图像质量。这两张表中的数据基于人眼对不同频率的敏感程度制定。

量化表是控制 JPEG 压缩比的关键,可以根据输出图片的质量来自定义量化表,通常自定义量化表与标准量化表呈比例关系,表中数字越大则质量越低,压缩率越高。PhotoShop 有12张量化表。

量化过程为,使用量化矩阵与前面得到的 DCT 矩阵逐项相除并取整。之前为亮度矩阵,顾使用亮度量化表:

量化是有损的,在解码时,反量化会乘回量化表的相应值。由于存在取整,低频段会有所损失,高频段的0字段则会被舍弃,最终导致图像质量降低。

4 熵编码(zigzag scan & 霍夫曼编码)- 无损

得到量化后的矩阵就要开始编码过程了,首先要把二维矩阵变为一维数组,这里采用了 zigzag 排列,将相似频率组在一起:

zigzag [2]

得出的序列为:

霍夫曼编码中,在 JPEG 有个 EOB(End OBlock) 字段,表示从字段开始后面全为0,然后再根据霍夫曼编码再进行压缩。

至此,这个亮度 8*8 的像素组压缩编码完毕。

将图像每个 8*8 像素组进行编码就可以压缩整个图像了。


关于 JPEG 编码的内容就写到这里,如有错误或遗漏,欢迎在评论区指正。

以后也会在这个新分类下写一些其他视频编码,如果大家有其他内容想了解,也可以写在评论里。

没有微信公众号,只在专栏里写些东西,顺便自己也可以学习,欢迎关注。


参考资料:

[1] JPEG-Wikipedia

[2] JPEG 标准 | itu-t81.pdf

编辑于 2018-07-27 19:13

这篇关于影像算法解析——JPEG 压缩算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!