HEVC帧内预测参考像素检测获取和滤波
作者: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帧内预测参考像素检测获取和滤波相关推荐
- HEVC帧内预测参考相邻帧代码解析
作者:66 (转载请注明出处) 参考链接:http://blog.csdn.net/hevc_cjl/article/details/8200793 亮度分量的帧内预测涉及到的模块比较多,CU-> ...
- 2.H.265/HEVC —— 帧内预测
在H.265/HEVC中,35种预测模式是在PU的基础上定义的,而具体帧内预测过程的实现则是以TU为单位的.编撰规定PU可以以四叉树的形式划分TU,且一个PU内所有TU共享同一种预测模式的形式划分TU ...
- HEVC算法和体系结构:预测编码之帧内预测
预测编码之帧内预测(Intra-Picture Prediction) 预测编码(Prediction Coding)是视频编码的核心技术之一,指利用已编码的一个或几个样本值,根据某种模型或方法,对当 ...
- HEVC学习(五) —— 帧内预测系列之三
由于研究的需要,现将一晨不变大神的关于HEVC帧内预测的相关博客进行转载,方便自己查阅.一直都看一晨不变大神的帖子,受益匪浅.原著博客地址:http://blog.csdn.net/HEVC_CJL/ ...
- ISP(图像信号处理)学习笔记-帧内预测组合(视频编码入门)
转载小柴柴博主的博文 本文链接:https://blog.csdn.net/cxy19931018/article/details/80635898 PDPC(Position Dependent I ...
- VCIP2020:不同尺寸块基于神经网络的帧内预测
本文来自VCIP2020论文<Fully Neural Network Mode Based Intra Prediction of Variable Block Size> 论文提出使用 ...
- H.266:帧内预测之PDPC(VTM4)
关于H.266帧内完整过程的总结(来自小小柴): https://blog.csdn.net/cxy19931018/article/details/80635898#commentBox 其中,对角 ...
- 关于帧内预测模式的视频隐写代码介绍
关于帧内预测模式的视频隐写代码介绍 前言 一.H.265/HEVC的帧内预测过程 二.论文[1]的介绍以及如何复现 前言 在早期的基于帧内预测模式(IPM)的H.265/HEVC视频中,大多是基于自定 ...
- H.264 入门篇 - 05 (帧内预测)
目录 0.前言 1.帧内预测类型 2.亮度 Intra_4x4 预测 2.1.当前块 Intra4x4PredMode 的推导过程 2.1.1.预测模式获取情况 2.2.获取预测数据 2.3.Intr ...
最新文章
- Codeforces Gym 100523E E - Gophers SET
- ScriptManager.RegisterStartupScript方法和Page.ClientScript.RegisterStartupScript() 区别
- 今天抽点时间来说一个C#里的关键字及它们的原型
- 复杂网络社区结构划分方法
- Linux服务器编程之:truncate()函数+案例说明
- 失业日志:2009年10月12日星期一
- R语言-Kindle特价书爬榜示例 输出HTML小技巧
- vantUI所有的弹出层组件(代码、调用、示例) - 集合篇
- Rsync、Inotify-tools简介
- ccd视觉定位教程_CCD视觉定位激光打标机的工作原理
- 分享一个linux下的steam的rpm安装包的链接
- Guice 快速入门
- 本地可以ping远程的服务器,但服务器不能ping本地
- struct字节计算
- 英语不规则动词变化表
- mesh组网是什么意思
- get_sequencer的用法总结
- MySQL的基本查询语句
- oracle数据库期末上机题,oracle数据库期末考试试题及复习资料
- 中国枪械店软件市场趋势报告、技术动态创新及市场预测