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;              // no SAD start 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)'做变换前后的向量长度并不相等啊。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS中的块元素,内联元素,内联块元素

块元素,内联元素,内联块元素 元素就是标签&#xff0c;布局中常用的有三种标签&#xff0c;块元素、内联元素、内联块元素&#xff0c;了解这三种元素的特性&#xff0c;才能熟练的进行页面布局。 块元素块元素&#xff0c;也可以称为行元素&#xff0c;布局中常用的标签如&…

django 与 vue 的完美结合

最近接到一个任务&#xff0c;就是用django后端&#xff0c;前段用vue&#xff0c;做一个普通的简单系统&#xff0c;我就是一搞后端的&#xff0c;听到vue也是比较震惊&#xff0c;之前压根没接触过vue。看了vue的一些文档&#xff0c;还有一些项目&#xff0c;先说一下django…

东芝确定半导体重组计划:保留闪存其他全卖

会计丑闻给日本东芝公司的业绩带来严重影响&#xff0c;为了提高盈利&#xff0c;东芝正在对旗下的半导体、个人电脑、白色家电等业务进行一次重大重组。据日经新闻1月23日报道&#xff0c;东芝已经正式制定了芯片业务重组的详细计划&#xff0c;除了占据优势的闪存芯片之外&am…

python画两条曲线图_python绘制多个曲线的折线图

这篇文章利用的是matplotlib.pyplot.plot的工具来绘制折线图&#xff0c;这里先给出一个段代码和结果图&#xff1a; # -*- coding: UTF-8 -*- import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt #这里导入你自己的数据 #...... #...... #x_axix&a…

5.19汇总

int block_x 8*(b8 & 0x01)4*(b4 & 0x01);int block_y 8*(b8 >> 1)4*(b4 >> 1);请问下老大 这两句定义是什么意思啊&#xff1f; 带些值进去算一下就知道了 b8 0 1 2 3b4 0 1 2 3 A&#xff1a;0 ........Er…

oracle 截取字指定的字符串

过滤指定的字符串,一字符串有重复的数据内容,所以需要去掉重复的内容,subst()截取 起止下标;instr()获取终止下标位置 例如:substr(p.address, 0, instr(p.address, -, 1, 1)-1) ); case when length(substr(p.address, 0, instr(p.address, -, 1, 1)-1) ) 13 then substr(sub…

[django]django模型中auto_now和auto_now_add

示例: update_time models.DateTimeField(更新时间, defaulttimezone.now) create_time models.DateTimeField(创建时间, auto_now_addTrue) auto_now无论是你添加还是修改对象&#xff0c;时间为你添加或者修改的时间。 auto_now_add为添加时的时间&#xff0c;更新对象时不…

2014-7-29-阿里电面-第一轮

等了好久&#xff0c;以为简历要挂了&#xff0c;今天最终打来了。面试过程中手抖嘴抖有木有&#xff01; 1、经经常使用的集合类。我回到ArrayList、LinkedList、HashMap&#xff0c;接着问ArrayList、LinkedList的差别&#xff0c;以及分别的适用范围。看了Java集合类基本上是…

数据分级分类实施指南_运营商行业数据安全治理实践

建立组织构建大数据安全保障组一、大数据安全保障工作组职责 1、负责制定大数据信息安全策略&#xff0c;明确信息安全目标。 2、组织相关平台负责人定期召开信息安全会议。 3、负责客户数据安全突发事件应急方案实施和大数据信息系统日常安全运行管理的组织协调及决策工作。 4…

CSS中的定位

定位 关于定位我们可以使用css的position属性来设置元素的定位类型&#xff0c;postion的设置项如下&#xff1a; relative 生成相对定位元素&#xff0c;元素所占据的文档流的位置不变&#xff0c;元素本身相对文档流的位置进行偏移absolute 生成绝对定位元素&#xff0c;元…

servlet中中文正常显示,mysql数据库手动插入中文正常显示,servlet向mysql中插入中文显示乱码...

作者&#xff1a;http://5563447.blog.51cto.com/5553447/1422627 问题是&#xff1a;就是POST请求提交表单数据给servlet,通过JDBC插入Mysql,出现中文乱码。 解决方式&#xff1a;在url后面加这句 ?useUnicodetrue&characterEncodingutf-8 我的项目&#xff1a; 结果&am…

rtp问题引领汇总

视频网络传输一定要用rtp吗&#xff1f; RTP/RTCP有一套很好的反馈机制&#xff0c;通过其可以估算网络状况&#xff0c;然后在编码端进行调整&#xff0c;如网络繁忙时适当的降低画面质量&#xff0c;减小码率等&#xff0c;主要是想通过RTP/RTCP协议实现QoS&#xff01;同时…

Django的信号机制详解

Django的信号机制详解 Django提供一种信号机制。其实就是观察者模式&#xff0c;又叫发布-订阅(Publish/Subscribe) 。当发生一些动作的时候&#xff0c;发出信号&#xff0c;然后监听了这个信号的函数就会执行。 Django内置了一些信号&#xff0c;比如&#xff1a; django.…

垃圾回收算法_垃圾回收算法有哪些

垃圾检测通常通过建立一个根对象的集合以及建立一个从这些根对象开始能够触及的对象集合来实现。如果正在执行的程序可以访问到根对象和某个对象之间存在引用路径&#xff0c;这个对象就是可触及的。对于程序来说&#xff0c;根对象总是可以访问的。从这些根对象开始&#xff0…

不错的电子书下载网站

为什么80%的码农都做不了架构师&#xff1f;>>> www.jb51.net 电子书质量不错,虽然是扫描版的,但是都是高清的. vdisk.weibo.com 网盘, 内容很多! 转载于:https://my.oschina.net/GMT/blog/1188971

GeoHash核心原理解析

原文地址&#xff1a;http://www.cnblogs.com/LBSer/p/3310455.html geohash for php&#xff1a;附件下载geohash.tar.gz 引子 机机是个好动又好学的孩子&#xff0c;平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西。某一天机机到北海公园游玩&#xff0c;肚肚饿了&am…

[转载]流行视频格式讲解

*. MPEG/.MPG/.DAT MPEG也是Motion Picture Experts Group 的缩写。这类格式包括了 MPEG-1, MPEG-2 和 MPEG-4在内的多种视频格式。MPEG-1相信是大家接触得最多的了&#xff0c;因为目前其正在被广泛地应用在 VCD 的制作和一些视频片段下载的网络应用上面&#xff0c;大部分的…

Ajax相关介绍

ajax是什么? AJAX 是与服务器交换数据并更新部分网页的艺术&#xff0c;在不重新加载整个页面的情况下。 AJAX 指异步 JavaScript 及 XML&#xff08;Asynchronous JavaScript And XML&#xff09;。 AJAX 是一种在 2005 年由 Google 推广开来的编程模式。 AJAX 不是一种新的…

解决Ubuntu中文件管理器死掉的情况

有时会遇到Ubuntu文件管理器死掉的情况&#xff0c;怎么点击都没有反应&#xff0c;这时只需在终端上运行 ps -A | grep nautilus&#xff0c; 查找文件管理器nautilus对应的pid,然后sudokillpid就可以关闭文件管理器进程&#xff0c;随便点击一个文件夹就可以重启文件管理器了…

element table 怎么知道点击的是第几行_el-data-table, 让CRUD更简单??

基于Vue2.x, element-ui 2.x&#xff0c;以及开源组件el-form-renderer封装了一个业务组件el-data-table&#xff0c;已在github开源&#xff0c;其目标是&#xff1a;makes restful api crud easily 特点&#xff1a;1. 使用axios自动发送请求2.自带新增/修改/删除逻辑(默认新…