H266/VVC 变换编码中大尺寸变换块高频系数置零技术

大尺寸变换块高频系数置零

  1. 近年来视频技术有了飞速的变化,视频的分辨率从 1080P 过渡到 4K,并逐渐向发展 8K。为了适应日益增长的视频分辨率,新的编码技术采用了更大尺寸的变换块来提高编码效率,最大变换块大小变成 64x64。变换块的增大对高分辨率的视频图像非常有用,但由此引入的计算复杂度、存储带宽及空间的要求也不可忽略。同时,在大变换块的计算完成后,高频系数都基本趋于 0,在解码中对图像质量的影响不大。为减小计算的复杂度,VVC 针对 64 宽高的变换块进行了高频置 0 的操作,仅保留低频的系数部分,可大大减小变换操作的计算复杂度和存储带宽及空间。
  2. 在 VVC 中,最大的变换块被限制为 64x64,由于存在 MTT 分割,可能存在矩形的变换块,因此对于在变换块中高频置 0 条件为:
    • 当变换块的宽高均等于 64,或者宽或高等于 64 时,进行高频置 0 操作,仅保留低频系数部分。
  3. 如图下图所示,变换块大小为 MxN,当 M、N 均等于 64 时,保留左方 32 列 的变换系数,右方 32 列变换系数置 0;当变换块为矩形块,M>N 且 M 等于 64 时,保留左方 32 列的变换系数,右方 32 列变换系数置 0;当 M<N 且 N 等于 64 时,保留上方 32 行变换系数,下方 32 行变换系数置 0。
    在这里插入图片描述
  4. 当 transform skip 模式使用时,所有的变换块均不执行高频置 0 操作,包括宽或高等于 64 的情况。
  5. 用户可在 sps 语法中修改最大变换块的大小,这样编码器可根据自身资源情况灵活选择 32 或 64 的最大变换块。
  6. 高频变换系数置 0 的操作大大减少了变换块的计算复杂度、存储带宽及空间的使用,同时带来的编码损失影响可忽略。
  7. 在 2020 年 1 月的 JVET-Q2002[Algorithm description for Versatile Video Coding and Test Model 8 (VTM 8)] 提案中对 MTS 技术进行了总结描述。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  8. 在 VVenC 编码器中 TrQuant.cpp 文件中transformNxN函数用来对残差数据进行变换的核心函数。
void TrQuant::transformNxN(TransformUnit &tu, const ComponentID compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr)
{
        CodingStructure &cs = *tu.cs;
  const CompArea& rect      = tu.blocks[compID];
  const uint32_t uiWidth        = rect.width;
  const uint32_t uiHeight       = rect.height;

  const CPelBuf resiBuf     = cs.getResiBuf(rect);

  if( tu.noResidual )
  {
    uiAbsSum = 0;
    TU::setCbfAtDepth( tu, compID, tu.depth, uiAbsSum > 0 );
    return;
  }
  if (tu.cu->bdpcmM[toChannelType(compID)])
  {
    tu.mtsIdx[compID] = MTS_SKIP;
  }

  uiAbsSum = 0;
  CHECK( cs.sps->getMaxTbSize() < uiWidth, "Unsupported transformation size" );

  CoeffBuf tempCoeff(loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_plTempCoeff, rect);
  if (!loadTr)
  {
    DTRACE_PEL_BUF( D_RESIDUALS, resiBuf, tu, tu.cu->predMode, compID );
    if (tu.mtsIdx[compID] == MTS_SKIP)
    {
      xTransformSkip(tu, compID, resiBuf, tempCoeff.buf);
    }
    else
    {
      xT(tu, compID, resiBuf, tempCoeff, uiWidth, uiHeight);
    }
  }
  if (cs.sps->LFNST)
  {
    xFwdLfnst(tu, compID, loadTr);
  }
  DTRACE_COEFF_BUF( D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID );

  xQuant( tu, compID, tempCoeff, uiAbsSum, cQP, ctx );

  DTRACE_COEFF_BUF( D_TCOEFF, tu.getCoeffs( compID ), tu, tu.cu->predMode, compID );

  // set coded block flag (CBF)
  TU::setCbfAtDepth (tu, compID, tu.depth, uiAbsSum > 0);
}
  1. 在 VVenC 编码器中 TrQuant.cpp 文件中 xT函数用是进行主变换的函数,里面有关于大尺寸块高频置零的操作逻辑。
void TrQuant::xT( const TransformUnit& tu, const ComponentID compID, const CPelBuf& resi, CoeffBuf& dstCoeff, const int width, const int height )
{
  PROFILER_SCOPE_AND_STAGE( 1, _TPROF, P_TRAFO );

  const unsigned maxLog2TrDynamicRange  = tu.cs->sps->getMaxLog2TrDynamicRange( toChannelType( compID ) );
  const unsigned bitDepth               = tu.cs->sps->bitDepths[               toChannelType( compID ) ];
  const int      TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_FORWARD];
  const uint32_t transformWidthIndex    = Log2(width ) - 1;  // nLog2WidthMinus1, since transform start from 2-point
  const uint32_t transformHeightIndex   = Log2(height) - 1;  // nLog2HeightMinus1, since transform start from 2-point

  int trTypeHor = DCT2;
  int trTypeVer = DCT2;

  xSetTrTypes( tu, compID, width, height, trTypeHor, trTypeVer );

  int  skipWidth  = ( trTypeHor != DCT2 && width  == 32 ) ? 16 : width  > JVET_C0024_ZERO_OUT_TH ? width  - JVET_C0024_ZERO_OUT_TH : 0;
  int  skipHeight = ( trTypeVer != DCT2 && height == 32 ) ? 16 : height > JVET_C0024_ZERO_OUT_TH ? height - JVET_C0024_ZERO_OUT_TH : 0;

  if( tu.cu->lfnstIdx )
  {
    if ((width == 4 && height > 4) || (width > 4 && height == 4))
    {
      skipWidth  = width - 4;
      skipHeight = height - 4;
    }
    else if ((width >= 8 && height >= 8))
    {
      skipWidth  = width - 8;
      skipHeight = height - 8;
    }
  }

  TCoeff* block = m_blk;
  TCoeff* tmp   = m_tmp;

  const Pel* resiBuf    = resi.buf;
  const int  resiStride = resi.stride;

#if ENABLE_SIMD_TRAFO
  if( width & 3 )
#endif
  {
    for( int y = 0; y < height; y++ )
    {
      for( int x = 0; x < width; x++ )
      {
        block[( y * width ) + x] = resiBuf[( y * resiStride ) + x];
      }
    }
  }
#if ENABLE_SIMD_TRAFO
  else if( width & 7 )
  {
    g_tCoeffOps.cpyCoeff4( resiBuf, resiStride, block, width, height );
  }
  else
  {
    g_tCoeffOps.cpyCoeff8( resiBuf, resiStride, block, width, height );
  }
#endif //ENABLE_SIMD_TRAFO

  if (width > 1 && height > 1)
  {
    const int shift_1st = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
    const int shift_2nd =  (Log2(height))            + TRANSFORM_MATRIX_SHIFT;
    CHECK( shift_1st < 0, "Negative shift" );
    CHECK( shift_2nd < 0, "Negative shift" );
    fastFwdTrans[trTypeHor][transformWidthIndex](block, tmp, shift_1st, height, 0, skipWidth);
    fastFwdTrans[trTypeVer][transformHeightIndex](tmp, dstCoeff.buf, shift_2nd, width, skipWidth, skipHeight);
  }
  else if (height == 1)   // 1-D horizontal transform
  {
    const int shift = ((Log2(width )) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
    CHECK( shift < 0, "Negative shift" );
    fastFwdTrans[trTypeHor][transformWidthIndex](block, dstCoeff.buf, shift, 1, 0, skipWidth);
  }
  else   // if (iWidth == 1) //1-D vertical transform
  {
    int shift = ((floorLog2(height)) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange;
    CHECK(shift < 0, "Negative shift");
    CHECKD((transformHeightIndex < 0), "There is a problem with the height.");
    fastFwdTrans[trTypeVer][transformHeightIndex](block, dstCoeff.buf, shift, 1, 0, skipHeight);
  }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5989.数字接龙

5989.数字接龙 小蓝最近迷上了一款名为《数字接龙》的迷宫游戏&#xff0c;游戏在一个大小为 NN 的格子棋盘上展开&#xff0c;其中每一个格子处都有着一个 0…K−10…K−1 之间的整数。 游戏规则如下&#xff1a; 从左上角 (0,0) 处出发&#xff0c;目标是到达右下角 (N−1…

Titans: 学习在测试时记忆 - 论文解读与总结

论文地址&#xff1a;https://arxiv.org/pdf/2501.00663v1 本文介绍了一篇由 Google Research 发表的关于新型神经网络架构 Titans 的论文&#xff0c;该架构旨在解决传统 Transformer 在处理长序列时的局限性。以下是对论文的详细解读&#xff0c;并结合原文图片进行说明&…

账号IP属地:依据手机号还是网络环境?

在数字化生活中&#xff0c;账号的IP属地信息往往成为我们关注的一个焦点。无论是出于安全考虑&#xff0c;还是为了满足某些特定服务的需求&#xff0c;了解账号IP属地的确定方式都显得尤为重要。那么&#xff0c;账号IP属地根据手机号还是网络来确定的呢&#xff1f;本文将深…

微信小程序实现自定义日历功能

文章目录 1. 创建日历组件实现步骤&#xff1a;2. 代码实现过程3. 实现效果图4. 关于作者其它项目视频教程介绍 1. 创建日历组件实现步骤&#xff1a; 创建日历组件&#xff1a;首先&#xff0c;你需要创建一个日历组件&#xff0c;包含显示日期的逻辑。样式设计&#xff1a;为…

YOLOv9改进,YOLOv9检测头融合RFAConv卷积,适合目标检测、分割任务

摘要 空间注意力已广泛应用于提升卷积神经网络(CNN)的性能,但它存在一定的局限性。作者提出了一个新的视角,认为空间注意力机制本质上解决了卷积核参数共享的问题。然而,空间注意力生成的注意力图信息对于大尺寸卷积核来说是不足够的。因此,提出了一种新型的注意力机制—…

【机器学习】深入无监督学习分裂型层次聚类的原理、算法结构与数学基础全方位解读,深度揭示其如何在数据空间中构建层次化聚类结构

&#x1f31f;个人主页&#xff1a;落叶 &#x1f31f;当前专栏: 机器学习专栏 目录 引言 分裂型层次聚类&#xff08;Divisive Hierarchical Clustering&#xff09; 1. 基本原理 2. 分裂型层次聚类的算法步骤 Step 1: 初始化 Step 2: 选择分裂的簇 Step 3: 执行分裂操作…

VirtualBox can‘t enable the AMD-V extension

个人博客地址&#xff1a;VirtualBox cant enable the AMD-V extension | 一张假钞的真实世界 最近一次完成Deepin的系统更新后&#xff0c;进入VirtualBox创建的虚拟机&#xff08;Widows10&#xff09;时&#xff0c;出现以下错误&#xff1a; 根据网址“https://askubuntu.…

[JavaScript] 数组与对象详解

文章目录 数组&#xff08;Array&#xff09;什么是数组数组的常用操作**访问数组元素****修改数组元素****数组的长度****添加和删除元素** 常用数组方法map():filter():reduce():**其他实用方法** 对象&#xff08;Object&#xff09;什么是对象对象的基本操作**访问属性****…

“模板”格式化发布新创诗(为《诗意 2 0 2 5》贡献力量)

预置MarkDown&Html文本&#xff0c;脚本读取f-string模板完成录入嵌套。 (笔记模板由python脚本于2025-01-22 19:19:58创建&#xff0c;本篇笔记适合喜欢分享的达人的coder翻阅) 【学习的细节是欢悦的历程】 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不…

论文速读|Multi-Modal Disordered Representation Learning Network for TBPS.AAAI24

论文地址&#xff1a;Multi-Modal Disordered Representation Learning Network for Description-Based Person Search 代码地址&#xff1a;未开源&#xff08;2025.01.22&#xff09; bib引用&#xff1a; inproceedings{yang2024multi,title{Multi-Modal Disordered Repres…

计算机视觉算法实战——实体物体跟踪

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​​​​​ ​ 1. 领域介绍✨✨ 实体物体跟踪&#xff08;Object Tracking&#xff09;是计算机视觉领域中的一个重要研究方向&#x…

C++17 新特性深入解析:constexpr 扩展、if constexpr 和 constexpr lambda

C17 不仅增强了现有特性&#xff0c;还引入了一些全新的编程工具&#xff0c;极大地提升了代码的效率和表达力。在这篇文章中&#xff0c;我们将深入探讨 C17 中与 constexpr 相关的三个重要特性&#xff1a;constexpr 的扩展用法、if constexpr 和 constexpr lambda。这些特性…

IVR:交互式语音应答系统解析及其应用

引言 IVR&#xff08;Interactive Voice Response&#xff09;&#xff0c;即交互式语音应答系统&#xff0c;是一种功能强大的电话自动服务系统。它通过语音识别和按键反馈&#xff0c;使用户与系统之间实现实时交互&#xff0c;为用户提供自助服务、咨询、报告、投诉等多种功…

Observability:最大化可观察性 AI 助手体验的 5 大提示(prompts)

作者&#xff1a;来自 Elastic Zoia_AUBRY 在过去三年担任客户工程师期间&#xff0c;我遇到了数百名客户&#xff0c;他们最常问的问题之一是&#xff1a;“我的数据在 Elastic 中&#xff1b;我该如何利用它获得最大优势&#xff1f;”。 如果这适用于你&#xff0c;那么本…

【Vim Masterclass 笔记25】S10L45:Vim 多窗口的常用操作方法及相关注意事项

文章目录 S10L45 Working with Multiple Windows1 水平分割窗口2 在水平分割的新窗口中显示其它文件内容3 垂直分割窗口4 窗口的关闭5 在同一窗口水平拆分出多个窗口6 关闭其余窗口7 让四个文件呈田字形排列8 光标在多窗口中的定位9 调节子窗口的尺寸大小10 变换子窗口的位置11…

STM32_SD卡的SDIO通信_基础读写

本篇将使用CubeMXKeil, 创建一个SD卡读写的工程。 目录 一、SD卡要点速读 二、SDIO要点速读 三、SD卡座接线原理图 四、CubeMX新建工程 五、CubeMX 生成 SD卡的SDIO通信部分 六、Keil 编辑工程代码 七、实验效果 一、SD卡 速读 SD卡&#xff0c;全称Secure Digital M…

大模型GUI系列论文阅读 DAY2续:《一个具备规划、长上下文理解和程序合成能力的真实世界Web代理》

摘要 预训练的大语言模型&#xff08;LLMs&#xff09;近年来在自主网页自动化方面实现了更好的泛化能力和样本效率。然而&#xff0c;在真实世界的网站上&#xff0c;其性能仍然受到以下问题的影响&#xff1a;(1) 开放领域的复杂性&#xff0c;(2) 有限的上下文长度&#xff…

【ESP32】ESP32连接JY61P并通过WIFI发送给电脑

前言 手头上有个ESP32&#xff0c;发现有wifi功能&#xff0c;希望连接JY61P并通过WIFI把姿态数据发送给电脑 1.采用Arduino IDE编译器&#xff1b;需要安装ESP32的开发板管理器&#xff1b; 2.电脑接受数据是基于python的&#xff1b; 1. ESP32 连接手机WIFI #include <…

C语言程序设计十大排序—冒泡排序

文章目录 1.概念✅2.冒泡排序&#x1f388;3.代码实现✅3.1 直接写✨3.2 函数✨ 4.总结✅ 1.概念✅ 排序是数据处理的基本操作之一&#xff0c;每次算法竞赛都很多题目用到排序。排序算法是计算机科学中基础且常用的算法&#xff0c;排序后的数据更易于处理和查找。在计算机发展…

【Elasticsearch】腾讯云安装Elasticsearch

Elasticsearch 认识Elasticsearch安装Elasticsearch安装Kibana安装IK分词器分词器的作用是什么&#xff1f;IK分词器有几种模式&#xff1f;IK分词器如何拓展词条&#xff1f;如何停用词条&#xff1f; 认识Elasticsearch Elasticsearch的官方网站如下 Elasticsearch官网 Ela…