DCT 变换及整数DCT 变换
为了给x264打好基础,x264用的是整数DCT 变换,所以就先来说说DCT 变换吧。 DCT(Discrete Cosine Transform),又叫离散余弦变换,它的第二种类型,经常用于信号和图像数据的压缩。经过DCT 变换后的数据能量非常集中,一般只有左上角的数值是非零的,也就是能量都集中在离散余弦变换后的直流和低频部分,下面我会用matlab 来演示整个过程。
1. 一维DCT 变换 我们首先来看看一维的DCT 变换,这是二维的基础。一维的DCT 变换共有8种,其中最
实用的是第二种形式,公式如下:其中c(u)是加上去一个系数,为了能使DCT 变换矩阵成为正交矩阵,在后面二维变换将看到他的作用。N 是
f(x)的总数。相比其他几种形式,他的运算还是比较简单的,因此也用的比较广。
2. 二维DCT 变换
二维DCT 变换是在一维的基础上再进行一次DCT 变换,这个比较好理解,直接看公式:
这里我只讨论两个N 相等的情况,也就是数据是方阵的形式,在实际应用中对不是方阵的数据都是先补齐再进行变换的。为了matlab 仿真方便点,写成矩阵形式:
下面就用matlab 来模拟一下,使用随机生成的4x4矩阵
作为输入,程序如下:
1.
2.
3. clear; clc; X=round(rand(4)*100);%随机生成的数据
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16. A=zeros(4);%变换矩阵 for i=0:3 for j=0:3 if i==0 a=sqrt(1/4); else a=sqrt(2/4); end A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4); end end Y=A*X*A';%DCT变换 YY=dct2(X);%用matlab 中的函数进行DCT 变换
Y 是使用上面的公式进行变换,YY 是用matlab 自带的dct2函数变换,结果是是: 1.
2.
3.
4.
5.
6.
7.
8.
9. 10.
11.
12.
13.
14.
15.
16.
17. X = 61 19 50 20 82 26 61 45 89 90 82 43 93 59 53 97 Y = 242.5000 32.1613 22.5000 33.2212 -61.8263 7.9246 -10.7344 30.6881 -16.5000 -14.7549 22.5000 -6.8770 8.8322 16.6881 -35.0610 -6.9246 YY = 242.5000 32.1613 22.5000 33.2212 -61.8263 7.9246 -10.7344 30.6881 -16.5000 -14.7549 22.5000 -6.8770 8.8322 16.6881 -35.0610 -6.9246
可以看出Y 和YY 的结果是一样的,这也进一步验证了上面的公式是正确的。由于X 是我随机生成的,相关性很小,变换后的结果比较乱;如果是信号或图像这样相关性比较大的数据的话,数值会集中在左上角,右下角一般都是零,再使用“之”字型扫描得到数据流会包含很多连续的零,编码后数据量会非常小,这就是DCT 变换带来的好处。
3. 二维DCT 反变换
DCT 逆变换的公式如下:
矩阵形式可以
由正变换的公式直接推出来,因为在A 中加了c(i)这个系数,使得A 成为了正交矩阵,所以我们就可以这样做:
原来的数据: 在用matlab 来验证是否能反变换出
1.
2.
3.
4.
5.
6.
7. 8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20. clear; clc; X=[ 61 19 50 20 82 26 61 45 89 90 82 43 93 59 53 97]; A=zeros(4); for i=0:3 for j=0:3 if i==0 a=sqrt(1/4); else a=sqrt(2/4); end A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4); end end Y=A*X*A'; X1=A'*Y*A;
X 使用的是上面正变换用的数据,运行后得到的X1为:
1.
2.
3.
4.
5. X1 = 61.0000 19.0000 50.0000 20.0000 82.0000 26.0000 61.0000 45.0000 89.0000 90.0000 82.0000 43.0000 93.0000 59.0000 53.0000 97.0000
和X 完全相等。在实际进行编码的时候,比如JPEG 压缩的时候,只会对Y 左上角的数据进行传输,所以解码出来的内容不会完全和原来的相同。
4. 整数DCT 变换
说道DCT 就顺便提一下x264中的整数DCT 变换,整数
DCT 变换是以DCT 变换为基础的,为了减少计算量做的一些调整,下面我写一下整数DCT 变换公式的大致推导过程:
(4)
然后根据A 是正交矩阵,把c=bd带入A 中,使行向量为单位向量可以得到d=2-1=0.4142。这个数不是有理数, 不便于使用二进制的算术运算. 为简化运算, 令d=1/2。
T 2为了保持矩阵A 的正交性, 及A A =I , 求解得到b=/[2(1+d )]=2/5。于是变换式(4)
中的常数定选定为:a=1/2, b =2/5,d=1/2,而c =/10。
代入上面的式子中,把0.5提取出来放到右边的点
乘中就得到了:这样在对大括号部分进行计算时就都是加法和减法了。需要说明的是:(1)这个正交变换是近似的正交变换,因为对d 和b 做了改动,因此变换的输出与4x4的DCT 变换不一致;但在精度上没有太大降低;(2)在x264实际编码中,变换和量化是一起进行的,使得编码速度有了很大的提高。
DCT 变换及整数DCT 变换
为了给x264打好基础,x264用的是整数DCT 变换,所以就先来说说DCT 变换吧。 DCT(Discrete Cosine Transform),又叫离散余弦变换,它的第二种类型,经常用于信号和图像数据的压缩。经过DCT 变换后的数据能量非常集中,一般只有左上角的数值是非零的,也就是能量都集中在离散余弦变换后的直流和低频部分,下面我会用matlab 来演示整个过程。
1. 一维DCT 变换 我们首先来看看一维的DCT 变换,这是二维的基础。一维的DCT 变换共有8种,其中最
实用的是第二种形式,公式如下:其中c(u)是加上去一个系数,为了能使DCT 变换矩阵成为正交矩阵,在后面二维变换将看到他的作用。N 是
f(x)的总数。相比其他几种形式,他的运算还是比较简单的,因此也用的比较广。
2. 二维DCT 变换
二维DCT 变换是在一维的基础上再进行一次DCT 变换,这个比较好理解,直接看公式:
这里我只讨论两个N 相等的情况,也就是数据是方阵的形式,在实际应用中对不是方阵的数据都是先补齐再进行变换的。为了matlab 仿真方便点,写成矩阵形式:
下面就用matlab 来模拟一下,使用随机生成的4x4矩阵
作为输入,程序如下:
1.
2.
3. clear; clc; X=round(rand(4)*100);%随机生成的数据
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16. A=zeros(4);%变换矩阵 for i=0:3 for j=0:3 if i==0 a=sqrt(1/4); else a=sqrt(2/4); end A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4); end end Y=A*X*A';%DCT变换 YY=dct2(X);%用matlab 中的函数进行DCT 变换
Y 是使用上面的公式进行变换,YY 是用matlab 自带的dct2函数变换,结果是是: 1.
2.
3.
4.
5.
6.
7.
8.
9. 10.
11.
12.
13.
14.
15.
16.
17. X = 61 19 50 20 82 26 61 45 89 90 82 43 93 59 53 97 Y = 242.5000 32.1613 22.5000 33.2212 -61.8263 7.9246 -10.7344 30.6881 -16.5000 -14.7549 22.5000 -6.8770 8.8322 16.6881 -35.0610 -6.9246 YY = 242.5000 32.1613 22.5000 33.2212 -61.8263 7.9246 -10.7344 30.6881 -16.5000 -14.7549 22.5000 -6.8770 8.8322 16.6881 -35.0610 -6.9246
可以看出Y 和YY 的结果是一样的,这也进一步验证了上面的公式是正确的。由于X 是我随机生成的,相关性很小,变换后的结果比较乱;如果是信号或图像这样相关性比较大的数据的话,数值会集中在左上角,右下角一般都是零,再使用“之”字型扫描得到数据流会包含很多连续的零,编码后数据量会非常小,这就是DCT 变换带来的好处。
3. 二维DCT 反变换
DCT 逆变换的公式如下:
矩阵形式可以
由正变换的公式直接推出来,因为在A 中加了c(i)这个系数,使得A 成为了正交矩阵,所以我们就可以这样做:
原来的数据: 在用matlab 来验证是否能反变换出
1.
2.
3.
4.
5.
6.
7. 8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20. clear; clc; X=[ 61 19 50 20 82 26 61 45 89 90 82 43 93 59 53 97]; A=zeros(4); for i=0:3 for j=0:3 if i==0 a=sqrt(1/4); else a=sqrt(2/4); end A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4); end end Y=A*X*A'; X1=A'*Y*A;
X 使用的是上面正变换用的数据,运行后得到的X1为:
1.
2.
3.
4.
5. X1 = 61.0000 19.0000 50.0000 20.0000 82.0000 26.0000 61.0000 45.0000 89.0000 90.0000 82.0000 43.0000 93.0000 59.0000 53.0000 97.0000
和X 完全相等。在实际进行编码的时候,比如JPEG 压缩的时候,只会对Y 左上角的数据进行传输,所以解码出来的内容不会完全和原来的相同。
4. 整数DCT 变换
说道DCT 就顺便提一下x264中的整数DCT 变换,整数
DCT 变换是以DCT 变换为基础的,为了减少计算量做的一些调整,下面我写一下整数DCT 变换公式的大致推导过程:
(4)
然后根据A 是正交矩阵,把c=bd带入A 中,使行向量为单位向量可以得到d=2-1=0.4142。这个数不是有理数, 不便于使用二进制的算术运算. 为简化运算, 令d=1/2。
T 2为了保持矩阵A 的正交性, 及A A =I , 求解得到b=/[2(1+d )]=2/5。于是变换式(4)
中的常数定选定为:a=1/2, b =2/5,d=1/2,而c =/10。
代入上面的式子中,把0.5提取出来放到右边的点
乘中就得到了:这样在对大括号部分进行计算时就都是加法和减法了。需要说明的是:(1)这个正交变换是近似的正交变换,因为对d 和b 做了改动,因此变换的输出与4x4的DCT 变换不一致;但在精度上没有太大降低;(2)在x264实际编码中,变换和量化是一起进行的,使得编码速度有了很大的提高。