理解JEPG原理
JEPG不是一种文件格式,而是一类图像压缩算法.
1.彩色图像
灰度图像
灰度,一个pixel取值0-255.

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

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=(b′−y)/1.772
Cr=(r′−y)/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)




2.JPEG算法
JPEG不是一种文件格式,而是一类图像压缩算法, 下面我介绍的是JPEG2000,最基础的算法,可以帮助理解整个过程.
首先说一下怎么理解图像压缩, 以huffman编码为例, 对图像每个byte做频率统计, 构造huffman树重新编码, 以减小编码长度. 但是, 直接对图像做huffman编码的压缩并不好, 因为需要对256个像素值都编码, 码长不会显著减小.
如果能将图像变换到一个含有比较少的不同值的空间中, huffman编码效果将会显著提升. 这就是jpeg的核心思想.
2.1 预处理
先将RGB转成YCbCr, 然后把这三层当作灰度图像看就行, 操作是一样的.
然后, 将图像切割成一堆8×8的块.

所有操作都是独立对这样每一个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⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢2√2cosπ16cos2π16cos3π16cos4π16cos5π16cos6π16cos7π162√2cos3π16cos6π16cos9π16cos12π16cos15π16cos18π16cos21π162√2cos5π16cos10π16cos15π16cos20π16cos25π16cos30π16cos35π162√2cos7π16cos14π16cos21π16cos28π16cos35π16cos42π16cos49π162√2cos9π16cos18π16cos27π16cos36π16cos45π16cos54π16cos63π162√2cos11π16cos22π16cos33π16cos44π16cos55π16cos66π16cos77π162√2cos13π16cos26π16cos39π16cos52π16cos65π16cos78π16cos91π162√2cos15π16cos30π16cos45π16cos60π16cos75π16cos90π16cos105π16⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
DCT每一行图示
row0是常数, 可以看出每行频率逐渐增加.







仔细看上图, 可以发现每个图橙色的点高度和为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=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢51515051515051505252505050515251515151505052515250515250515250525050525250515250525251505050505150525150515052525251515150505051⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
经过DCT变换(保留小数点后三位), 也可以发现除了左上角407,其他的值都接近0.
B=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢4070.3521.904−0.661−1.−0.2290.023−0.1100.058−0.654−0.1161.350−0.3350.162−0.173−0.383−0.5181.0191.0.6891.1710.115−1.7070.105−0.5920.818−0.598−0.0550.1020.711−1.5290.470−0.50.179−2.174−0.4250.50.9560.6300.0050.118−1.074−0.352−0.599−0.020−1.9020.1090.568−0.5971.1900.2930.2540.868−0.1081.−0.4700.086−1.194−1.006−0.412−0.5021.454−0.6030.111⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
DCT特点
- DCT 矩阵 U是可逆的, 同时 U是正交的, 有UT=U−1.证明
- DCT计算B=UAUT, 这是个相似变换. 可以通过FFT(Fast Fourier Transformation)加速.
2.3 Quantization量化
上一节看到, DCT矩阵是无理数组成的, 而输入矩阵是整数, 输出矩阵一般为实数. 而接下来的编码最好是作用在整数域. 所以JPEG有一步量化.
下面走一下JPEG流程来说明量化的工作机制. 给出一个经过预处理(-127)的block.
A=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢−122−121−122−94−119−64−76−7849494052−23−122−80−746631454253−25−64−8441451054751−26−122−122413531−122453353574350−66−1227015644340411886163841382487514212−122−53⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
经过DCT变换(保留小数点后两位).
B=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢−27.50168.23−27.2030.1819.50−70.5912.0871.15−213.4751.61−31.24−43.078.4666.88−19.13−38.37−149.61−21.54−32.28−50.4733.5947.446.25−75.92−95.28−239.52173.3967.13−53.11−32.61−55.1629.29−103.75−8.24−51.14−14.12−36.75−8.2085.59−16.45−46.95−24.50−56.9411.142.9218.13−0.60−23.44−58.72−52.664.0071.01−5.80−22.998.03−4.2127.23−96.6249.1418.04−18.396.6311.2115.62⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
为了量化block
B, JPEG用一个预设的表
Z去除
B(element-wise division)然后取整.
这个矩阵Z也体现了JPEG压缩的特点, 左上角的信息压缩的程度小, 右下角的信息压缩的程度大.通过缩放矩阵Z,达到控制压缩程度.
Z=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢1612141418244972111213172235649210141622375578951619242956648798242640516881103112405857871091041211005160698010311312010361555662779210199⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
得到一个新矩阵
Q, 其中
qjk=round(bjk/zjk) for
j,k=1,...,8.
Q=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢−214−221−301−194−2−30200−15−2−2−2110−1−6−1372−1−1−10−40−10−1010−10−100000−1−10100000−2100000⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
因为有取整的操作, JPEG是有损的压缩
逆转过程
要逆转过程, 重新得到原来的blockA,只需先反转除法, 得到B′, 其中b′jk=qjk×zjk. 注意到B′和B的值是有一点不同的(lossy).
B′=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢−32168−282818−72072−20948−26−5107000−150−28−32−4437550−95−96−24716858−56−64−870−960−400−6801030−400−5700000−51−6008000000−1105600000⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
然后作用inverse DCT,
A′=UTB′U.下面对比一下原图像
A和恢复的
A′,可以看出JPEG有损的特点了.
A′=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢−128−110−115−105−116−67−67−7845394051−24−118−79−69714504356−47−60−8063481521863−24−116−138224113−126333049633268−88−99801769412265−41962−121249521376602829−108−67⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
A=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢−122−121−122−94−119−64−76−7849494052−23−122−80−746631454253−25−64−8441451054751−26−122−122413531−122453353574350−66−1227015644340411886163841382487514212−122−53⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥
2.4 编码
JPEG最后一步是对变换,量化后的图像进行编码. 用huffman编码或者其他编码方式, 可以显著节省存储空间.
3. 参考
- Basic JEPG
- The Discrete Cosine Transformation
- Quantization
- comupterphile jpeg系列