作者:66

(转载请注明出处)

还是参考HEVC_CJL的博客,理论都清楚,跟着他的进度看代码,感谢前辈的分享,他的代码里没有强滤波过程,在此我稍加补充。

原文链接:http://blog.csdn.net/hevc_cjl/article/category/1283611

分析initAdiPattern函数,其中调用了之前的fillReferenceSample函数。

initAdiPattern实现的功能如下,1.先按4x4块从左下到右上检测每个块是否可用。2.调用fillReferenceSample填充参考样点。3.参考样点的滤波,分了常规滤波和强滤波。另外,HEVC_CJL博客中最后uiWidth,uiHeigth标识错误了,经几次确认后,应该是uiWidth=2*uiCuWidth,uiHeith=2*uiCuHeigth。

具体过程见代码注释,肯定也有表述不完备的地方,请不吝赐教:

Void TComPattern::initAdiPattern( TComDataCU* pcCU, UInt uiZorderIdxInPart, UInt uiPartDepth, Int* piAdiBuf, Int iOrgBufStride, Int iOrgBufHeight, Bool& bAbove, Bool& bLeft, Bool bLMmode )
{Pel*  piRoiOrigin;//当前cu首地址Int*  piAdiTemp;UInt  uiCuWidth   = pcCU->getWidth(0) >> uiPartDepth;//cu宽度,uiPartDepth为四叉树深度UInt  uiCuHeight  = pcCU->getHeight(0)>> uiPartDepth;//cu高度UInt  uiCuWidth2  = uiCuWidth<<1;UInt  uiCuHeight2 = uiCuHeight<<1;UInt  uiWidth;//cu宽度UInt  uiHeight;//cu高度Int   iPicStride = pcCU->getPic()->getStride();//每次步进的距离Int   iUnitSize = 0;//4*4块Int   iNumUnitsInCu = 0;Int   iTotalUnits = 0;//总共包含的4*4块数量Bool  bNeighborFlags[4 * MAX_NUM_SPU_W + 1];//标记参考像素是否可用,4*16+1Int   iNumIntraNeighbor = 0;//可用的相邻块数UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;//获取当前PU左上、右上、左下以4x4为单位的ZorderpcCU->deriveLeftRightTopIdxAdi( uiPartIdxLT, uiPartIdxRT, uiZorderIdxInPart, uiPartDepth );pcCU->deriveLeftBottomIdxAdi  ( uiPartIdxLB,              uiZorderIdxInPart, uiPartDepth );iUnitSize      = g_uiMaxCUWidth >> g_uiMaxCUDepth;//4x4iNumUnitsInCu  = uiCuWidth / iUnitSize;iTotalUnits    = (iNumUnitsInCu << 2) + 1;//Top + RightTop\+ Left + LeftBottom + LeftTop = iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + 1//统计可用总数量,扫描顺序从左下到左上,再到右上bNeighborFlags[iNumUnitsInCu*2] = isAboveLeftAvailable( pcCU, uiPartIdxLT );//统计左上iNumIntraNeighbor  += (Int)(bNeighborFlags[iNumUnitsInCu*2]);iNumIntraNeighbor  += isAboveAvailable     ( pcCU, uiPartIdxLT, uiPartIdxRT, bNeighborFlags+(iNumUnitsInCu*2)+1 );//上,这个函数的\四个参数解释分别为当前pu编号,开始参考像素块号,结束块号,标志数组当前的位置指针iNumIntraNeighbor  += isAboveRightAvailable( pcCU, uiPartIdxLT, uiPartIdxRT, bNeighborFlags+(iNumUnitsInCu*3)+1 );//右上iNumIntraNeighbor  += isLeftAvailable      ( pcCU, uiPartIdxLT, uiPartIdxLB, bNeighborFlags+(iNumUnitsInCu*2)-1 );//左iNumIntraNeighbor  += isBelowLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, bNeighborFlags+ iNumUnitsInCu   -1 );//左下bAbove = true;bLeft  = true;//uiWidth、uiHeight与uiCuWidth,uiCuHeight不一样uiWidth=uiCuWidth2+1;//lefttop+above+rightaboveuiHeight=uiCuHeight2+1;//lefttop+left+leftbelow//超出buf的长 if (((uiWidth<<2)>iOrgBufStride)||((uiHeight<<2)>iOrgBufHeight)){return;}piRoiOrigin = pcCU->getPic()->getPicYuvRec()->getLumaAddr(pcCU->getAddr(), pcCU->getZorderIdxInCU()+uiZorderIdxInPart);piAdiTemp   = piAdiBuf;fillReferenceSamples (g_bitDepthY, piRoiOrigin, piAdiTemp, bNeighborFlags, iNumIntraNeighbor, iUnitSize, iNumUnitsInCu, iTotalUnits, uiCuWidth, uiCuHeight, uiWidth, uiHeight, iPicStride, bLMmode);Int   i;// generate filtered intra prediction samples参考像素滤波Int iBufSize = uiCuHeight2 + uiCuWidth2 + 1;  // left and left above border + above and above right border + top left corner = length of 3. filter bufferUInt uiWH = uiWidth * uiHeight;               // number of elements in one bufferbuf的大小//piFilteredBuf1最终参考像素放置的bufInt* piFilteredBuf1 = piAdiBuf + uiWH;        // 1. filter bufferInt* piFilteredBuf2 = piFilteredBuf1 + uiWH;  // 2. filter buffer//piFilterBuf中进行滤波计算Int* piFilterBuf = piFilteredBuf2 + uiWH;     // buffer for 2. filtering (sequential)//此处存放经滤波后的值Int* piFilterBufN = piFilterBuf + iBufSize;   // buffer for 1. filtering (sequential)//draft8.4.2.3Filtering process of neighbouring sampleInt l = 0;//左下到右上// left border from bottom to topfor (i = 0; i < uiCuHeight2; i++)//将处理后的参考样点值放到piFilterBuf中{piFilterBuf[l++] = piAdiTemp[uiWidth * (uiCuHeight2 - i)];}// top left cornerpiFilterBuf[l++] = piAdiTemp[0];// above border from left to rightfor (i=0; i < uiCuWidth2; i++){piFilterBuf[l++] = piAdiTemp[1 + i];}//判断是否进行强滤波if (pcCU->getSlice()->getSPS()->getUseStrongIntraSmoothing()){Int blkSize = 32;//强滤波块大小限定值,需要大于32的块Int bottomLeft = piFilterBuf[0];//左下角一个像素Int topLeft = piFilterBuf[uiCuHeight2];//左上角像素Int topRight = piFilterBuf[iBufSize-1];//右上角像素Int threshold = 1 << (g_bitDepthY - 5);//强滤波判断阈值//左下+左上-2*左中间<阈值Bool bilinearLeft = abs(bottomLeft+topLeft-2*piFilterBuf[uiCuHeight]) < threshold;//左上+右上-2*上中间<阈值Bool bilinearAbove  = abs(topLeft+topRight-2*piFilterBuf[uiCuHeight2+uiCuHeight]) < threshold;//强滤波if (uiCuWidth>=blkSize && (bilinearLeft && bilinearAbove)){Int shift = g_aucConvertToBit[uiCuWidth] + 3;  // log2(uiCuHeight2)=log2(64)=6piFilterBufN[0] = piFilterBuf[0];//复制左下piFilterBufN[uiCuHeight2] = piFilterBuf[uiCuHeight2];//左上piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1];//右上//滤波的权值与据本边界两顶点的距离有关for (i = 1; i < uiCuHeight2; i++)//垂直方向滤波{//uiCuHeitht2 = (64-纵坐标)*左上+纵坐标*右上+32piFilterBufN[i] = ((uiCuHeight2-i)*bottomLeft + i*topLeft + uiCuHeight) >> shift;}for (i = 1; i < uiCuWidth2; i++)//水平方向滤波{//同上piFilterBufN[uiCuHeight2 + i] = ((uiCuWidth2-i)*topLeft + i*topRight + uiCuWidth) >> shift;}}else {// 1. filtering with [1 2 1],常规滤波piFilterBufN[0] = piFilterBuf[0];//左下最后一个的参考像素点piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1];//右上最后一个for (i = 1; i < iBufSize - 1; i++){piFilterBufN[i] = (piFilterBuf[i - 1] + 2 * piFilterBuf[i]+piFilterBuf[i + 1] + 2) >> 2;}}}else {//常规滤波,同上,注意代码结构,并非进行两次。// 1. filtering with [1 2 1]piFilterBufN[0] = piFilterBuf[0];piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1];for (i = 1; i < iBufSize - 1; i++){piFilterBufN[i] = (piFilterBuf[i - 1] + 2 * piFilterBuf[i]+piFilterBuf[i + 1] + 2) >> 2;}}//滤波后的参考像素复制到piFilteredBuf1中// fill 1. filter buffer with filtered valuesl=0;for (i = 0; i < uiCuHeight2; i++)//垂直方向,从下到上{piFilteredBuf1[uiWidth * (uiCuHeight2 - i)] = piFilterBufN[l++];}piFilteredBuf1[0] = piFilterBufN[l++];//左上顶点for (i = 0; i < uiCuWidth2; i++)//水平方向{piFilteredBuf1[1 + i] = piFilterBufN[l++];}
}

其实这个代码有些细节很有意思,应该设计到可移植性和以后的更新维护,有时间了研究一下。

(转载请务必注明出处)

HEVC帧内预测参考像素检测获取和滤波相关推荐

  1. HEVC帧内预测参考相邻帧代码解析

    作者:66 (转载请注明出处) 参考链接:http://blog.csdn.net/hevc_cjl/article/details/8200793 亮度分量的帧内预测涉及到的模块比较多,CU-> ...

  2. 2.H.265/HEVC —— 帧内预测

    在H.265/HEVC中,35种预测模式是在PU的基础上定义的,而具体帧内预测过程的实现则是以TU为单位的.编撰规定PU可以以四叉树的形式划分TU,且一个PU内所有TU共享同一种预测模式的形式划分TU ...

  3. HEVC算法和体系结构:预测编码之帧内预测

    预测编码之帧内预测(Intra-Picture Prediction) 预测编码(Prediction Coding)是视频编码的核心技术之一,指利用已编码的一个或几个样本值,根据某种模型或方法,对当 ...

  4. HEVC学习(五) —— 帧内预测系列之三

    由于研究的需要,现将一晨不变大神的关于HEVC帧内预测的相关博客进行转载,方便自己查阅.一直都看一晨不变大神的帖子,受益匪浅.原著博客地址:http://blog.csdn.net/HEVC_CJL/ ...

  5. ISP(图像信号处理)学习笔记-帧内预测组合(视频编码入门)

    转载小柴柴博主的博文 本文链接:https://blog.csdn.net/cxy19931018/article/details/80635898 PDPC(Position Dependent I ...

  6. VCIP2020:不同尺寸块基于神经网络的帧内预测

    本文来自VCIP2020论文<Fully Neural Network Mode Based Intra Prediction of Variable Block Size> 论文提出使用 ...

  7. H.266:帧内预测之PDPC(VTM4)

    关于H.266帧内完整过程的总结(来自小小柴): https://blog.csdn.net/cxy19931018/article/details/80635898#commentBox 其中,对角 ...

  8. 关于帧内预测模式的视频隐写代码介绍

    关于帧内预测模式的视频隐写代码介绍 前言 一.H.265/HEVC的帧内预测过程 二.论文[1]的介绍以及如何复现 前言 在早期的基于帧内预测模式(IPM)的H.265/HEVC视频中,大多是基于自定 ...

  9. H.264 入门篇 - 05 (帧内预测)

    目录 0.前言 1.帧内预测类型 2.亮度 Intra_4x4 预测 2.1.当前块 Intra4x4PredMode 的推导过程 2.1.1.预测模式获取情况 2.2.获取预测数据 2.3.Intr ...

最新文章

  1. Codeforces Gym 100523E E - Gophers SET
  2. ScriptManager.RegisterStartupScript方法和Page.ClientScript.RegisterStartupScript() 区别
  3. 今天抽点时间来说一个C#里的关键字及它们的原型
  4. 复杂网络社区结构划分方法
  5. Linux服务器编程之:truncate()函数+案例说明
  6. 失业日志:2009年10月12日星期一
  7. R语言-Kindle特价书爬榜示例 输出HTML小技巧
  8. vantUI所有的弹出层组件(代码、调用、示例) - 集合篇
  9. Rsync、Inotify-tools简介
  10. ccd视觉定位教程_CCD视觉定位激光打标机的工作原理
  11. 分享一个linux下的steam的rpm安装包的链接
  12. Guice 快速入门
  13. 本地可以ping远程的服务器,但服务器不能ping本地
  14. struct字节计算
  15. 英语不规则动词变化表
  16. mesh组网是什么意思
  17. get_sequencer的用法总结
  18. MySQL的基本查询语句
  19. oracle数据库期末上机题,oracle数据库期末考试试题及复习资料
  20. 中国枪械店软件市场趋势报告、技术动态创新及市场预测

热门文章

  1. python 节假日_python判断工作日,节假日
  2. python解法:【PAT520砖石争霸赛】7-2真的恭喜你(10)
  3. LCD6210字符型液晶显示器 (1)
  4. 国际十大正规现货黄金交易平台排名(2023年优质版)
  5. 推荐四个不错的公众号
  6. 【天池竞赛】心跳数据挖掘
  7. 【机器学习】阿里云天池竞赛——工业蒸汽量预测(1)
  8. 除了苹果耳机外哪个无线耳机好?苹果蓝牙耳机平替推荐
  9. python网易云爬虫_使用python进行爬虫下载网易云音乐
  10. 如何写15分钟的计时器