转自:http://fellowher.blog.163.com/blog/static/5076351520099279115651/  中间有自己的理解。

为什么要进行变换

空间图像数据通常是很难压缩的:相邻的采样点具有很强的相关性(相互关联的),而且能量一般平均分布在一幅图像中,从而要想丢掉某些数据和降低数据精度而不明显影响图像质量,就要选择合适的变换,方法,使图像易于被压缩。适合压缩的变换方法要有这样几个性质:

1、可以聚集图像的能量(将能量集中到少数有意义的数值上);如下图:

举个例子说明,下图是变换前的数据:

以下是变换后的数据:

可以看出,经变换后,数据的能量基本上集中到左上方(低频信号)了,而变换后的数据完全可以通过反变换还原成原来的数据。为了达到压缩文件的目的,我们就可以丢弃掉一些能量低的数据(高频信号),而对图像质量影响很小。

2、可以除去数据之间的相关性(以使丢掉不重要的数据对图像的质量影响很少)。

3、变换方法应该适合用软硬件实现。

以下将描述4x4整数DCT推导过程

将上面的DCT公式转变为矩阵形式,为了说明标准中整数变换和反变换,先设d=c/b,

[sno: 这里两个[]中间是矩阵乘的关系]

我们可以把DCT变换写成下式:

[sno:这是三个矩阵相乘,就是DCT转换的公式:Cf * X *Cft  ]

其中,为了保证正交,a ,b, c, d的值可分别如下设置:

根据假设,上式可化为:

把两边的对称矩阵移到左边可得:(对角阵移项)

这一步也有点问题:(等价的乘数移项)

此时,d的值为0.4142。这样的话,还是实数运算。如我们令d=1/2,则b=sqrt(2/5).

c=sqrt(1/10),同样,可以保证矩阵的正交,同时,可以把运算变为整数运算。

1/2可以提到矩阵外面,并与右边的点乘合并,得

其中,

在JM编码器中,变换过程只包括了

后面的点乘实际上是在量化过程中进行,因为后面的点乘还有实数运算,实数运算将不可避免地产生精度误差,而且运算量巨大。而量化本身就会丢失一些信号,因些,这些实数运算放在量化过程中将大大的降低变换的运算率同时又不明显影响精度?[sno: 之所有把后面的Ef和这里分割开,是因为在转换和量化这一步,不可避免的会遇到乘法操作,这里说的只用加减和移位操作,是在这三个矩阵乘法大数据量运算之间只使用加减和移位,可以把64次的乘法运算转为只有两次的乘法运算,极大的减少消耗,在量化的时候,再对每个W[i][j]分别进行乘法操作。]

然而,4X4的矩阵运算如果按常规算法的话仍要进行64次乘法运算和48次加法,这将耗费较多的时间,于是在H.264中,有一种改进的算法(蝶形算法)可以减少运算的次数。这种矩阵运算算法构造非常巧妙,利用构造的矩阵的整数性质和对称性,可完全将乘法运算转化为加法运算。

变换过程在JM中代码实现如下:

//  Horizontal transform水平变换,其实就是左乘Cf,

for (j=0; j < BLOCK_SIZE && !lossless_qpprime; j++)

{

for (i=0; i < 2; i++)

{

i1=3-i;

m5[i]=img->m7[i][j]+img->m7[i1][j];

m5[i1]=img->m7[i][j]-img->m7[i1][j];

}

img->m7[0][j]=(m5[0]+m5[1]);

img->m7[2][j]=(m5[0]-m5[1]);

img->m7[1][j]=m5[3]*2+m5[2];

img->m7[3][j]=m5[3]-m5[2]*2;

}

//  Vertical transform垂直变换,其实就是右乘CfT

for (i=0; i < BLOCK_SIZE && !lossless_qpprime; i++)

{

for (j=0; j < 2; j++)

{

j1=3-j;

m5[j]=img->m7[i][j]+img->m7[i][j1];

m5[j1]=img->m7[i][j]-img->m7[i][j1];

}

img->m7[i][0]=(m5[0]+m5[1]);

img->m7[i][2]=(m5[0]-m5[1]);

img->m7[i][1]=m5[3]*2+m5[2];

img->m7[i][3]=m5[3]-m5[2]*2;

}

上面的内容载抄自网络,我做了少量更改。多数内容来自毕厚杰的书。

这里来分析一下蝶形算法,这个蝶形算法和一般FFT的蝶形算法不同,由于我没有找到相关论文,能找到的书和网络资料又语焉不详,只好自己推导。上面的JM代码就是计算下面三个4x4矩阵的过程。

分析一下前两个矩阵的乘法,只分析他们结果矩阵的第一行。有什么办法可以减少运算量呢?首先采用传统方法计算,得到结果:

X[0] = x[00]+x[10]+x[20]+x[30]

X[1] = 2*x[00]+x[10]-x[20]-2*x[30]

X[2]= x[00]-x[10]-x[20]+x[30]

X[3] = x[00]-2x[10]+2x[20]-x[30]

计算代价是16次乘法12次加法,考虑到矩阵的1的乘法可以省略,去除8个乘1,还需要8次乘法和12次加法。那么我们再仔细思考他们的相关性,从一般算法意义上来说,可以用空间代价换时间代价,比如设置中间变量来减少计算次数。用不同的颜色把需要重复运算的部分标上,作为中间变量。

X[0] = x[00]+x[10]+x[20]+x[30]

X[1] = 2*x[00]+x[10]-x[20]-2*x[30]

X[2]= x[00]-x[10]-x[20]+x[30]

X[3] = x[00]-2x[10]+2x[20]-x[30]

那么提取出来的中间变量将是:

x[00]+x[30]

x[00]-x[30]

x[10]+x[20]

x[10]-x[20]

存储了这四个中间变量,我们对比看看蝶形图,和图中第一层的算式相符合。用这些中间变量来组合,就可以把最终的X[0]..X[3], 计算出来。这样,就把运算量降低到2个乘法和8个加法,剩余的运算就是叠代这个算法。

所以,可以得出以下结论:

  1. 这个蝶形图和一般意义的FFT或FDCT蝶形图不同,是对H.264在整数DCT基础上的具体算法优化,只对于以上Cf矩阵。
  2. 计算过程是把上面的三个4x4矩阵乘法分成两两矩阵相乘。再把残差矩阵和后来的中间结果Cf x X一行行分别输入蝶形图进行一维整数DCT计算。
  3. 蝶形图优化思想就是提取矩阵的相关部分,定义中间变量,减少运算次数。[sno:这里很重要,之所以使用蝶形算法,就是统计一下多次运行的规律,不重复计算相关的量。]
  4. sno: 矩阵相乘 A*B   就是把A矩阵当前元素所在的这一行乘以B矩阵当前元素所在的这一列。代码实现如下
    int  matrix_multiply(int a[4][4],int b[4][4],int c[4][4])
    {
            int i,j,k;
            for(i=0;i<4;i++)
                    for(j=0;j<4;j++)
                    {
                            c[i][j]=0;
                            for(k=0;k<4;k++)        
                                    c[i][j]+=a[i][k]*b[k][j];  ///c[i][j]=a的i这一行*b的j这一列的总和 ,这里是累计和                          
                    }
            return 0;        
    }

H264___DCT蝶形算法____理解相关推荐

  1. matlab温度数据怎么滤波_卡尔曼滤波算法思想理解 Kalman filter 第一篇

    卡尔曼滤波算法思想理解 Kalman filter 第一篇 最近在初步的理解目标跟踪的领域, 其中一个非常经典的算法卡尔曼滤波Kalman filter是需要有很好的理解才行, 由于已经脱离了学校,懂 ...

  2. Interview:算法岗位面试—11.15下午上海某航天***公司(国企)技术面之工业机器视觉认知、计算机视觉算法的理解、目标检测相关项目案例

    ML岗位面试:11.15下午上海某航天***公司(国企)技术面之工业机器视觉认知.计算机视觉算法的理解.目标检测相关项目案例 Interview:算法岗位面试-11.15下午上海某航天***公司(国企 ...

  3. React中diff算法的理解

    React中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DO ...

  4. Vue中diff算法的理解

    Vue中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DOM结 ...

  5. 电子凸轮追剪曲线生成算法 算法,理解后可转成其他品牌PLC或任何一种编程语言

    电子凸轮追剪曲线生成算法. 品牌:麦格米特(算法,理解后可转成其他品牌PLC或任何一种编程语言) YID:5850633554519425

  6. 算法小白理解最大流最小割(Maximum flow Minimum cut)问题

    网上流传的关于最大流最小割问题的全都是索然无味 的一些讲课视频,当然如果你英语能力很强,直接看外国的视频也十分好理解,但于我这种理工科渣渣来说,看懂那种专业的讲课视频是不可能的,不存在的,所以把自己对 ...

  7. openCV中直方图均衡化算法的理解

    直方图均衡化就是调整灰度直方图的分布,即将原图中的灰度值映射为一个新的值.映射的结果直观表现是灰度图的分布变得均匀,从0到255都有分布,不像原图那样集中.图像上的表现就是对比度变大,亮的更亮,暗的更 ...

  8. 【signal】傅里叶分析和FFT蝶形算法

    Date: 2018.10.31 下面两篇文章对傅里叶分析和FFT蝶形算法的分析很好,特转载. https://www.cnblogs.com/luoqingyu/p/5930181.html htt ...

  9. Levenberg-Marquardt(LM算法)的理解

    Levenberg-Marquardt LM算法 的理解 1. convex optimization 1.1 convex set 1.2 convex function 1.3 optimizat ...

  10. 八皇后BFS算法、DFS算法、A*算法代码理解

    代码参考了Python:DFS/BFS/UCS解决八皇后问题_流动的风与雪的博客-CSDN博客 和Python:GBF/A*算法解决八皇后问题_流动的风与雪的博客-CSDN博客 但是我花了两天时间才看 ...

最新文章

  1. python字符串按长度分割_python 按照固定长度分割字符串的方法小结
  2. IBM的大数据就是返朴归真
  3. angularjs中的分页指令
  4. 回溯算法详解:理论+基础类回溯题解
  5. 【自】数据库系统原理(三)——测试总结后,
  6. 住建部印发《全国建筑设计周期定额》——建设和设计单位“不得压缩”设计周期...
  7. 清华085211计算机技术,2018年清华大学计算机系计算机技术考研(085211)考试科目、参考书目、复习经验---新祥旭考研...
  8. linux服务器什么意思,linux中的“/”和“./”是什么意思
  9. Ajax-GET请求
  10. 混拨vps与单城市拨号vps有什么区别?
  11. 计算机打字盲打方法,盲打
  12. 记WSL下MySQL安装和使用BUG
  13. android高德地图线路,独立路径规划-路线规划-开发指南-Android 导航SDK | 高德地图API...
  14. Renix软件如何建立OSPF邻居——网络测试仪实操
  15. Java 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量问题解决
  16. 【Hadoop】org.apache.hadoop.security.AccessControlException: Permission denied
  17. Autodesk所有产品的卸载、安装解决方案(3dsmax、cad等)
  18. 011 Rust死灵书之幽灵数据
  19. android设备什么手机号码,安卓手机如何查看本机号码 查看本机号码的方法有哪些...
  20. Qt编译报错:未找到文件main.obj

热门文章

  1. Fall 2020 Berkeley cs61a hw04答案
  2. Matlab基础(5)——符号运算
  3. c语言如何显示shp文件,shapefile文件(shp)读取
  4. 解读《美国国家BIM标准》– BIM能力成熟度模型 (一)
  5. 计算机画图工具介绍PPT,怎么用思维导图制作PPT课件,迅捷画图软件讲解
  6. Android基于在线地图的轨迹跟踪服务
  7. 【gigabyte】开机循环进入技嘉主板界面、BIOS功能识别不出硬盘
  8. 网络游戏行业按20%的税率缴个人所得税?每百万要上缴20万怎么节税
  9. 【Proteus仿真】基于STC15单片机简易数码管定时器时钟
  10. c语言编程绝对质数,C语言《绝对素数》