理解JPEG图像压缩算法,DCT变换

理解JEPG原理

JEPG不是一种文件格式,而是一类图像压缩算法.

1.彩色图像

灰度图像

灰度,一个pixel取值0-255.
理解JPEG图像压缩算法,DCT变换

彩色图像

需要比灰度图像更多的存储空间, 事实上, 所有颜色都可以用红绿蓝三原色的组合表示, 彩色图像可用RGB三通道表示.

理解JPEG图像压缩算法,DCT变换

YCbCr

研究发现对于图像压缩, RGB的表示不是最佳的.

人脑对亮度(luminance)和色差(chrominance)的微小变化不敏感. YCbCr用一层亮度和两层色差表示RGB图像. Y是亮度通道, Cb和Cr是色差通道.

RGB转YCbCr是这样定义的,对一个(r,g,b)元组, 先归一化(r,g,b)=(r/255,g/255,b/255).

通过一下公式得到亮度值 y:

y=0.299r+0.587g+0.114b

色差通道通过计算red和blue两颜色通道和参照通道y的差得到:
Cb=(by)/1.772

Cr=(ry)/1.402

1.772和1.402做分母使Cb和Cr都落在区间[1/2,1/2].
最后一步, 为了显示将三通道缩放到[0,255],并取整:
Y=round(219y+16)

Cb=round(224Cb+128)

Cr=round(224Cr+128)

理解JPEG图像压缩算法,DCT变换

理解JPEG图像压缩算法,DCT变换

理解JPEG图像压缩算法,DCT变换

理解JPEG图像压缩算法,DCT变换

2.JPEG算法

JPEG不是一种文件格式,而是一类图像压缩算法, 下面我介绍的是JPEG2000,最基础的算法,可以帮助理解整个过程.

首先说一下怎么理解图像压缩, 以huffman编码为例, 对图像每个byte做频率统计, 构造huffman树重新编码, 以减小编码长度. 但是, 直接对图像做huffman编码的压缩并不好, 因为需要对256个像素值都编码, 码长不会显著减小.

如果能将图像变换到一个含有比较少的不同值的空间中, huffman编码效果将会显著提升. 这就是jpeg的核心思想.

2.1 预处理

先将RGB转成YCbCr, 然后把这三层当作灰度图像看就行, 操作是一样的.

然后, 将图像切割成一堆8×8的块.

理解JPEG图像压缩算法,DCT变换
所有操作都是独立对这样每一个8×8的小块做的.

2.2 DCT变换

考虑一个8×8的块, 这个块在原图像中所占的比例是非常小的, 在大部分情况下, 这个块中pixel数值变化是很平滑的. 打个比方,一个块正好罩在一面墙壁上, 这块的pixel值在79-81之间变化, 若要用cos函数的组合去拟合这段离散的数值, 这些函数的频率会很高.

这些变化也被称为高频信息, 而人眼对高频信息不敏感, 对低频信息比较敏感. 如果一个块罩在墙和背景交界的地方, 块的pixel数值会出现不平滑的变化,跨度很大, 这时要用函数组合去拟合这段离散数值时, 就会出现低频.

因此, 再结合图像压缩的核心思想, 用较少的不同数值来表示图像, 就需要找到一种变换, 将图像高频的信息和低频的信息区分开来, 并将人眼不敏感的低频信息映射到接近或等于0.

JPEG用的就是DCT(Discrete Cosine Transformation), 下面就是DCT矩阵, 任何8×8块都可以用DCT矩阵表示.

U=12[2222222222222222cosπ16cos3π16cos5π16cos7π16cos9π16cos11π16cos13π16cos15π16cos2π16cos6π16cos10π16cos14π16cos18π16cos22π16cos26π16cos30π16cos3π16cos9π16cos15π16cos21π16cos27π16cos33π16cos39π16cos45π16cos4π16cos12π16cos20π16cos28π16cos36π16cos44π16cos52π16cos60π16cos5π16cos15π16cos25π16cos35π16cos45π16cos55π16cos65π16cos75π16cos6π16cos18π16cos30π16cos42π16cos54π16cos66π16cos78π16cos90π16cos7π16cos21π16cos35π16cos49π16cos63π16cos77π16cos91π16cos105π16]

DCT每一行图示

row0是常数, 可以看出每行频率逐渐增加.

理解JPEG图像压缩算法,DCT变换
理解JPEG图像压缩算法,DCT变换
理解JPEG图像压缩算法,DCT变换
理解JPEG图像压缩算法,DCT变换
理解JPEG图像压缩算法,DCT变换
理解JPEG图像压缩算法,DCT变换
理解JPEG图像压缩算法,DCT变换
仔细看上图, 可以发现每个图橙色的点高度和为0. 这意味着, 对于一个constant vector(向量中每个数相同), 和row 1-7任意一个点乘的结果都是0, 而对近似constant vector点乘的结果接近0.(这就达到了将高频信息转换到接近0的效果)

DCT变换作用在8×8矩阵A上表现为B=UAUT. 首先计算 C=UA, 若A是一个平滑的矩阵(near-constant), C往下会出现许多元素接近或等于0. 最终结果B=CUT, 将U转制之后, 原来的row变成了column, 类似的, B往右会出现许多元素接近或等于0. 总的来看, DCT会将信息往左上角聚拢, 而剩下的信息都是接近或等于0的.

示例

下面是一个8×8矩阵A只包含值100.

A=[100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100]

DCT得到B=UAUT.

B=[800000000000000000000000000000000000000000000000000000000000000000]

可以看到整个块的信息除了(1,1)位置都被变换为0. 再看另一个例子, 下面的矩阵A只包含值50-52(near-constant), 对于图像来说,是平滑的一块, 包含的是高频信息.

A=[51525150505250525152515150525251505051525251515151505050525050515150505150505150505152525150505051525150525052505051525250515251]

经过DCT变换(保留小数点后三位), 也可以发现除了左上角407,其他的值都接近0.

B=[4070.0580.5180.5920.50.1180.5970.0860.3520.6541.0190.8180.1791.0741.1901.1941.9040.1161.0.5982.1740.3520.2931.0060.6611.3500.6890.0550.4250.5990.2540.4121.0.3351.1710.1020.50.0200.8680.5020.2290.1620.1150.7110.9561.9020.1081.4540.0230.1731.7071.5290.6300.1091.0.6030.1100.3830.1050.4700.0050.5680.4700.111]

DCT特点

  1. DCT 矩阵 U是可逆的, 同时 U是正交的, 有UT=U1.证明
  2. DCT计算B=UAUT, 这是个相似变换. 可以通过FFT(Fast Fourier Transformation)加速.

2.3 Quantization量化

上一节看到, DCT矩阵是无理数组成的, 而输入矩阵是整数, 输出矩阵一般为实数. 而接下来的编码最好是作用在整数域. 所以JPEG有一步量化.

下面走一下JPEG流程来说明量化的工作机制. 给出一个经过预处理(-127)的block.

A=[12249664141434038121493145355041241224045105316618879452424712212285111923535145706142641222526331561276806412253643812278748412257434153]

经过DCT变换(保留小数点后两位).

B=[27.50213.47149.6195.28103.7546.9558.7227.23168.2351.6121.54239.528.2424.5052.6696.6227.2031.2432.28173.3951.1456.944.0049.1430.1843.0750.4767.1314.1211.1471.0118.0419.508.4633.5953.1136.752.925.8018.3970.5966.8847.4432.618.2018.1322.996.6312.0819.136.2555.1685.590.608.0311.2171.1538.3775.9229.2916.4523.444.2115.62]

为了量化blockB, JPEG用一个预设的表Z去除B(element-wise division)然后取整.

这个矩阵Z也体现了JPEG压缩的特点, 左上角的信息压缩的程度小, 右下角的信息压缩的程度大.通过缩放矩阵Z,达到控制压缩程度.

Z=[1611101624405161121214192658605514131624405769561417222951878062182237566810910377243555648110411392496478871031211201017292959811210010399]

得到一个新矩阵Q, 其中qjk=round(bjk/zjk) for j,k=1,...,8.
Q=[21915641101442130012222711012322001010111000321100000001100010100000]

因为有取整的操作, JPEG是有损的压缩

逆转过程

要逆转过程, 重新得到原来的blockA,只需先反转除法, 得到B, 其中bjk=qjk×zjk. 注意到BB的值是有一点不同的(lossy).

B=[322091509696405101684828247006011028263216840570562851445800800180375668000727055640000000871030007209500000]

然后作用inverse DCT, A=UTBU.下面对比一下原图像A和恢复的A,可以看出JPEG有损的特点了.
A=[12845716322322252110394484168651311540501521388476105514318126991960116245663338062286711847243017122967796011649691210878698013863414967]

A=[12249664141434038121493145355041241224045105316618879452424712212285111923535145706142641222526331561276806412253643812278748412257434153]

2.4 编码

JPEG最后一步是对变换,量化后的图像进行编码. 用huffman编码或者其他编码方式, 可以显著节省存储空间.

3. 参考

  1. Basic JEPG
  2. The Discrete Cosine Transformation
  3. Quantization
  4. comupterphile jpeg系列