当前位置:   article > 正文

HEVC变换编码实现代码详解_hevc对图像编码代码

hevc对图像编码代码

作者:66

有关变换模块

    先推荐一个特别好的博主,可以参考他分析的HEVC,收获颇丰,感谢前辈。

     推荐链接:http://blog.csdn.net/HEVC_CJL/article/category/1283611/3

    经预测后的残差数据,在空域上是存在大量冗余的,包含较多的平坦区域和内容变化缓慢的区域,相邻的相近像素差距很小,经适当的变换,可以将空域的分散分布转换到频域的集中分布。再结合Z扫描、熵编码等可以进行有效压缩。

  变换到频域的方法有许多种,DCT变换形式与输入信号无关且存在快速实现算法,另外DCT可以将能量集中到左上角(之前看理论时从网上知道的,不明白缘由,有时间研究一下傅里叶变换在图形处理方面的基础)。

H.265中,为了适应不同预测方式下的残差分布情况,还引入了离散余弦变换DST

理论部分直接网上搜索DCT原理及特点,涉及到较多的数字信号处理内容,这里不作赘述。

DCT的实现:

不管是h.264h.265中,都为了提高变换速度,避免实数运算,对DCT进行了调整。h.264中,将DCT阵中调整为12,计算过程中仅需要加法、移位等操作。为近似为12所损失的精度较高(相对于h.265)

h.265中,将DCT矩阵中的元素全部放大了64√N倍(N为变换块大小),放大后为了保持正交性作了微量调整。先看一下h.265下的DCT变换矩阵,有481632大小的,这里放下48大小的。

const Short g_aiT4[4][4] =

{

  { 64, 64, 64, 64},

  { 83, 36,-36,-83},

  { 64,-64,-64, 64},

  { 36,-83, 83,-36}

};

const Short g_aiT8[8][8] =

{

  { 64, 64, 64, 64, 64, 64, 64, 64},

  { 89, 75, 50, 18,-18,-50,-75,-89},

  { 83, 36,-36,-83,-83,-36, 36, 83},

  { 75,-18,-89,-50, 50, 89, 18,-75},

  { 64,-64,-64, 64, 64,-64,-64, 64},

  { 50,-89, 18, 75,-75,-18, 89,-50},

  { 36,-83, 83,-36,-36, 83,-83, 36},

  { 18,-50, 75,-89, 89,-75, 50,-18}

};

这里变换阵是有特点的,奇数行偶对称,偶数行奇对称。另外,8x8阵中的0246行前四个元素组成了4x4矩阵。因此设计有统一形式的DCT蝶形算法。

整数DCT公式:


正常两个4x4矩阵相乘,需要64次乘法,但DCT矩阵中对称,每行中有一半的乘法是重复计算的,蝶形就是将他们去掉,另外代码中计算用到了简单的转置,在此稍作提示:

整数DST公式:

仅适用于4x4变换块

其中DST矩阵为:

DST矩阵如下

{ 29, 55, 74, 84

  74, 74,  0,-74

  84,-29,-74, 55

  55,-84, 74,-29}

//注意其中29 + 55 = 84,下面代码计算过程中用到了这点。

DCT变换(16x1632x32就不贴了,类似的)

  1. /** 4x4 forward transform implemented using partial butterfly structure (1D)
  2. * \param src input data (residual)
  3. * \param dst output data (transform coefficients)
  4. * \param shift specifies right shift after 1D transform
  5. */
  6. void partialButterfly4(Short *src,Short *dst,Int shift, Int line)
  7. {
  8. Int j;
  9. Int E[2],O[2];
  10. Int add = 1<<(shift-1);
  11. for (j=0; j<line; j++)//利用变换阵偶数行奇对称,奇数行偶对称的特性,将对称部分的两次乘合并为一次。乘法降低一半
  12. {
  13. /* E and O */
  14. E[0] = src[0] + src[3];
  15. O[0] = src[0] - src[3];
  16. E[1] = src[1] + src[2];
  17. O[1] = src[1] - src[2];
  18. dst[0] = (g_aiT4[0][0]*E[0] + g_aiT4[0][1]*E[1] + add)>>shift;
  19. dst[2*line] = (g_aiT4[2][0]*E[0] + g_aiT4[2][1]*E[1] + add)>>shift;
  20. dst[line] = (g_aiT4[1][0]*O[0] + g_aiT4[1][1]*O[1] + add)>>shift;
  21. dst[3*line] = (g_aiT4[3][0]*O[0] + g_aiT4[3][1]*O[1] + add)>>shift;
  22. src += 4;//此时src按转置阵参与计算,本为g_aiT4行乘src的列,这里写的是g_aiT4的行乘src的行
  23. dst ++;
  24. }
  25. }
  26. //8x8
  27. void partialButterfly8(Short *src,Short *dst,Int shift, Int line)
  28. {
  29. Int j,k;
  30. Int E[4],O[4];
  31. Int EE[2],EO[2];
  32. Int add = 1<<(shift-1);
  33. for (j=0; j<line; j++)
  34. {
  35. /* E and O*/
  36. for (k=0;k<4;k++)
  37. {
  38. E[k] = src[k] + src[7-k];
  39. O[k] = src[k] - src[7-k];
  40. }
  41. /* EE and EO */
  42. EE[0] = E[0] + E[3];//类似4x4
  43. EO[0] = E[0] - E[3];
  44. EE[1] = E[1] + E[2];
  45. EO[1] = E[1] - E[2];
  46. dst[0] = (g_aiT8[0][0]*EE[0] + g_aiT8[0][1]*EE[1] + add)>>shift;
  47. dst[4*line] = (g_aiT8[4][0]*EE[0] + g_aiT8[4][1]*EE[1] + add)>>shift;
  48. dst[2*line] = (g_aiT8[2][0]*EO[0] + g_aiT8[2][1]*EO[1] + add)>>shift;
  49. dst[6*line] = (g_aiT8[6][0]*EO[0] + g_aiT8[6][1]*EO[1] + add)>>shift;
  50. dst[line] = (g_aiT8[1][0]*O[0] + g_aiT8[1][1]*O[1] + g_aiT8[1][2]*O[2] + g_aiT8[1][3]*O[3] + add)>>shift;
  51. dst[3*line] = (g_aiT8[3][0]*O[0] + g_aiT8[3][1]*O[1] + g_aiT8[3][2]*O[2] + g_aiT8[3][3]*O[3] + add)>>shift;
  52. dst[5*line] = (g_aiT8[5][0]*O[0] + g_aiT8[5][1]*O[1] + g_aiT8[5][2]*O[2] + g_aiT8[5][3]*O[3] + add)>>shift;
  53. dst[7*line] = (g_aiT8[7][0]*O[0] + g_aiT8[7][1]*O[1] + g_aiT8[7][2]*O[2] + g_aiT8[7][3]*O[3] + add)>>shift;
  54. src += 8;
  55. dst ++;
  56. }
  57. }


DST变换:

  1. // Fast DST Algorithm. Full matrix multiplication for DST and Fast DST algorithm
  2. // give identical results
  3. //DST矩阵如下
  4. //{ 29, 55, 74, 84
  5. // 74, 74, 0,-74
  6. // 84,-29,-74, 55
  7. // 55,-84, 74,-29}
  8. //注意其中29 + 55 = 84,下面代码计算过程中利用了这点
  9. void fastForwardDst(Short *block,Short *coeff,Int shift) // input block, output coeff
  10. {
  11. Int i, c[4];
  12. Int rnd_factor = 1<<(shift-1);
  13. for (i=0; i<4; i++)
  14. {
  15. // Intermediate Variables
  16. c[0] = block[4*i+0] + block[4*i+3];
  17. c[1] = block[4*i+1] + block[4*i+3];
  18. c[2] = block[4*i+0] - block[4*i+1];
  19. c[3] = 74* block[4*i+2];
  20. coeff[ i] = ( 29 * c[0] + 55 * c[1] + c[3] + rnd_factor ) >> shift;
  21. coeff[ 4+i] = ( 74 * (block[4*i+0]+ block[4*i+1] - block[4*i+3]) + rnd_factor ) >> shift;
  22. coeff[ 8+i] = ( 29 * c[2] + 55 * c[0] - c[3] + rnd_factor ) >> shift;
  23. coeff[12+i] = ( 55 * c[2] - 29 * c[1] + c[3] + rnd_factor ) >> shift;
  24. }
  25. }


(转载请注明出处)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/735641
推荐阅读
相关标签
  

闽ICP备14008679号