Hadamard 变换

H.264对帧内或帧间预测的残差(residual)进行DCT变换编码。为了克服浮点运算带来的硬件设计复杂,更重要的是舍入误差造成的编码器和解码器之间不匹配(mismatch)的问题,新标准对DCT的定义做了修改,使得变换仅用整数加减法和移位操作即可实现,这样在不考虑量化影响的情况下,解码端的输出可以准确地恢复编码端的输入。当然这样做的代价是压缩性能的略微下降。此外,该变换是针对4×4块进行的,这也有助于减少块效应。

为了进一步利用图像的空间相关性,在对chroma的预测残差和16×16帧内预测的预测残差进行上述整数DCT变换之后,标准还将每个4×4变换系数块中的DC系数组成2×2或4×4大小的块,进一步做哈达玛(Hadamard)变换。

 

  是Hadamard矩阵成立的充要条件。

1阶和2阶的Hadamard矩阵





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

 

Int SATD (int* diff, int use_hadamard)      

{

  int k, satd = 0, m[16], dd, *d=diff;

 

  if (use_hadamard)

  {

/*===== hadamard transform =====*/

------------------------第一阶段计算------------------------

    m[ 0] = d[ 0] + d[12];

    m[ 4] = d[ 4] + d[ 8];

    m[ 8] = d[ 4] - d[ 8];

    m[12] = d[ 0] - d[12];

    m[ 1] = d[ 1] + d[13];

    m[ 5] = d[ 5] + d[ 9];

    m[ 9] = d[ 5] - d[ 9];

    m[13] = d[ 1] - d[13];

    m[ 2] = d[ 2] + d[14];

    m[ 6] = d[ 6] + d[10];

    m[10] = d[ 6] - d[10];

    m[14] = d[ 2] - d[14];

    m[ 3] = d[ 3] + d[15];

    m[ 7] = d[ 7] + d[11];

    m[11] = d[ 7] - d[11];

    m[15] = d[ 3] - d[15];

   

    d[ 0] = m[ 0] + m[ 4];   -> d[ 0] + d[12]+ d[ 4] + d[ 8]

    d[ 8] = m[ 0] - m[ 4];   -> d[ 0] + d[12]-( d[ 4] + d[ 8])

    d[ 4] = m[ 8] + m[12];  -> d[ 4] - d[ 8]+ d[ 0] - d[12]

    d[12] = m[12] - m[ 8];  -> d[ 0] - d[12] - d[ 4] +d[ 8]

    d[ 1] = m[ 1] + m[ 5];   -> d[ 1] + d[13] + d[ 5] + d[ 9]

    d[ 9] = m[ 1] - m[ 5];  -> d[ 5] + d[ 9] - d[ 1] + d[13]

    d[ 5] = m[ 9] + m[13];  -> d[ 5] - d[ 9] + d[ 1] - d[13]

    d[13] = m[13] - m[ 9];  -> d[ 1] - d[13] - d[ 5] - d[ 9]

    d[ 2] = m[ 2] + m[ 6];  -> d[ 2] + d[14] + d[ 6] + d[10]

    d[10] = m[ 2] - m[ 6];

    d[ 6] = m[10] + m[14];

    d[14] = m[14] - m[10];

    d[ 3] = m[ 3] + m[ 7];

    d[11] = m[ 3] - m[ 7];

    d[ 7] = m[11] + m[15];

    d[15] = m[15] - m[11];

    --------------------第二阶段计算-----------------

    m[ 0] = d[ 0] + d[ 3];

    m[ 1] = d[ 1] + d[ 2];

    m[ 2] = d[ 1] - d[ 2];

    m[ 3] = d[ 0] - d[ 3];

    m[ 4] = d[ 4] + d[ 7];

    m[ 5] = d[ 5] + d[ 6];

    m[ 6] = d[ 5] - d[ 6];

    m[ 7] = d[ 4] - d[ 7];

    m[ 8] = d[ 8] + d[11];

    m[ 9] = d[ 9] + d[10];

    m[10] = d[ 9] - d[10];

    m[11] = d[ 8] - d[11];

    m[12] = d[12] + d[15];

    m[13] = d[13] + d[14];

    m[14] = d[13] - d[14];

    m[15] = d[12] - d[15];

   

    d[ 0] = m[ 0] + m[ 1];

    d[ 1] = m[ 0] - m[ 1];

    d[ 2] = m[ 2] + m[ 3];

    d[ 3] = m[ 3] - m[ 2];

    d[ 4] = m[ 4] + m[ 5];

    d[ 5] = m[ 4] - m[ 5];

    d[ 6] = m[ 6] + m[ 7];

    d[ 7] = m[ 7] - m[ 6];

    d[ 8] = m[ 8] + m[ 9];

    d[ 9] = m[ 8] - m[ 9];

    d[10] = m[10] + m[11];

    d[11] = m[11] - m[10];

    d[12] = m[12] + m[13];

    d[13] = m[12] - m[13];

    d[14] = m[14] + m[15];

    d[15] = m[15] - m[14];

   

    /*===== sum up =====*/

    for (dd=diff[k=0]; k<16; dd=diff[++k])

    {

      satd += (dd < 0 ? -dd : dd);

    }

    satd >>= 1;

  }

  else

  {

    /*===== sum up =====*/

    for (k = 0; k < 16; k++)

    {

      satd += byte_abs [diff [k]];

    }

  }

 

  return satd;

}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值