H266/VVC 帧内预测中 MDIS 技术

参考像素平滑滤波 MDIS

  1. VVC 的帧内预测参考像素获取过程和 HEVC 相同,但参考像素滤波过程有所改进。在H.266中 MDIS(Mode Dependent Intra Smoothing)即模式依赖帧内平滑滤波,是对帧内预测的亮度分量参考像素进行滤波决策的一个技术。H266 对帧内角度模式使用 4 抽头插值滤波来提高预测精度;其提供了两种 4 抽头滤波方式,一种是基于 DCT 的插值滤波器(DCTIF)其生成方式和 HEVC 相同,另一种是 4 抽头平滑插值滤波器(SIF) 。
  2. 帧内角度模式分类:下图中实现是整数角度模式,虚线是分数角度模式
    • A 类:水平或垂直(HOR_IDX、VER_IDX)
    • B 类:角度是 non-fractional 方向,对角模式(2,34,66)以及部分的宽角度模式(-14,-12,-10,-6,72,76,78,80)
    • C 类:其他角度模式
      在这里插入图片描述
  3. MDIS 技术处理过程:
    • 对于 A 类角度模式,不进行滤波处理,也不需要插值,直接用参考像素生成预测像素;
    • 对于 B 类角度模式,满足下列五个条件,则使用 [1 2 1]/4 三抽头滤波器对参考像素进行滤波,将滤波后的参考像素直接作为预测像素;
      • 参考行限制:预测过程为单行参考像素
      • 大小限制:当前 CU 包含的像素个数大于 32
      • 仅对亮度分量有用
      • 不使用 ISP 模式
      • 当前 CU 的预测模式是 Planar 模式或对角模式
    • 对于 C 类角度模式和不满足上述条件的 B 类角度模式,会使用4抽头的高斯插值或者三次插值滤波器,对参考像素进行插值(对预测像素的参考像素在非整数位置的情况)生成预测像素。具体使用 DCTIF 插值还是 SIF 插值由下列条件决定:
      • 设置 minDistVerHor =Min( Abs( predModeIntra − 50 ), Abs( predModeIntra − 18 ) )。

      • 设置 nTbS=(Log2(W)+Log2(H))>>1。

      • intraHorVerDistThres[ nTbS ]设置如下,
        在这里插入图片描述

      • 如果 minDistVerHor 大于 intraHorVerDistThres[ nTbS ],使用 SIF 进行插值。否则使用 DCTIF 进行插值。

    • 具体 DCTIF 和 SIF 的滤波系数可以参考标准或中文版书籍中介绍。
  4. VVenC 编码器中关于滤波器选择的函数在 IntraPrediction.cpp 文件中 initPredIntraParams 函数中判断。
    在这里插入图片描述
// Function for initialization of intra prediction parameters
void IntraPrediction::initPredIntraParams(const CodingUnit& cu, const CompArea area, const SPS& sps)
{
  const ComponentID compId = area.compID;
  const ChannelType chType = toChannelType(compId);

  const bool        useISP = NOT_INTRA_SUBPARTITIONS != cu.ispMode && isLuma( chType );

  const Size   cuSize    = Size( cu.blocks[compId].width, cu.blocks[compId].height );
  const Size   puSize    = Size( area.width, area.height );
  const Size&  blockSize = useISP ? cuSize : puSize;
  const int      dirMode = CU::getFinalIntraMode(cu, chType);
  const int     predMode = getWideAngle( blockSize.width, blockSize.height, dirMode );

  m_ipaParam.isModeVer            = predMode >= DIA_IDX;
  m_ipaParam.multiRefIndex        = isLuma (chType) ? cu.multiRefIdx : 0 ;
  m_ipaParam.refFilterFlag        = false;
  m_ipaParam.interpolationFlag    = false;
  m_ipaParam.applyPDPC            = (puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) && m_ipaParam.multiRefIndex == 0;

  const int    intraPredAngleMode = (m_ipaParam.isModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX);


  int absAng = 0;
  if (dirMode > DC_IDX && dirMode < NUM_LUMA_MODE) // intraPredAngle for directional modes
  {
    static const int angTable[32]    = { 0,    1,    2,    3,    4,    6,     8,   10,   12,   14,   16,   18,   20,   23,   26,   29,   32,   35,   39,  45,  51,  57,  64,  73,  86, 102, 128, 171, 256, 341, 512, 1024 };
    static const int invAngTable[32] = {
      0,   16384, 8192, 5461, 4096, 2731, 2048, 1638, 1365, 1170, 1024, 910, 819, 712, 630, 565,
      512, 468,   420,  364,  321,  287,  256,  224,  191,  161,  128,  96,  64,  48,  32,  16
    };   // (512 * 32) / Angle

    const int     absAngMode         = abs(intraPredAngleMode);
    const int     signAng            = intraPredAngleMode < 0 ? -1 : 1;
                  absAng             = angTable  [absAngMode];

    m_ipaParam.absInvAngle           = invAngTable[absAngMode];
    m_ipaParam.intraPredAngle        = signAng * absAng;
    if (intraPredAngleMode < 0)
    {
      m_ipaParam.applyPDPC = false;
    }
    else if (intraPredAngleMode > 0)
    {
      const int sideSize = m_ipaParam.isModeVer ? puSize.height : puSize.width;
      const int maxScale = 2;

      m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.absInvAngle - 2) - 8));
      m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0;
    }
  }

  // high level conditions and DC intra prediction
  if( !isLuma( chType )
    || useISP
    || CU::isMIP( cu, chType ) //th remove this
    || m_ipaParam.multiRefIndex
    || DC_IDX == dirMode
    )
  {
  }
  else if (cu.bdpcmM[chType])
  {
    m_ipaParam.refFilterFlag = false;
  }
  else if (dirMode == PLANAR_IDX) // Planar intra prediction
  {
    m_ipaParam.refFilterFlag = puSize.width * puSize.height > 32 ? true : false;
  }
  else if (!useISP)// HOR, VER and angular modes (MDIS)
  {
    bool filterFlag = false;
    {
      const int diff = std::min<int>( abs( predMode - HOR_IDX ), abs( predMode - VER_IDX ) );
      const int log2Size = (Log2(puSize.width * puSize.height) >> 1);
      CHECK( log2Size >= MAX_INTRA_FILTER_DEPTHS, "Size not supported" );
      filterFlag = (diff > m_aucIntraFilter[log2Size]);
    }

    // Selelection of either ([1 2 1] / 4 ) refrence filter OR Gaussian 4-tap interpolation filter
    if (filterFlag)
    {
      const bool isRefFilter       =  isIntegerSlope(absAng);
      CHECK( puSize.width * puSize.height <= 32, "DCT-IF interpolation filter is always used for 4x4, 4x8, and 8x4 luma CB" );
      m_ipaParam.refFilterFlag     =  isRefFilter;
      m_ipaParam.interpolationFlag = !isRefFilter;
    }
  }
}
  1. VVenC 编码器中关于 [1 2 1]/4 三抽头滤波器的算法在 IntraPrediction.cpp 文件中 xFilterReferenceSamples 函数中计算。
    在这里插入图片描述
void IntraPrediction::xFilterReferenceSamples( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea& area, const SPS &sps
  , int multiRefIdx
  , int stride
)
{
  if (area.compID != COMP_Y)
  {
    multiRefIdx = 0;
  }
  const int predSize = m_topRefLength + multiRefIdx;
  const int predHSize = m_leftRefLength + multiRefIdx;
  const int predStride = stride == 0 ? predSize + 1 : stride;


  const Pel topLeft =
    (refBufUnfiltered[0] + refBufUnfiltered[1] + refBufUnfiltered[predStride] + refBufUnfiltered[predStride + 1] + 2)
    >> 2;

  refBufFiltered[0] = topLeft;

  for (int i = 1; i < predSize; i++)
  {
    refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2;
  }
  refBufFiltered[predSize] = refBufUnfiltered[predSize];

  refBufFiltered += predStride;
  refBufUnfiltered += predStride;

  refBufFiltered[0] = topLeft;

  for (int i = 1; i < predHSize; i++)
  {
    refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2;
  }
  refBufFiltered[predHSize] = refBufUnfiltered[predHSize];
}
  1. VVenC 编码器中关于 4 抽头平滑滤波器的算法在 IntraPrediction.cpp 文件中 xPredIntraAng 函数中计算。
    在这里插入图片描述
/** Function for deriving the simplified angular intra predictions.
*
* This function derives the prediction samples for the angular mode based on the prediction direction indicated by
* the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and
* the reference row above the block in the case of vertical prediction or displacement of the rightmost column
* of the block and reference column left from the block in the case of the horizontal prediction. The displacement
* is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples,
* the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken
* from the extended main reference.
*/
//NOTE: Bit-Limit - 25-bit source

void IntraPrediction::xPredIntraAng( PelBuf& pDst, const CPelBuf& pSrc, const ChannelType channelType, const ClpRng& clpRng)
{
  int width =int(pDst.width);
  int height=int(pDst.height);

  const bool bIsModeVer     = m_ipaParam.isModeVer;
  const int  multiRefIdx    = m_ipaParam.multiRefIndex;
  const int  intraPredAngle = m_ipaParam.intraPredAngle;
  const int  absInvAngle    = m_ipaParam.absInvAngle;

  Pel* refMain;
  Pel* refSide;

  Pel  refAbove[2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];
  Pel  refLeft [2 * MAX_CU_SIZE + 3 + 33 * MAX_REF_LINE_IDX];

  // Initialize the Main and Left reference array.
  if (intraPredAngle < 0)
  {
    memcpy(&refAbove[height],pSrc.buf,(width + 2 + multiRefIdx)*sizeof(Pel));
    for (int y = 0; y <= height + 1 + multiRefIdx; y++)
    {
      refLeft[y + width] = pSrc.at(y, 1);
    }
    refMain = bIsModeVer ? refAbove + height : refLeft + width;
    refSide = bIsModeVer ? refLeft + width : refAbove + height;

    // Extend the Main reference to the left.
    int sizeSide = bIsModeVer ? height : width;
    for (int k = -sizeSide; k <= -1; k++)
    {
      refMain[k] = refSide[std::min((-k * absInvAngle + 256) >> 9, sizeSide)];
    }
  }
  else
  {
    memcpy(&refAbove[0], pSrc.buf, ((m_topRefLength)+multiRefIdx + 1) * sizeof(Pel));
    for (int y = 0; y <= m_leftRefLength + multiRefIdx; y++)
    {
      refLeft[y] = pSrc.at(y, 1);
    }

    refMain = bIsModeVer ? refAbove : refLeft;
    refSide = bIsModeVer ? refLeft : refAbove;

    // Extend main reference to right using replication
    const int log2Ratio = Log2(width) - Log2(height);
    const int s         = std::max<int>(0, bIsModeVer ? log2Ratio : -log2Ratio);
    const int maxIndex  = (multiRefIdx << s) + 2;
    const int refLength = bIsModeVer ? m_topRefLength : m_leftRefLength;
    const Pel val       = refMain[refLength + multiRefIdx];
    for (int z = 1; z <= maxIndex; z++)
    {
      refMain[refLength + multiRefIdx + z] = val;
    }
  }

  // swap width/height if we are doing a horizontal mode:
  if (!bIsModeVer)
  {
    std::swap(width, height);
  }
  Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE];
  const int dstStride = bIsModeVer ? pDst.stride : MAX_CU_SIZE;
  Pel* pDstBuf = bIsModeVer ? pDst.buf : tempArray;

  // compensate for line offset in reference line buffers
  refMain += multiRefIdx;
  refSide += multiRefIdx;

  Pel* pDsty = pDstBuf;

  if( intraPredAngle == 0 )  // pure vertical or pure horizontal
  {
    if (m_ipaParam.applyPDPC)
    {
      const int scale   = (Log2(width * height) - 2) >> 2;
      IntraHorVerPDPC(pDsty,dstStride,refSide,width,height,scale,refMain,clpRng);
    }
    else
    {
      for( int y = 0; y < height; y++ )
      {
        memcpy(pDsty,&refMain[1],width*sizeof(Pel));
        pDsty += dstStride;
      }
    }
  }
  else
  {
    if( !isIntegerSlope( abs( intraPredAngle ) ) )
    {
      int deltaPos = intraPredAngle * ( 1 + multiRefIdx );
      if( isLuma( channelType ) )
      {
        if( width <= 2 )
        {
          for( int y = 0, deltaPos = intraPredAngle * ( 1 + multiRefIdx );
               y < height;
               y++, deltaPos += intraPredAngle, pDsty += dstStride )
          {
            const int deltaInt   = deltaPos >> 5;
            const int deltaFract = deltaPos & 31;

            if( !isIntegerSlope( abs( intraPredAngle ) ) )
            {
              const bool useCubicFilter = !m_ipaParam.interpolationFlag;

              const TFilterCoeff intraSmoothingFilter[4] = { TFilterCoeff( 16 - ( deltaFract >> 1 ) ),
                                                             TFilterCoeff( 32 - ( deltaFract >> 1 ) ),
                                                             TFilterCoeff( 16 + ( deltaFract >> 1 ) ),
                                                             TFilterCoeff(      ( deltaFract >> 1 ) ) };
              const TFilterCoeff* const f =
                ( useCubicFilter ) ? InterpolationFilter::getChromaFilterTable( deltaFract ) : intraSmoothingFilter;

              for( int x = 0; x < width; x++ )
              {
                Pel p[4];

                p[0] = refMain[deltaInt + x + 0];
                p[1] = refMain[deltaInt + x + 1];
                p[2] = refMain[deltaInt + x + 2];
                p[3] = refMain[deltaInt + x + 3];

                Pel val = ( f[0] * p[0] + f[1] * p[1] + f[2] * p[2] + f[3] * p[3] + 32 ) >> 6;

                pDsty[x] = ClipPel( val, clpRng );   // always clip even though not always needed
              }
            }
          }
        }
        else
        {
          IntraPredAngleLuma(pDstBuf, dstStride, refMain, width, height, deltaPos, intraPredAngle, nullptr, !m_ipaParam.interpolationFlag, clpRng);
        }
      }
      else
      {
        IntraPredAngleChroma(pDstBuf,dstStride,refMain,width,height,deltaPos,intraPredAngle);
      }
    }
    else
    {
      for (int y = 0, deltaPos = intraPredAngle * (1 + multiRefIdx); y<height; y++, deltaPos += intraPredAngle, pDsty += dstStride)
      {
        const int deltaInt   = deltaPos >> 5;
        // Just copy the integer samples
        memcpy(pDsty,refMain  + deltaInt + 1,width*sizeof(Pel));
      }
    }

    if (m_ipaParam.applyPDPC)
    {
      pDsty = pDstBuf;
      IntraAnglePDPC(pDsty,dstStride,refSide,width,height,m_ipaParam.angularScale,absInvAngle);
    }
  } // else

  // Flip the block if this is the horizontal mode
  if( !bIsModeVer )
  {
    pDst.transposedFrom( CPelBuf( pDstBuf, dstStride, width, height) );
  }
}

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

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

相关文章

Chrome访问https页面显示ERR_CERT_INVALID,且无法跳过继续访问

在访问网页的时候&#xff0c;因为浏览器自身的安全设置问题&#xff0c; 对于https的网页访问会出现安全隐私的提示&#xff0c; 甚至无法访问对应的网站&#xff0c;尤其是chrome浏览器&#xff0c; 因此本文主要讲解如何设置chrome浏览器的设置&#xff0c;来解决该问题&…

深入解析 Transformer:从原理到可视化再到PyTorch实现

文章目录 深入解析 Transformer1 理解 Transformer1.1 理解自注意力机制 (Self-Attention)1.2 理解位置编码 (Positional Encoding)1.2.1 整数编码1.2.2 正弦编码 1.3 理解编码器和解码器模块1.3.1 编码器 1.4 最终线性层和 Softmax 层 2 编写 Transformer 的代码2.1 摘要和引言…

系统架构设计师考点—软件工程基础知识

一、备考指南 软件工程基础知识主要考查的是软件工程基础、软件开发方法、系统分析、设计、测试及运行和维护等相关知识&#xff0c;同时也是重点考点&#xff0c;在系统架构设计师的考试中选择题12~15分&#xff0c;案例分析和论文中也会考到相关内容&#xff0c;属于重点章节…

电影动画shader解析与实现

着色器代码解析 大家好&#xff01;我是 [数擎AI]&#xff0c;一位热爱探索新技术的前端开发者&#xff0c;在这里分享前端和Web3D、AI技术的干货与实战经验。如果你对技术有热情&#xff0c;欢迎关注我的文章&#xff0c;我们一起成长、进步&#xff01; 开发领域&#xff1a;…

使用ML.NET进行对象检测

1、前言 ML.NET 是面向 .NET 开发人员的开源跨平台机器学习框架&#xff0c;支持将自定义机器学习模型集成到 .NET 应用程序中。 它包含一个 API&#xff0c;其中包含不同的 NuGet 包、名为 模型生成器的 Visual Studio 扩展&#xff0c;以及作为 .NET 工具安装的 命令行接口。…

年会抽奖Html

在这里插入图片描述 <!-- <video id"backgroundMusic" src"file:///D:/background.mp3" loop autoplay></video> --> <divstyle"width: 290px; height: 580px; margin-left: 20px; margin-top: 20px; background: url(D:/nianhu…

vue -关于浏览器localstorge数据定期清除的实现

1.实现背景 用户登录时的信息存在了localstorge中&#xff0c;但它会一直存在。一般来说&#xff0c;我们希望这个数据能够定期被清除掉&#xff0c;以下一个定时清除的实现。 2.实现原理 在用户登录时&#xff0c;将用户信息存入localstorge的同时&#xff0c;将当前时间作…

LabVIEW水轮发电机组振动摆度故障诊断

本文介绍了基于LabVIEW的水轮发电机组振动摆度故障诊断系统的设计与实施过程。系统在通过高效的故障诊断功能&#xff0c;实现水轮发电机组的振动、温度等关键指标的实时监控与智能分析&#xff0c;从而提高电力设备的可靠性和安全性。 ​ 项目背景 随着电力行业对设备稳定性…

Collaborate with AI -- Write a modern C++ singleton factory

translate my blog <<与AI合作 -- 写一个modern c单例工厂>> to English. NOTE: It was written at 2024.01, maybe the AI is not smart as now. Preface In this article, readers can learn about a hybrid of the modern C singleton pattern and factory pat…

【轻松学C:编程小白的大冒险】--- C语言简介 02

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【轻松学C&#xff1a;编程小白的大冒险】…

下载b站高清视频

需要使用的edge上的一个扩展插件&#xff0c;所以选择使用edge浏览器。 1、在edge浏览器上下载 强力视频下载合并 扩展插件 2、在edge上打开b站&#xff0c;登录自己账号&#xff08;登录后才能下载到高清&#xff01;&#xff01;&#xff09;。打开一个视频&#xff0c;选择自…

oxml中创建CT_Document类

概述 本文基于python-docx源码&#xff0c;详细记录CT_Document类创建的过程&#xff0c;以此来加深对Python中元类、以及CT_Document元素类的认识。 元类简介 元类&#xff08;MetaClass&#xff09;是Python中的高级特性。元类是什么呢&#xff1f;Python是面向对象编程…

Tableau数据可视化与仪表盘搭建-基础图表制作

目录 对比分析&#xff1a;比大小 柱状图 条形图 数据钻取 筛选器 热力图 气泡图 变化分析&#xff1a;看趋势 折线图 预测 面积图 关系分布&#xff1a;看位置 散点图 直方图 地图 构成分析&#xff1a;看占比 饼图 树地图 堆积图 对比分析&#xff1a;比大…

QML学习(八) Quick中的基础组件:Item,Rectangle,MouseArea说明及使用场景和使用方法

上一篇中我们从设计器里可以看到Qt Quick-Base中有几大基础组件&#xff0c;如下图&#xff0c;这篇文章先介绍下Item&#xff0c;Rectangle&#xff0c;MouseArea这三个的说明及使用场景和使用方法 Item Item 是 QML 中所有可视元素的基类&#xff0c;是一个非常基础和通用的…

万界星空科技质量管理QMS系统具体功能介绍

一、什么是QMS系统&#xff0c;有什么价值&#xff1f; 1、QMS 系统即质量管理系统&#xff08;Quality Management System&#xff09;。 它是一套用于管理和控制企业产品或服务质量的集成化体系。 2、QMS 系统的价值主要体现在以下几个方面&#xff1a; 确保产品质量一致性…

字符串哈希stl解决

题目如下 STL的unordered-set STL的map 谢谢观看&#xff01;&#xff01;&#xff01;

JAVA I/O流练习1

往D盘中的JAVA复习文件夹中写数据&#xff1a; 数据改了一下哈&#xff1a; import java.io.*; import java.util.Scanner; public class Test {public static void main(String[] args) throws IOException {String fileName"D:JAVA复习\\grade.txt";FileWriter w…

英伟达Project Digits赋能医疗大模型:创新应用与未来展望

英伟达Project Digits赋能医疗大模型&#xff1a;创新应用与未来展望 一、引言 1.1 研究背景与意义 在当今数字化时代&#xff0c;医疗行业作为关乎国计民生的关键领域&#xff0c;正面临着前所未有的挑战与机遇。一方面&#xff0c;传统医疗模式在应对海量医疗数据的处理、复…

OpenAI 故障复盘 - 阿里云容器服务与可观测产品如何保障大规模 K8s 集群稳定性

本文作者&#xff1a; 容器服务团队&#xff1a;刘佳旭、冯诗淳 可观测团队&#xff1a;竺夏栋、麻嘉豪、隋吉智 一、前言 Kubernetes(K8s)架构已经是当今 IT 架构的主流与事实标准&#xff08;CNCF Survey[1]&#xff09;。随着承接的业务规模越来越大&#xff0c;用户也在使…

移动电商的崛起与革新:以开源AI智能名片2+1链动模式S2B2C商城小程序为例的深度剖析

摘要&#xff1a;本文旨在探讨移动电商的崛起背景、特点及其对传统电商模式的革新影响&#xff0c;并以开源AI智能名片21链动模式S2B2C商城小程序为具体案例&#xff0c;深入分析其在移动电商领域的创新实践。随着移动互联网技术的飞速发展&#xff0c;移动电商已成为电商行业的…