背景

为压缩数据,H264标准需要使用整数DCT变换把图像信号转换到频域。变换过程实际上就是矩阵乘法,使用蝶形变换可以减少运算量,提升算法性能。

原理

整数DCT变换公式推导过程不再赘述,可以参考《深入理解视频编解码技术 --基于H264标准及参考模型》。
以4x4为例,变换公式如下:

  Y = Cf * X * Cf.T其中 Cf = [1, 1,  1,  1,2, 1, -1, -2,1,-1, -1,  1,1,-2,  2, -1]

展开如下:

  • 先以Cf*X 为例,矩阵乘需要进行64次乘法和48次加法,这将耗费较多的时间。蝶形算法则是利用构造的矩阵的整数性质和对称性,将乘法运算转化为加法运算。
    先分析两个相乘矩阵的第一列,结果如下:
    p0 = x00+x30\color{#FF0000} { x00 + x30}x00+x30 + x10+x20\color{#00FF00}{x10 + x20 }x10+x20
    p1 = 2∗x00+2∗x30\color{#FF0000}{2 * x00+2 * x30}2∗x00+2∗x30 + x10−x20\color{#00FF00}{x10 - x20}x10−x20
    p2 = x00−x30\color{#FF0000} { x00 - x30}x00−x30 - x10−x20\color{#00FF00}{x10 - x20}x10−x20
    p3 = x00−x30\color{#FF0000} {x00- x30}x00−x30 - 2∗x10+2∗x20\color{#00FF00}{2 * x10 + 2 * x20}2∗x10+2∗x20
  • 从上面公式我们发现有重复运算(使用不同颜色标识),从一般算法意义上来说,可以用空间代价换时间代价,比如设置中间变量来减少计算次数。
    提取中间结果:
    M0 = x00 + x30
    M3 = x00 - x30
    M1 = x10 + x20
    M2 = x10 - x20
  • 存储了这四个中间变量,我们对比看看蝶形图,和图中第一层的算式相符合。用这些中间变量来组合,就可以把最终的p0…p3, 计算出来。这样,就把运算量降低到2个乘法和8个加法,剩余的运算就是叠代这个算法。

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

  • 这个蝶形图和一般意义的FFT或FDCT蝶形图不同,是对H.264在整数DCT基础上的具体算法优化,只对于以上Cf矩阵。
  • 计算过程是把上面的三个4x4矩阵乘法分成两两矩阵相乘。再把残差矩阵和后来的中间结果Cf x X一行行分别输入蝶形图进行一维整数DCT计算。
  • 蝶形图优化思想就是提取矩阵的相关部分,定义中间变量,减少运算次数。
代码示例

以下代码分别用传统矩阵运算和蝶形运算计算结果并对比结果

#include <iostream>
using namespace std;//Cf矩阵
int Cf[4][4]=
{1, 1,  1,  1,2, 1, -1, -2,1,-1, -1,  1,1,-2,  2, -1
};void matrixTransform(int a[][4])
{int i, j;int tmp;for(i=0; i<4; i++){for(j=i; j<4; j++){tmp = a[i][j];a[i][j] = a[j][i];a[j][i] = tmp;}}
}//矩阵求积
// c = a * b
void  matrixMultiply_4x4(int a[][4],int b[][4],int c[][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];  }}}
}//矩阵显示
void matrixShow(int a[][4])
{int i, j;cout << "*****************************" << endl;for(i = 0; i < 4; i++){for(j = 0; j < 4; j++){cout << a[i][j] << "\t";}cout << endl;}cout << "*****************************" << endl << endl;
}// 蝶形变换求解 Cf* orgYUV * Cf.T
// b为输出matrix, a为输入
void forward4x4(int a[][4], int b[][4])
{int tmp[16];int p0,p1,p2,p3;int t0,t1,t2,t3;int i, j;int *ptmp = tmp;//horizontal, Cf*orgYUV for(i=0; i<4; i++){t0 = a[0][i];t1 = a[1][i];t2 = a[2][i];t3 = a[3][i];p0 = t0+t3;p1 = t1+t2;p2 = t1-t2;p3 = t0-t3;*(ptmp++) = p0+p1;*(ptmp++) = p2+ (p3<<1); // 加运算符优先级要于左移 *(ptmp++) = p0-p1;*(ptmp++) = p3- (p2<<1);}    //verticalfor(int i=0; i<4; i++){t0 = tmp[i];t1 = tmp[i+4];t2 = tmp[i+2*4];t3 = tmp[i+3*4];p0 = t0+t3;p1 = t1+t2;p2 = t1-t2;p3 = t0-t3;b[i][0] = p0+p1;b[i][1] = p2+ (p3<<1);b[i][2] = p0-p1;b[i][3] = p3- (p2<<1);}
}int main(int argc, char** argv) {//原始的YUV矩阵int orgYUV[4][4] ={-85, 88, 126, 121,-79, 70,  65,  83,-80, 66,  49,  43,-82, 86,  97,  41};int D[4][4];int W[4][4];// W = Cf* orgYUV * Cf.TmatrixMultiply_4x4(Cf, orgYUV, D);matrixTransform(Cf);    matrixMultiply_4x4(D, Cf, W);cout << "====== W =====" << endl;matrixShow(W);forward4x4(orgYUV, W);cout << "====== butter W =====" << endl;matrixShow(W);return 0;
}

H264-整数DCT变换和蝶形变换代码实现相关推荐

  1. H264编码器6( H.264整数DCT公式推导及蝶形算法分析)

    这是网上的一篇文章, 我重新读了一下, 然后做了一些整理 1.为什么要进行变换 空间图像数据通常是很难压缩的:相邻的采样点具有很强的相关性(相互关联的),而且能量一般平均分布在一幅图像中,从而要想丢掉 ...

  2. H.264整数DCT公式推导及蝶形算法分析

    转载自https://www.cnblogs.com/xkfz007/archive/2012/07/31/2616791.html <div class="postBody" ...

  3. H264中DCT变换,量化,反量化,反DCT变换

    H.264中采用的是整数DCT变换,在实现的时候,该变换和量化又杂糅在一起,那么这些错综复杂的关系究竟是怎样纠缠的呢?在参考H.264乐园论坛会员cs1860wd的帖子和H.264 and MPEG- ...

  4. 快速傅立叶变换(FFT)算法(原来这就是蝶形变换)

    快速傅立叶变换(FFT)算法(原来这就是蝶形变换) 为了实现FFT的海面模拟,不得不先撸个FFT算法实现. 离散傅立叶变换(DFT) 学习FFT之前,首先要先了解什么是DFT,我们都知道傅立叶变换是将 ...

  5. 压缩感知稀疏基之离散余弦变换(DCT)和离散正弦变换(DST)

    题目:压缩感知稀疏基之离散余弦变换(DCT)和离散正弦变换(DST) 在前面一篇<压缩感知的常见稀疏基名称及离散傅里叶变换基>中集结了九篇压缩感知文献中有关稀疏基名称,并且直白地告诉大家稀 ...

  6. DCT变换和DFT变换

    DCT变换和DFT变换 1:DFT变换 这里我只谈论二维的DFT变换,有关一维的DFT,请查看一下博客,里面有详细介绍: https://blog.csdn.net/IMWTJ123/article/ ...

  7. 计算机图形学-二维图形变换 笔记总结与代码实战

    文章目录 1.向量基础知识 2.图形坐标系 3.二维图形变换原理 4.二维图形几何变换 5.窗口视区变换 基本二维几何变换代码 二维复合变换实战-五星红旗绘制 1.向量基础知识 为什么向量如此重要:在 ...

  8. MATLAB坐标系变换动画gif(附代码):坐标系旋转动画+坐标系平移动画代码

    MATLAB坐标系变换动画gif(附代码) 以之前的文章中的例题为例,绘制一个向量和一个运动坐标系在空间中的变换过程,并生成gif动画. 已知坐标系{B}的初始位姿与{A}重合,首先{B}相对于{A} ...

  9. 为什么要进行傅立叶变换?傅立叶变换究竟有何意义?如何用Matlab实现快速傅立叶变换?

    https://www.douban.com/note/164400821/ 写在最前面:本文是我阅读了多篇相关文章后对它们进行分析重组整合而得,绝大部分内容非我所原创.在此向多位原创作者致敬!!! ...

最新文章

  1. 一分钟详解点云配准ICP方法
  2. Azure平台管理员必须了解的安全问题
  3. Java对象和XML之间的编排与反编排
  4. Excel制作考勤管理
  5. PAT甲级1149 Dangerous Goods Packaging :[C++题解]哈希表、逆向思维
  6. 腾讯信用向全国开放了,据说700分都算低的!
  7. TCP中间件_个人方案
  8. poj 3621 Sightseeing Cows 01分数规划
  9. 【零基础学Java】—Java运行机制(三)
  10. 剑指Offer_42_和为S的两个数字
  11. 对HTML(HyperText Markup Language)的认识以及总结
  12. access orcad 数据库_cis(orcad)本地元件access数据库创建跟加载方法详解.doc
  13. 全功能杀毒软件行业调研报告 - 市场现状分析与发展前景预测
  14. 用电脑看epub电子书用什么阅读软件好?
  15. IEEE2019论文:使用基于特征融合和缩放的具有空间上下文分析的单镜头检测器在无人机图像中检测小物体
  16. L2-3 清点代码库【STL】
  17. 什么是 ETL ?什么是 ELT ?
  18. Unity中使用TexturePacke打包的图集
  19. CNCC 2018 科技展盛况空前,近 100 家企业汇聚一堂
  20. JavaEE之Servlet/Jsp初识

热门文章

  1. 剑指 Offer 55 - 2 平衡二叉树
  2. 大数据领域经常听到ETL,那么什么是ETL
  3. StopWatch方法详解
  4. java 线程 基类_关于Linux 系统下 C++ 的多线程基类 Thread
  5. PHP 使用 QueryList + Redis 批量下载壁纸
  6. 拍摄VR全景这些硬件设备缺一不可!
  7. 【Java学习—(1)入门者学习的Java的数据类型】
  8. vue+vuetify项目
  9. python绘制繁花曲线代码_使用python和pygame绘制繁花曲线
  10. 【react】子组件向父组件传值