更新博客内容
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
---
|
||||
title: "JPEG算法解密(二)"
|
||||
tags: 压缩 图像 程序 算法
|
||||
---
|
||||
# JPEG算法解密(二)
|
||||
|
||||
### 步骤三:离散余弦变换
|
||||
----
|
||||
这次我们来介绍JPEG算法中的核心内容,离散余弦变换(Discrete cosine transform),简称DCT。
|
||||
离散余弦变换属于傅里叶变换的另外一种形式,没错,就是大名鼎鼎的傅里叶变换。傅里叶是法国著名的数学家和物理学家,1807年,39岁的傅里叶在他的一篇论文里提出了一个想法,他认为*任何周期性的函数,都可以分解为为一系列的三角函数的组合*,这个想法一开始并没有得到当时科学界的承认,比如当时著名的数学家拉格朗日提出质疑,三角函数无论如何组合,都无法表达带有“尖角”的函数,一直到1822年拉格朗日死后,傅里叶的想法才正式在他的著作《热的解析理论》一书中正式发表。
|
||||
|
||||

|
||||
|
||||
金子总会闪光,傅里叶变换如今广泛应用于数学、物理、信号处理等等领域,变换除了它在数学上的意义外,还有其哲学上的伟大意义,那就是,世上任何复杂的事物,都可以分解为简单的事物的组合,而这个过程只需要借助数学工具就可以了。但是当年拉格朗日的质疑是正确的,三角函数的确无法表达出尖角形状的函数,不过只要三角函数足够多,可以无限逼近最终结果。比如下面这张动图,就动态描述了一个矩形方波,是如何做傅里叶分析的。
|
||||
<p align="center">
|
||||
<img src="/images/2014/08/jpeg_22.jpg" width="45%">
|
||||
<img src="/images/2014/08/jpeg_21.gif" width="45%">
|
||||
</p>
|
||||
|
||||
当我们要处理的不再是函数,而是一堆离散的数据时,并且这些数据是对称的话,那么傅里叶变化出来的函数只含有余弦项,这种变换称为离散余弦变换。举个例子,有一组一维数据$[x_0,x_1,x_2,\ldots,x_{n-1}]$,那么可以通过DCT变换得到$n$个变换级数$F_i$
|
||||
|
||||
$$\begin{aligned}
|
||||
F_m&=\sum_{k=0}^{n-1}x_k\cos\left[\frac{\pi}{n}m(k+\frac{1}{2})\right] \\
|
||||
m&=0,1,\ldots,n-1
|
||||
\end{aligned}\tag{2.1}
|
||||
$$
|
||||
此时原始数据$x_m$可以通过离散余弦变换变化的逆变换(IDCT)表达出来
|
||||
$$\begin{aligned}
|
||||
x_m&=\frac{F_0}{n}+\sum_{k=1}^{n-1}\left[\frac{2F_k}{n}\cos\left[\frac{\pi}{n}(m+\frac{1}{2})k\right]\right]\\
|
||||
m&=0,1,\ldots,n-1
|
||||
\end{aligned}\tag{2.2}
|
||||
$$
|
||||
也就是说,经过DCT变换,可以把一个数组分解成数个数组的和,如果我们数组视为一个一维矩阵,那么可以把结果看做是一系列矩阵的和
|
||||
$$\begin{aligned}
|
||||
&\left[x_0,x_1,x_2,\ldots,x_{n-1}\right]=\frac{F_0}{n}\left[1,1,1,\ldots,1\right]\\
|
||||
&+\small{\frac{2F_1}{n}\left[\cos{\frac{\pi}{2n}},\cos{\frac{3\pi}{2n}},\cos{\frac{5\pi}{2n}},\ldots,\cos{\frac{(2n-1)\pi}{2n}}\right]}\\
|
||||
&+\small{\frac{2F_2}{n}\left[\cos{\frac{2\pi}{2n}},\cos{\frac{6\pi}{2n}},\cos{\frac{10\pi}{2n}},\ldots,\cos{\frac{2(2n-1)\pi}{2n}}\right]}\\
|
||||
&+\small{\frac{2F_3}{n}\left[\cos{\frac{3\pi}{2n}},\cos{\frac{9\pi}{2n}},\cos{\frac{15\pi}{2n}},\ldots,\cos{\frac{3(2n-1)\pi}{2n}}\right]}\\
|
||||
&+\ldots\\
|
||||
&+\small{\frac{2F_{n-1}}{n}\left[\cos{\frac{(n-1)\pi}{2n}},\cos{\frac{2(n-1)\pi}{2n}},\cos{\frac{3(n-1)\pi}{2n}},\ldots,\cos{\frac{(n-1)(2n-1)\pi}{2n}}\right]}\\
|
||||
\end{aligned}\tag{2.3}
|
||||
$$
|
||||
举个例子,我们有一个长度为8的数字,内容为[50,55,67,80,-10,-5,20,30],在数轴上展示的话,没有任何明显的规律
|
||||
|
||||

|
||||
|
||||
经过DCT转换,得到8个级数为[287.0,106.3,14.2,-110.8,9.2,65.7,-8.2,-43.9],根据公式2.3把这个数组转换为8个新的数组的和,再使用图像来表达的话,就可以发现DCT转换的有趣之处了
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
奥妙之处在于,经过DCT,数据中隐藏的规律被发掘了出来,杂乱的数据被转换成几个工整变化的数据。DCT转换后的数组中第一个是一个直线数据,因此又被称为“直流数据”,简称DC,后面的数据被称为“交流数据”,简称AC,这个称呼起源于信号分析中的术语。
|
||||
在JPEG压缩过程中,经过颜色空间的转换,每一个8X8的图像块,在数据上表现为3个8X8的矩阵,紧接着我们对这三个矩阵做一个二维的DCT转换,二维的DCT转换公式为
|
||||
$$\small{\begin{aligned}
|
||||
F(u,v)&=\alpha(u)\cdot\alpha(v)\cdot \sum_{x=0}^{7}\sum_{y=0}^{7}f(x,y)\cos\left(\frac{2x+1}{16}u\pi\right)\cos\left(\frac{2y+1}{16}v\pi\right)\quad u,v=0,1,2,\ldots,7\\
|
||||
\alpha(u)&=\begin{cases}1/\sqrt{8}, & \text{when u}=0\\
|
||||
1/2, & \text{when u}\neq 0\end{cases}
|
||||
\end{aligned}}\tag{2.4}
|
||||
$$
|
||||
DCT的威力究竟有多大,我们可以做一个实际的测试,比如一个所有数值都一样的矩阵,经过DCT转换后,将所有级数组合成一个新的矩阵
|
||||
$$
|
||||
\small{\begin{bmatrix}
|
||||
100&100&100&100&100&100&100&100\\
|
||||
100&100&100&100&100&100&100&100\\
|
||||
100&100&100&100&100&100&100&100\\
|
||||
100&100&100&100&100&100&100&100\\
|
||||
100&100&100&100&100&100&100&100\\
|
||||
100&100&100&100&100&100&100&100\\
|
||||
100&100&100&100&100&100&100&100\\
|
||||
100&100&100&100&100&100&100&100
|
||||
\end{bmatrix}\overset{\text{DCT}}{\Longrightarrow}
|
||||
\begin{bmatrix}
|
||||
800&0&0&0&0&0&0&0\\
|
||||
0&0&0&0&0&0&0&0\\
|
||||
0&0&0&0&0&0&0&0\\
|
||||
0&0&0&0&0&0&0&0\\
|
||||
0&0&0&0&0&0&0&0\\
|
||||
0&0&0&0&0&0&0&0\\
|
||||
0&0&0&0&0&0&0&0\\
|
||||
0&0&0&0&0&0&0&0
|
||||
\end{bmatrix}
|
||||
}
|
||||
$$
|
||||
可以看到,经过DCT转换,矩阵的“能量”被全部集中在左上角上的直流分量F(0,0)上,其他位置都变成了0。
|
||||
在实际的JPEG压缩过程中,由于图像本身的连贯性,一个8X8的图像中的数值一般不会出现大的跳跃,经过DCT转换会有类似的效果,左上角的直流分量保存了一个大的数值,其他分量都接近于0,我们以Lenna左上角第一块图像的Y分量为例,经过变换的矩阵为
|
||||
$$
|
||||
\small{\begin{bmatrix}
|
||||
34&34&34&33&34&28&35&32\\
|
||||
34&34&34&33&34&28&35&32\\
|
||||
34&34&34&33&34&28&35&32\\
|
||||
34&34&34&33&34&28&35&32\\
|
||||
34&34&34&33&34&28&35&32\\
|
||||
36&36&29&27&33&31&30&31\\
|
||||
32&32&35&30&32&33&31&27\\
|
||||
30&30&27&28&30&30&28&29\\
|
||||
\end{bmatrix}\overset{\text{DCT}}{\Longrightarrow}
|
||||
\begin{bmatrix}
|
||||
257.1&6.4&2.5&-0.3&0.4&0.1&-6.0&6.9\\
|
||||
8.4&0.0&0.5&-0.5&1.9&3.4&-4.2&3.3\\
|
||||
-5.3&-1.0&-1.4&1.3&-0.7&-0.5&2.1&-1.7\\
|
||||
2.4&1.7&1.5&1.5&-0.6&-1.5&0.2&0.4\\
|
||||
-1.1&-1.6&-0.2&-1.8&1.6&1.2&-1.4&-0.1\\
|
||||
1.4&0.9&-1.9&-0.1&-2.0&0.9&1.5&0.7\\
|
||||
-2.0&-0.1&3.1&2.0&1.8&-2.7&-0.9&-1.3\\
|
||||
1.5&-0.2&-2.3&-1.9&-1.0&2.3&0.3&1.1\\
|
||||
\end{bmatrix}
|
||||
}
|
||||
$$
|
||||
可以看到,数据经过DCT变化后,被明显分成了直流分量和交流分量两部分,为后面的进一步压缩起到了充分的铺垫作用,可以说是整个JPEG中最重要的一步,后面我们会介绍数据量化。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user