原地址:http://blog.sina.com.cn/s/blog_6dcd52870100yl2v.html

        http://zh.wikipedia.org/wiki/%E9%98%BF%E8%BE%BE%E9%A9%AC%E5%8F%98%E6%8D%A2

哈达玛(Hadamard)矩阵是由+1和-1元素构成的正交方阵。所谓正交方阵,指它的任意两行(或两列)都是正交的。把行(或列)看作一个函数,任意两行(或两列)都是正交的 H2n=[Hn Hn;Hn -Hn].在现在的视频编码标准中,阿达马变换多被用来计算SATD(一种视频残差信号大小的衡量)。

变换矩阵

H.264中使用了4阶和8阶的阿达马变换来计算SATD,其变换矩阵为:

SATD计算方法

当计算4x4块的SATD时,先使用下面的方法进行二维的阿达马变换:
然后计算所有系数绝对值之和并归一化。
类似的,当计算8x8块的SATD时,先使用下面的方法进行二维的Hadamard变换:
然后计算所有系数绝对值之和并归一化。

构建阿达马变换


阿达马变换转换主要型式为  点的转换矩阵,其最小单位矩阵为 2x2 的阿达马变换矩阵,以下分别为二点、四点与如何产生  点的阿达马变换转换步骤。
  • 二点阿达马变换转换:
  • 四点阿达马变换转换:
  • 产生  点阿达马变换的步骤:
步骤一: 
步骤二: 根据正负号次序 (Sign change,正负号改变次数) 将矩阵 (Matrix) 内的列向量座顺序上的重新排列。

范例


优缺点比较

优点

  • 仅需实数运算 (Real operation) 。
  • 不需乘法运算 (No multiplication) ,仅有加减法运算。
  • 有部分性质类似于离散傅立叶变换 (Discrete fourier transform) 。
  • 顺向转换 (Forward transform) 与反向转换 (Inverse transform ) 型式为相似式。
其中  分别都为行向量 (Column vector) 。

缺点

  • 其收敛速度较离散余弦变换慢,因此对于频谱分析的效果较差。
  • 其加减法量较离散傅立叶变换、离散余弦变换多。

Hadamard变换

   for (j=0;j<16;j)
   {
       for (i=0;i<16;i)
       {
          M1[ i ][j]=imgY_org[img->opix_y+j][img->opix_x+i]-img->mprr_2[k][j][ i ];       

          //计算当前宏块残差块
          M0[i%4][i/4][j%4][j/4]=M1[ i ][j];
       }
   }
   current_intra_sad_2=0;              // noSADstart handicap here
   for (jj=0;jj<4;jj)
   {
     for (ii=0;ii<4;ii)
     {
      for (j=0;j<4;j)                                                      第一次一维Hadamard变换
      {                               
         M3[0]=M0[0][ii][j][jj]+M0[3][ii][j][jj];
         M3[1]=M0[1][ii][j][jj]+M0[2][ii][j][jj];
         M3[2]=M0[1][ii][j][jj]-M0[2][ii][j][jj];
         M3[3]=M0[0][ii][j][jj]-M0[3][ii][j][jj];
         M0[0][ii][j][jj]=M3[0]+M3[1];                     
         M0[2][ii][j][jj]=M3[0]-M3[1];                     
         M0[1][ii][j][jj]=M3[2]+M3[3];                     
         M0[3][ii][j][jj]=M3[3]-M3[2];                     
      }                                                                                    
      for (i=0;i<4;i)                                                       
      {                                                                                    
         M3[0]=M0[ i ][ii][0][jj]+M0[ i ][ii][3][jj];
         M3[1]=M0[ i ][ii][1][jj]+M0[ i ][ii][2][jj];
         M3[2]=M0[ i ][ii][1][jj]-M0[ i ][ii][2][jj];
         M3[3]=M0[ i ][ii][0][jj]-M0[ i ][ii][3][jj];
         第二次一维Hadamard变换
         M0[ i ][ii][0][jj]=M3[0]+M3[1];                     
         M0[ i ][ii][2][jj]=M3[0]-M3[1];                     
         M0[ i ][ii][1][jj]=M3[2]+M3[3];                     
         M0[ i ][ii][3][jj]=M3[3]-M3[2];                     
         for (j=0;j<4;j)                                             
         if ((i+j)!=0)                                                       
         current_intra_sad_2 += abs(M0[ i ][ii][j][jj]);      变换后的AC残差值取绝对值求和作为代价
      }                                                                                    
     }
   }
   for (j=0;j<4;j)
   for (i=0;i<4;i)
   M4[ i ][j]=M0[0][ i ][0][j]/4;
   // Hadamard of DC koeff
   for (j=0;j<4;j)     后面两个for循环对当前宏块的DC残差进行Hadamard变换并将变换后的值取绝对值求和作为代价
   {
      M3[0]=M4[0][j]+M4[3][j];
      M3[1]=M4[1][j]+M4[2][j];
      M3[2]=M4[1][j]-M4[2][j];
      M3[3]=M4[0][j]-M4[3][j];
      M4[0][j]=M3[0]+M3[1];
      M4[2][j]=M3[0]-M3[1];
      M4[1][j]=M3[2]+M3[3];
      M4[3][j]=M3[3]-M3[2];
   }
   for (i=0;i<4;i)
   {
      M3[0]=M4[ i ][0]+M4[ i ][3];
      M3[1]=M4[ i ][1]+M4[ i ][2];
      M3[2]=M4[ i ][1]-M4[ i ][2];
      M3[3]=M4[ i ][0]-M4[ i ][3];
      M4[ i ][0]=M3[0]+M3[1];
      M4[ i ][2]=M3[0]-M3[1];
      M4[ i ][1]=M3[2]+M3[3];
      M4[ i ][3]=M3[3]-M3[2];
      for (j=0;j<4;j)
      current_intra_sad_2 += abs(M4[ i ][j]);
    }
    if(current_intra_sad_2 < best_intra_sad2)
    {
      best_intra_sad2=current_intra_sad_2;
      *intra_mode = k; // update best intra mode
     }
    }
  }
   best_intra_sad2 = best_intra_sad2/2;
   return best_intra_sad2;
}
以上是源程序里的一段,intra_16*16并不是计算SAD值,而是计算SATD。
其中M1中放的是宏块的残差,M0也是,不过为了下面计算HADAMARD变换方便,他表示成M0[4][4][4][4]的形式,前2个[4][4]表示8X8块坐标,后2个[4][4]表示一个8X8里的4X4块坐标。
程序先对残差进行HADAMARD变换,然后把所有的DC分量提出来,再对DC分量做HADAMARD变换,
最后得到的是SATD。
有两点不明白,谁知道的解释一下:
1 在提取DC分量时为什么要除以4?
2 最后的best_intra_sad2 为什么要除以2?

这主要是由于SATD变换不是归一化矩阵,变换后的系数值幅值增加,因此要相应的/2和/4

hadamard 变换本身就有一个 /2 的操作,因此每次变换都要对所有系数进行 /2。而 find_sad_16x16 函数执行了两次 hadamard 变换:首先对 256 个系数进行一次,其次对所有 DC 系数再做一次,因此对 DC 系数应该 /4,而对 AC 系数应该 /2。find_sad_16x16 函数中的:M4[ i ][j]=M0[0][ i ][0][j]/4;就是对 DC 系数 /4,而最后的:best_intra_sad2 = best_intra_sad2/2;可以认为是对 AC 系数的变相 /2。但这里相当于是对所有系数 /2,所以 DC 系数多了一次 /2。这个多的一次就不知道原因了。

264乐园群里探讨过这个问题。对于hadamard变换的/2已经有了结论。但是对DC系数多除的那一次2,目前尚未找到根据。
4阶hadamard变换的定义式本身就是包含了这个/2的。可以见http://en.wikipedia.org/wiki/Hadamard_transform。这里再多解释一点
假设hadamard变换没有/2, 变换矩阵为:
1  1   1  1
1 -1   1 -1
1  1  -1 -1
1 -1  -1  1
这时对一个列向量v = (1, 1, 1, 1)'做变换,即用变换矩阵左乘列向量v,得到的变换后向量v' = (4, 0, 0, 0)'。
现在观察v和v',在欧氏空间中,对一个向量的“大小”的衡量就是其长度,通过计算内积得到。那么
len(v)   = sqrt( 1^2 + 1^2 + 1^2 + 1^2) = 2
len(v') = sqrt( 4^2 + 0^2 + 0^2 + 0^2) = 4
由此可见如果没有那个/2,变换前后,该向量的长度发生了变化。这样的变换是违背正交变换的定义的。

所以,作为正交变换的hadamard变换,必须要有这个/2的归一化。

A:推而广之,整数 DCT 变换在变换前后向量的长度也发生了变化,为什么没有除以 2 呢?

DCT变换(非整数)也是归一化的整数变换也是正交变换,所以也一定会满足归一化的。firstime是不是忘记把scaling matrix考虑进来了啊。

按照毕厚杰书上 113 页,变换矩阵为公式 6.15(这个时候 scaling matrix 还没分离出来吧?):
a   a   a   a
b   c -c -b
a -a -a   a
c -b   b -c
其中 a = 1/2,b = (2/5)^0.5。这个矩阵对列向量v = (1, 1, 1, 1)'做变换前后的向量长度并不相等啊。

才发现毕厚杰书上的DCT变换矩阵是错的。。。。第二行第四列应该是-b
应该是
a  a  a  a
b  c -c  -b
a -a -a  a
c -b  b -c

Hadamard变换相关推荐

  1. 图像处理之Hadamard变换和Hough变换

    一.Hadamard变换 1.基本原理 Hadamard变换相当于在原来的图像矩阵左右分别乘以一一个矩阵,这两个矩阵都是正交矩阵,称为Hadamard变换矩阵.Hadamard变换矩阵中所有的元素都是 ...

  2. MATLAB对图形做Hadamard变换和离散余弦变换

    cameraman=imread('cameraman.tif'); H=hadamard(256); %hadamad矩阵 cameraman=double(cameraman)/255; %数据类 ...

  3. matlab hadamard(哈达玛变换)变换

    close all;clear all;clc; %对图像进行Hadamard变换 I=imread('peppers.png'); I=rgb2gray(I); I=im2double(I); h1 ...

  4. matlab怎么求hadamard,hadamard matlab

    3.图像Hadamard变换 数字图像处理 ? Matlab没有提供图像Hadamard变换功能,不过 提供了求Hadamard变换矩阵的功能.例如使用 命令hadamard(8)能够得到下面[8 8 ...

  5. 哈达玛变换的应用SATD、SAD等匹配算法

    参考:新一代高效视频编码 H.265/HEVC:原理.标准与实现. 转载:http://xiyou07127.blog.163.com/blog/static/11349879220125241070 ...

  6. 视频编解码 — DCT变换和量化

    目录 视频编码流程 DCT变换 Hadamard变换 量化 H264中的DCT变换和量化 H264各模式的DCT变换和量化过程 1.亮度16x16帧内预测块 2,其它模式亮度块 3,色度块 小结 视频 ...

  7. matlab 沃尔什矩阵,压缩感知——沃尔什-哈达玛(WHT)变换与逆变换的Matlab代码实现...

    沃尔什-哈达玛变换(Walsh-Hadmard Transform,WHT),是一种典型的非正弦函数变换,采用正交直角函数作为基函数,具有与傅里叶函数类似的性质,图像数据越是均匀分布,经过沃尔什-哈达 ...

  8. matlab 沃尔什,Walsh-Hadamard 变换

    Walsh-Hadamard 变换 Walsh-Hadamard 变换是一种将信号分解成一组基函数的非正弦类正交变换方法.这些基函数是 Walsh 函数,它们是值为 +1 或 –1 的矩形波或方波.W ...

  9. Hadamard Transform

    Hadamard 变换在量子逻辑门中提过,只不过那时是单量子的Hadamard门, 负责把|1〉变成 |−〉|,|0〉变成|+〉. 对于多量子逻辑门,其实说过一句,是单量子逻辑门的张量积. 如果想要有 ...

最新文章

  1. 批处理系统服务监控器[超牛B]
  2. html输入完账号密码才能跳转,HTML输入字段跳转
  3. java linearlayout_LinearLayout属性用法和源码分析
  4. LeetCode 103. 二叉树的锯齿形层次遍历(BFS / 双栈)
  5. xshell怎么让程序后台运行_使程序在Linux下后台运行
  6. C++|Qt工作笔记-Windows平台下的句柄与Qt中QWindow::winId()以及 QPlatformWindow::handle的区别与联系
  7. c语言加减乘除计算程序,求一个计算加减乘除的C语言程序
  8. leetcode_sql_1,176,177
  9. AD15如何更新原理图库
  10. 回归预测 | MATLAB实现GLM广义线性模型数据回归预测
  11. 5G风起,CDN边缘计算将乘风破浪
  12. ZUI框架加上Flex布局构建登录后的主页
  13. Kali 编译 Android 源码
  14. 统一身份认证子系统界面设计与实现
  15. 培训机构管理信息系统设计与开发(一)
  16. Redis--布隆过滤器--使用/原理/实例
  17. 用户存续期价值评估CLV(三) Gamma-Gamma模型 Python模拟
  18. Unity 亮晶晶✨的粒子特效
  19. 用CSS实现段落前面缩进两个字
  20. 怎么把PDF转换成CAD文件呢?分享两种转换小技巧

热门文章

  1. php你们想不到的强大,找电影的好网站,再也不用担心下不到好电影了!
  2. 单片机adc0809模数转换实验c语言,单片机C语言程序设计:ADC0809 数模转换与显示...
  3. 多端合一小程序商城制作系统源码 后台自由DIY+全开源可二开
  4. DC/DC直流12V升400V、12V升350V高压电源模块
  5. CMake命令:find_package、make instal、make --build .、CMAKE_PREFIX_PATH、add_compile_options、set_property
  6. 快速分析出百世快运中转延误的单号,并导出表格
  7. 7-4 藏头诗 (15 分)
  8. java编写换酒问题,ASP空瓶换酒递归算法题目
  9. Compose Preview 的 UX 设计之旅
  10. 华硕的电脑装linux系统下载,华硕电脑无法安装Ubuntu 10.10以后版本解决