矩阵加权帧内预测(Matrix weighted intra prediction,MIP)是VTM5.0中新加的帧内预测技术。该技术的核心就是训练矩阵,当前的亮度预测块的相邻采样点首先进行平均操作减少采样点数目,构成一个向量,然后该向量和视频序列集训练的一个参数矩阵相乘,通过该矩阵和向量相乘得到一个部分预测值的散点阵列,最后通过双线性插值生成出最终的预测值

如果预测一个WxH的PU,MIP使用上边的W个重建像素,左边的H个重建像素作为参考像素。参考像素的生成方法和普通的帧内预测一样。然后经过平均、矩阵向量相乘、线性插值三个步骤得到最终预测值。

1、平均

首先需要从左边参考列和上边参考行通过邻域平均的方法取参考样点。当W=H=4时,左边取2个上边取2个,共4个。其他情况下左边取4个,上边取4个,共8个。如上图左边部分所示。

    // init reduced boundary sizeif (m_blockSize.width > 4 || m_blockSize.height > 4){m_reducedBoundarySize = Size(4, 4);}else{m_reducedBoundarySize = Size(2, 2);}

计算邻域平均是个下采样过程,如下:

void PredictorMIP::doDownsampling( int* dst, const int* src, const SizeType srcLen, const SizeType dstLen ){// TODO: Check if src and dst can ever be negative. If not assign unsigned type and simplify rounding.const SizeType downsmpFactor = srcLen / dstLen;CHECKD( srcLen != dstLen * downsmpFactor, "Need integer downsampling factor." );CHECKD( ( downsmpFactor & ( downsmpFactor - 1 ) ) != 0, "Need power of two downsampling factor." );const int log2DownsmpFactor = g_aucLog2[ downsmpFactor ];const int roundingOffsetPositive = ( 1 << ( log2DownsmpFactor - 1 ) );
​for( SizeType srcIdx = 0, dstIdx = 0; dstIdx < dstLen; ++dstIdx ){int sum = 0;for( SizeType blockIdx = 0; blockIdx < downsmpFactor; ++blockIdx, ++srcIdx ){sum += src[ srcIdx ];}const int roundingOffset = roundingOffsetPositive - ( sum < 0 ? 1 : 0 );dst[ dstIdx ] = ( sum + roundingOffset ) >> log2DownsmpFactor;}}

取出的参考样点要拼接成长度为4或8的向量。拼接方式如下:

其中mode指的是MIP-mode。

#if JVET_N0217_MATRIX_INTRAPRED
int getNumModesMip(const Size& block)
{if (block.width > (4 * block.height) || block.height > (4 * block.width)){return 0;}
​if( block.width == 4 && block.height == 4 ){return 35;}else if (block.width <= 8 && block.height <= 8){return 19;}else{return 11;}
}
​bool PredictorMIP::isTransposed( const int modeIdx ) const{return ( modeIdx > ( m_numModes / 2 ) );}

2、矩阵向量相乘

上一步得到的向量和一个训练好的矩阵相乘,再加上一个偏移量得到预测值。

其中矩阵A和向量b都是训练好的,取自于集合S0,S1或S2。

int PredictorMIP::getWeightIdx( const int modeIdx ) const{//!<对于模式号大于m_numModes / 2 的需要进行折叠和小于m_numModes / 2 的使用相同矩阵if( modeIdx > m_numModes / 2 ){return modeIdx - m_numModes / 2;}else{return modeIdx;}}
​void PredictorMIP::getMatrixBias( const short*& matrix, const short*& bias, const int modeIdx ) const{const int idx = getWeightIdx( modeIdx );//!<4x4块使用mipMatrix4x4和mipBias4x4里的矩阵和向量,下同if( m_blockSize.width == 4 && m_blockSize.height == 4 ){matrix = &mipMatrix4x4[idx][0][0];bias   = &mipBias4x4  [idx][0];}else if( m_blockSize.width <= 8 && m_blockSize.height <= 8 ){matrix = &mipMatrix8x8[idx][0][0];bias   = &mipBias8x8  [idx][0];}else{matrix = &mipMatrix16x16[idx][0][0];bias   = &mipBias16x16  [idx][0];}}

上面代码中mipMatrix4x4和mipBias4x4就是S0,mipMatrix8x8和mipBias8x8就是S1,mipMatrix16x16和mipBias16x16就是S2。

mipMatrix4x4里含18个16x4的矩阵,mipBias4x4里含18个16维的向量,用于4x4的块。

mipMatrix8x8里含10个16x8的矩阵,mipBias8x8里含10个16维的向量,用于4x8,8x4,8x8块。

mipMatrix16x16里含6个64x8的矩阵,mipBias16x16里含6个64维的向量,用于其他块。

由于篇幅限制,具体的矩阵和向量值就不贴了。

注:

1、由getNumModesMip函数可知,4x4块有35种MIP模式,4x8,8x4,8x8块有19种MIP模式,其他情况有11种模式。而这里S0,S1,S2长度分别是18,10,6,比之前减半了。注意由getWeightIdx可知每2种模式共享一个矩阵和向量。

2、对于4xn,nx4(n>8)的块,由上面公式可知其对应的矩阵A应该是32x8,这里使用S2内的矩阵和向量进行计算,其中会丢掉矩阵中的32行和向量中的32个值。丢掉的行分别对应于生成的8x8矩阵中的x奇数位置和y的奇数位置。

3、插值

插值是一个上采样过程。

如果两个方向都需要插值,如果W<H先进行水平方向插值否则先进行垂直方向插值。

以WxH块的垂直插值为例,其中max(W,H)≧8且W≧H。

首先,将待插值的矩阵扩展到上面一行,如图1右半部分所示。上边一行按下式得到。

然后,对空余位置利用相邻值按下式进行插值。

从上面公式可以看出,当上采样2倍时即U_ver=2或H_ver=2,进行插值计算时不需要乘法运算。在其他情况下每次插值计算会进行不多于2次乘法运算。

void PredictorMIP::predictionUpsampling1D( int* const dst, const int* const src, const int* const bndry,const SizeType srcSizeUpsmpDim, const SizeType srcSizeOrthDim,const SizeType srcStep, const SizeType srcStride,const SizeType dstStep, const SizeType dstStride,const unsigned int upsmpFactor ){// TODO: Check if src and dst can ever be negative. If not assign unsigned type and simplify rounding.const int log2UpsmpFactor = g_aucLog2[ upsmpFactor ];CHECKD( upsmpFactor <= 1, "Upsampling factor must be at least 2." );
​SizeType idxOrthDim = 0;const int* srcLine = src;int* dstLine = dst;while( idxOrthDim < srcSizeOrthDim ){SizeType idxUpsmpDim = 0;const int* before = bndry + idxOrthDim;const int* behind = srcLine;int* currDst = dstLine;while( idxUpsmpDim < srcSizeUpsmpDim ){SizeType pos = 1;int scaledBefore = ( *before ) << log2UpsmpFactor;int scaledBehind = 0;while( pos <= upsmpFactor ){scaledBefore -= *before;scaledBehind += *behind;*currDst = scaledBefore + scaledBehind;*currDst = ( *currDst + ( 1 << ( log2UpsmpFactor - 1 ) ) -( *currDst < 0 ? 1 : 0 ) ) >> log2UpsmpFactor;
​pos++;currDst += dstStep;}
​idxUpsmpDim++;before = behind;behind += srcStep;}
​idxOrthDim++;srcLine += srcStride;dstLine += dstStride;}}

4、示例

下面给出一个完整的MIP算法过程是示例。

1.对于4x4的块,从左边和上边参考行各取两个值组成一个4维的向量。将该向量进行矩阵向量相乘运算,矩阵取自于S0。完成矩阵向量相乘和偏移值相加后得到一个16维的向量。这个16维向量形成一个4x4的矩阵不用进行插值直接作为预测矩阵。预测矩阵的每个值需要进行(4x16)/(4x4)=4次乘法运算。

2.对于8x8的块,从左边和上边参考行各取4个值组成一个8维的向量。将该向量进行矩阵向量相乘运算,矩阵取自于S1。完成矩阵向量相乘和偏移值相加后得到一个16维的向量。这个16维向量形成预测矩阵的奇数位置值。然后在垂直和水平方向进行插值,由于这个插值过程不需要进行乘法运算,所以预测矩阵的每个值需要进行(8x16)/(8x8)=2次乘法运算。

3.对于8x4的块,从左边和上边参考行各取4个值组成一个8维的向量。将该向量进行矩阵向量相乘运算,矩阵取自于S1。完成矩阵向量相乘和偏移值相加后得到一个16维的向量。这个16维向量形成预测矩阵的奇数行值和所有的列值。然后在水平方向进行插值,由于这个插值过程不需要进行乘法运算,所以预测矩阵的每个值需要进行(8x16)/(8x4)=4次乘法运算。4x8块处理过程类似。

4.对于16x16的块,从左边和上边参考行各取4个值组成一个8维的向量。将该向量进行矩阵向量相乘运算,矩阵取自于S2。完成矩阵向量相乘和偏移值相加后得到一个64维的向量。这个64维向量形成预测矩阵的奇数行值和奇数列值。然后在垂直和水平方向进行插值,由于插值过程不需要进行乘法运算,所以预测矩阵的每个值需要进行(8x64)/(16x16)=2次乘法运算。

对于更大尺寸的块处理过程类似,很容易计算出每个样点乘法运算次数小于4。

对于Wx8,W>8的块,生成的8x8预测矩阵包含所有行和奇数列,所以只需要在水平方向进行插值。预测矩阵的每个值需要进行(8x64)/(Wx8)=64/W次乘法运算。当W=16时,它的线性插值过程不需要乘法运算。当W>16时,每个像素插值过程需要的乘法运算少于2次。所以每个像素总的乘法运算小于等于4次。8xW类似。

对于Wx4的块,矩阵相乘时要去掉矩阵的奇数行,最终只需要在水平方向进行插值。预测矩阵的每个值需要进行(8x32)/(Wx4)=64/W次乘法运算。当W=16时,它的线性插值过程不需要乘法运算。当W>16时,每个像素插值过程需要的乘法运算少于2次。所以每个像素总的乘法运算小于等于4次。4xW类似。

感兴趣的请关注微信公众号Video Coding

VVC帧内预测(六)MIP相关推荐

  1. H.266 VVC 帧内预测中MIP技术更新

    P次会议采纳的MIP技术: (1)P0199, P0289, P0303(解决方案一样,待看) (2)P0803中 固定上采样顺序,先水平,后垂直 不受最大变换尺寸大小(3232/6464)限制,使M ...

  2. H.266/VVC帧内预测总结

    一.帧内预测基本原理 帧内预测技术是利用同一帧中相邻像素的相关性,利用当前块相邻区域的重建像素预测当前块中像素的技术,如下图所示,当前CU可以利用相邻A.B.C.D和E位置处的重建像素来预测当前CU中 ...

  3. VVC帧内预测(一)

    1.帧内预测模式 为了适应更多的预测方向,VVC的帧内角度预测模式增加为65个,加上DC模式和planar模式,VVC的帧内预测模式有67个.下图中红色的线是VVC比HEVC增加的预测方向. 在HEV ...

  4. VVC 帧内预测代码 xPredIntraAng()函数

    帧内预测中的initPredIntraParams()函数 (负参考方向处在跑代码时再看一遍)_青椒鸡汤的博客-CSDN博客 H.266/VVC-VTM代码学习-帧内预测05-Angular模式下计算 ...

  5. VVC帧内预测(三)PDPC

    位置决定的帧内预测组合(Position dependent intra prediction combination,PDPC)是在帧内预测时使用未滤波和已滤波的参考像素的加权值作为预测值. PDP ...

  6. VVC帧内算法-PDPC

    3.3.3 Position dependent intra prediction combination (PDPC) 在VVC帧内预测中,DC,Planar和几种角度模式的预测值会进一步被PDPC ...

  7. 从HEVC到VVC:帧内预测技术的演进(2) – 多划分及多参考行帧内预测

    当前主流的视频编码标准(如H.264/AVC,VP9,AVS1,HEVC等)均使用当前预测单元最邻近的已重构像素对当前预测单元进行帧内预测.因为当前预测单元与其临近的像素之间有很强的相关性,该帧内预测 ...

  8. H.266/VVC代码学习:帧内预测之角度预测函数(predIntraAng、xPredIntraAng)

    predIntraAng函数 VTM中,帧内预测的角度预测的入口函数为predIntraAng函数,该函数主要是用于进行传统的帧内预测(Planar.DC.角度预测),然后对Planar和DC模式使用 ...

  9. VVC帧间预测(十)帧间帧内联合预测CIIP

    帧间帧内联合预测(Combined inter and intra prediction ,CIIP),在HEVC中一个CU在预测时要么使用帧内预测要么使用帧间预测,二者只能取其一.而VVC中提出的C ...

最新文章

  1. 2019与下一个十年:我们将要放弃的和将要拥抱的
  2. mysql myisam转innodb_Mysql MyISAM数据库批量转换表引擎为Innodb
  3. python的快速入门-Python快速入门,你想要的就在这里了!
  4. ubuntu 循环登录问题,
  5. Java 中的多线程你只要看这一篇就够了
  6. Redis 数据结构 :SDS、链表、字典、跳表、整数集合、压缩列表
  7. Loj #6077. 「2017 山东一轮集训 Day7」逆序对
  8. Jmeter5 语言中文
  9. android 音乐 数据库,android从数据库中取音乐数据
  10. OS: 读者写者问题(写者优先+LINUX+多线程+互斥量+代码)(转)
  11. 设置电脑系统密码以及桌面密码
  12. Linux操作系统下的多线程编程详细解析----条件变量
  13. 达梦安装与基本使用【进阶】
  14. 冰点还原忘记密码如何修改配置或卸载
  15. 【教程】如何批量获取图片信息,尺寸、大小、路径、文件名,然后导出表格或者txt的文本,下面教你使用方法
  16. SASS _ 入门版
  17. python 汉字转拼音
  18. 专题训练二 搜索进阶 HDU - 3085 Nightmare Ⅱ (双向BFS + 曼哈顿距离)
  19. 设计模式讲解与代码实践(二十三)——模板方法
  20. 3.14 python笔记

热门文章

  1. Js鼠标放上去图片变大变小
  2. 微信后台基于时间序的新一代海量数据存储架构的设计实践
  3. Parallels Desktop 17.x by TNT 出现网络初始化失败怎么办
  4. SpringCloud-Alibaba之入门
  5. 华为推送 简介 集成 MD
  6. 网易2018实习生招聘笔试题-JAVA开发实习生
  7. linux ubuntu bionic,在Ubuntu 18.04 Bionic Beaver Linux上安装和设置KVM
  8. HTML5在vivo手机适配问题
  9. 云耀服务器切换系统,云耀云服务器切换操作系统
  10. 前端页面模拟浏览器搜索功能Ctrl+F实现