二维DCT变换

https://wuyuans.com/2012/11/dct2/

写这篇文章的目的主要是为了给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. clear;
  2. clc;
  3. X=round(rand(4)*100);%随机生成的数据
  4. A=zeros(4);%变换矩阵
  5. for i=0:3
  6. for j=0:3
  7. if i==0
  8. a=sqrt(1/4);
  9. else
  10. a=sqrt(2/4);
  11. end
  12. A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4);
  13. end
  14. end
  15. Y=A*X*A‘;%DCT变换
  16. YY=dct2(X);%用matlab中的函数进行DCT变换

Y是使用上面的公式进行变换,YY是用matlab自带的dct2函数变换,结果是是:

  1. X =
  2. 61 19 50 20
  3. 82 26 61 45
  4. 89 90 82 43
  5. 93 59 53 97
  6. Y =
  7. 242.5000 32.1613 22.5000 33.2212
  8. -61.8263 7.9246 -10.7344 30.6881
  9. -16.5000 -14.7549 22.5000 -6.8770
  10. 8.8322 16.6881 -35.0610 -6.9246
  11. YY =
  12. 242.5000 32.1613 22.5000 33.2212
  13. -61.8263 7.9246 -10.7344 30.6881
  14. -16.5000 -14.7549 22.5000 -6.8770
  15. 8.8322 16.6881 -35.0610 -6.9246

可以看出Y和YY的结果是一样的,这也进一步验证了上面的公式是正确的。由于X是我随机生成的,相关性很小,变换后的结果比较乱;如果是信号或图像这样相关性比较大的数据的话,数值会集中在左上角,右下角一般都是零,再使用“之”字型扫描得到数据流会包含很多连续的零,编码后数据量会非常小,这就是DCT变换带来的好处。

3.二维DCT反变换

DCT逆变换的公式如下:矩阵形式可以由正变换的公式直接推出来,因为在A中加了c(i)这个系数,使得A成为了正交矩阵,所以我们就可以这样做:在用matlab来验证是否能反变换出原来的数据:

  1. clear;
  2. clc;
  3. X=[
  4. 61 19 50 20
  5. 82 26 61 45
  6. 89 90 82 43
  7. 93 59 53 97];
  8. A=zeros(4);
  9. for i=0:3
  10. for j=0:3
  11. if i==0
  12. a=sqrt(1/4);
  13. else
  14. a=sqrt(2/4);
  15. end
  16. A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4);
  17. end
  18. end
  19. Y=A*X*A‘;
  20. X1=A‘*Y*A;

X使用的是上面正变换用的数据,运行后得到的X1为:

  1. X1 =
  2. 61.0000 19.0000 50.0000 20.0000
  3. 82.0000 26.0000 61.0000 45.0000
  4. 89.0000 90.0000 82.0000 43.0000
  5. 93.0000 59.0000 53.0000 97.0000

和X完全相等。在实际进行编码的时候,比如JPEG压缩的时候,只会对Y左上角的数据进行传输,所以解码出来的内容不会完全和原来的相同。

4.整数DCT变换

说道DCT就顺便提一下x264中的整数DCT变换,整数DCT变换是以DCT变换为基础的,为了减少计算量做的一些调整,下面我写一下整数DCT变换公式的大致推导过程:然后根据A是正交矩阵,把c=bd带入A中,使行向量为单位向量可以得到d=0.4142。令d=0.5,得到b*b=0.4,代入上面的式子中,把0.5提取出来放到右边的点乘中就得到了:这样在对大括号部分进行计算时就都是加法和减法了,而且在精度上没有太大降低。在x264实际编码中,变换和量化是一起进行的,使得编码速度有了很大的提高。

作者:wuyuan 本文来自Wuyuan‘s Blog 转载请注明,谢谢! 文章地址: https://wuyuans.com/2012/11/dct2

时间: 2025-01-14 07:16:16

二维DCT变换的相关文章

二维图形变换

5.1二维图形变化 一.向量 是具有长度和方向的实体 二.特殊的线性组合 (1)仿射组合 (2)凸组合(对仿射组合加以更多的限制) 三.向量的点积和叉积 (1)点积 两个向量夹角的余弦值等于两个单位向量的点积 (2)叉积 两个向量的叉积是另一个三维向量,且与两个向量均正交 利用叉积求平面的法向量,三点可确定一个平面 5.2 图形坐标系 1.世界坐标系 是一个公共坐标系,是现实中物体或场景的统一参考系 2.建模坐标系 又称局部坐标系,每个物体有自己的局部中心和坐标系 3.观察坐标系 从观察者的角度

【DCT笔记】DCT变换、DCT反变换、分块DCT变换

DCT变换.DCT反变换.分块DCT变换 欢迎转载,但请注明出处! 一.引言 DCT变换的全称是离散余弦变换(Discrete Cosine Transform),主要用于将数据或图像的压缩,能够将空域的信号转换到频域上,具有良好的去相关性的性能.DCT变换本身是无损的,但是在图像编码等领域给接下来的量化.哈弗曼编码等创造了很好的条件,同时,由于DCT变换时对称的,所以,我们可以在量化编码后利用DCT反变换,在接收端恢复原始的图像信息.DCT变换在当前的图像分析已经压缩领域有着极为广大的用途,我

FFT与二维FFT的C#实现

傅里叶变换在信息处理应用中具有很实用的价值,而快速傅里叶变换,即FFT,是实用的计算算法. 本文介绍FFT和2维FFT的C#实现方法. 1. FFT编程依据 FFT是按照如图结构(也称蝶形结构)进行运算(图片来源于网络). 图中,箭头代表数据流向,箭头与箭头的合并点代表相加,箭头下面的常数代表相乘,WN(注:N为下标) = exp(-j * 2 * PI / N),j为虚数单位,DIT的输入(或DIF的输出)序列重排点y[m]与初始输入点x[n]的关系为:m与n互为倒位序(例:001 -- 10

二维图像频谱中的两点表示什么

冈萨雷斯版<图像处理>里面的解释非常形象:一个恰当的比喻是将傅里叶变换比作一个玻璃棱镜.棱镜是可以将光分解为不同颜色的物理仪器,每个成分的颜色由波长(或频率)来决定. 傅里叶变换可以看作是数学上的棱镜,将函数基于频率分解为不同的成分.当我们考虑光时,讨论它的光谱或频率谱.同样, 傅立叶变换使我们能通过频率成分来分析一个函数. 图像傅立叶变换的物理意义 图像的频率是表征图像中灰度变化剧烈程度的指标,是灰度在平面空间上的梯度.如:大面积的沙漠在图像中是一片灰度变化缓慢的区域,对应的频率值很低:而对

AVS-P2中的8x8二维整数余弦变换(Integer Cosine Transform, ICT)

为何采用ICT? 基于块的DCT能很大程度上去除图像元素在变换域中的相关性,在图像和视频编码领域得到广泛的应用.但由于DCT存在计算量大以及存在反变换失配,因此AVS Part 2采用的是ICT,其性能接近8x8 DCT,但精确定义到每一位的运算避免了不同反变换之间的失配.ICT具有复杂度低.完全匹配等优点.ICT可用加法和移位直接实现. 何为ICT? 整数余弦变换(Integer Cosine Transform, ICT)源自离散余弦变换,是定点余弦变换的扩展.设一个二维数据块X大小为nxm

二维图像的三角形变换算法解释

http://blog.csdn.net/aqua_aqua/article/details/407660 对于二维图像的变形,最简单直接的方式就是将需要变形的不规则区域进行三角形划分,使复杂多边形由1到N个三角形组成,那么最终的变形动作也就转化为这些三角形变形. 三角形变形,就是将一个三角形通过某种变换变成另一个三角形,同时也要保证在源三角形中的点能够正确映射到目标三角形中合适的位置.如下图所示: 图中△ABC是源三角形,Z点是源三角形中的任意一点.△abc为目标三角形,而z点就是源三角形中Z

C++实现离散余弦变换(参数为二维指针)

http://www.cnblogs.com/scut-linmaojiang/p/5013590.html 写在前面 到目前为止已经阅读了相当一部分的网格水印等方面的论文了,但是论文的实现进度还没有更上,这个月准备挑选一些较为经典的论文,将其中的算法实现.在实现论文的过程中,发现论文中有用到一些空域转频率域的算法.因此也就想到了实现一下离散余弦变换.虽然本文的代码和网上很多已有的代码很类似,思路都没有太多的差别,但是本文有一个比较重要的改进.具体的说,网上现有DCT算法输入的是一个固定的二维数

使用libqrencode库制作二维码电子名片--IOS版

1.效果图: 点击生成按钮,显示二维码: 使用微信扫一扫后,获得如下界面: 2.libqrencode库: libqrencode是一个日本人(Kentaro Fukuchi)写的生成二维码的跨平台c语言库.官网是这里,Github在这里.本人最喜欢的就是这种[用c写成的.跨平台的.功能单一的.使用方便的]库!IOS中Objc使用C/C++库超方便,android下,稍微麻烦一点. 3.Objc对libqrencode包装: 网上找的QRCodeGenerator类,由Andrew Kopane

nRF51800 蓝牙学习 进程记录 2:关于二维数组 执念执战

前天在玩OLED时想完成一直想弄得一个东西,就是简单的单片机游戏.因为STM32和nRF51822的内存足够,所以就用缓存数组的方法来显示图像(我也不知道术语是啥,反正就是在内存中建立一个128X64的二维数组,更新显示时将整个数组刷新到屏幕上),而且这两个OLED是串口的(还有一个128X32的OLED,一样串口的,连驱动时序和驱动函数都一样,两个都太小了,还那么贵......),四个IO口就能驱动(两个还是供电的VCC和GND),所以不像之前的那个mini 12864屏幕,它是8位并口的,带