本文主要是介绍MatLab画PU分割模式图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
HEVC的四叉树块分割算法的核心是确定CU/PU/TU的最优分割模式。最优分割模式算法的代码块,即xCompressCu,网上有对此比较详细的阐释,个人的学习也是参考这些,这里不再赘述。
本文主要目的是画出某B帧的NonSquare PU分割模式图,即包括2NxN,Nx2N,以及四种AMP分割。HM编码器参数配置采用Random_access,对BasketballDrill序列,这里参考http://blog.csdn.net/hevc_cjl/article/details/8169182
在TEncCu中调用完xCompressCu后加入如下代码,将最终的PU分割模式导出至PUpartion文件中:
ofstream PupartionInfo;
TComDataCU* Pupartion= m_ppcBestCU[0];
PupartionInfo.open("PuPartion.txt", ios::app);
int iCount = 0;
int iWidthInPart = g_uiMaxCUWidth >> 2;
for(UInt iPartitionNum = 0; iPartitionNum < Pupartion->getTotalNumPart(); iPartitionNum++){if ( (iCount & (iWidthInPart - 1)) == 0) PupartionInfo << "\n";//每16个数据换行iCount++;PupartionInfo << Pupartion-> getPartitionSize(g_auiRasterToZscan[iPartitionNum]) << " ";//以4x4块为基本单位,导出PU分割模式信息,光栅扫描转换为Z扫描}PupartionInfo.close();
得到的文件数据如图
接下来在matlab中,利用上面输出的数据,画出PU分割模式图,定义函数:function PU_View(YUV_FileName, Pu_Partion, Width, Height, NumFrame)
clc;
%% 参数设置
LCU_Size = 64;
MaxNumPartition = 256;
LCU_Width = 16;
LCU_Height = 16;
MinOperSize = 4;NumLCU_Row = floor( (Width + LCU_Size-1) / LCU_Size ); % 行有多少LCU,不满64的也算一个
NumLCU_Col = floor( (Height+ LCU_Size-1) / LCU_Size ); % 列有多少LCU,不满64的也算一个Fid_YUV = fopen(YUV_FileName,'rb');
Fid_Pu = fopen(Pu_Partion);for uiFrame = 1 : NumFrame%% 从buffer中读取数据ImgData = fread(Fid_YUV, [Width, Height], 'uint8'); % image data YImgData_U = fread(Fid_YUV ,[Width/2, Height/2], 'uint8'); % image data UImgData_V = fread(Fid_YUV ,[Width/2, Height/2], 'uint8'); % image data VImgData = ImgData';PUData = fscanf(Fid_Pu,'%d',[NumLCU_Row * NumLCU_Col * MaxNumPartition,1]);%以十进制读入数据,保存在PUData,PUData为NumLCU_Row * NumLCU_Col * MaxNumPartition行1列的矩阵%%画出LCU分界线figure ; imshow(ImgData,[]);for i = 1 : Width/LCU_Sizeline([i*LCU_Size, i*LCU_Size], [1 Height],'Color', 'r','LineWidth',2) %划纵向线endfor i = 1 : Height/LCU_Sizeline([1 Width], [i*LCU_Size, i*LCU_Size],'Color', 'r','LineWidth',2)%划横向线endfor i = 1 : NumLCU_Col %纵向扫描,表示第几行for j = 1 : NumLCU_Row %横向扫描,表示第几列Idx = (i-1) * NumLCU_Row + j;%获取当前LCU的IDuiPelX = (j-1) * LCU_Size + 1;%获取当前LCU左上角第一个像素的横坐标 uiPelY = (i-1) * LCU_Size + 1;%获取当前LCU左上角第一个像素的纵坐标PUData_Blk = PUData( (Idx-1)*MaxNumPartition + 1 : (Idx)*MaxNumPartition);%从存储PU分割尺寸信息的一维PUData文件中获取当期LCU的PU分割尺寸信息uiPelXscan1 = uiPelX;uiPelYscan1 = uiPelY;uiPelXscan2 = uiPelX;uiPelYscan2 = uiPelY;for k=1 : LCU_Height %第k行for l=1 : LCU_Width %第k行第l个元素if(PUData_Blk(16*(k-1)+l,1)~=0 && PUData_Blk(16*(k-1)+l,1)~=3 && PUData_Blk(16*(k-1)+l,1)~=8 && (uiPelXscan1 ~= uiPelX + LCU_Size - 1) && (uiPelXscan1 ~= Width))%寻找非对称分割PUuiPelXscan1 = uiPelX + (l-1) * MinOperSize;%获取NonSquare PU分割块左上角第一个像素点坐标uiPelYscan1 = uiPelY + (k-1) * MinOperSize;n=1;for m = l+1:l+15if(m>16)break;endif(PUData_Blk(16*(k-1)+m,1) == PUData_Blk(16*(k-1)+l,1))uiPelXscan2 = uiPelXscan1 + n * MinOperSize + 3;%获取当前NonSquare PU分割模式的块右上角像素的坐标uiPelYscan2 = uiPelYscan1;n=n+1;%n用于标识PU大小elsebreak;endendline([uiPelXscan1 uiPelXscan2], [uiPelYscan1 uiPelYscan2 ],'Color', 'g','LineWidth',1);line([uiPelXscan1 uiPelXscan2], [uiPelYscan1 + n * MinOperSize uiPelYscan1 + n * MinOperSize ],'Color', 'g','LineWidth',1);line([uiPelXscan1 uiPelXscan1], [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g', 'LineWidth',1);line([uiPelXscan2 uiPelXscan2], [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g', 'LineWidth',1);%PU轮廓线axis on;switch PUData_Blk(16*(k-1)+l,1)case 1 %2NxNline([uiPelXscan1 uiPelXscan2], [uiPelYscan1 + n/2 * MinOperSize uiPelYscan1 + n/2 * MinOperSize ],'Color', 'g','LineWidth',1); %画2NxN中间分割线case 2line([uiPelXscan1 + n/2 * MinOperSize uiPelXscan1 + n/2 * MinOperSize], [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g','LineWidth',1);case 4line([uiPelXscan1 uiPelXscan2], [uiPelYscan1 + n/4 * MinOperSize uiPelYscan1 + n/4 * MinOperSize ],'Color', 'g','LineWidth',1);case 5line([uiPelXscan1 uiPelXscan2], [uiPelYscan1 + n * 3/4 * MinOperSize uiPelYscan1 + n * 3/4 * MinOperSize ],'Color', 'g','LineWidth',1);case 6line([uiPelXscan1 + n/4 * MinOperSize uiPelXscan1 + n/4 * MinOperSize], [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g','LineWidth',1);case 7line([uiPelXscan1 + n * 3/4 * MinOperSize uiPelXscan1 + n * 3/4 * MinOperSize], [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g','LineWidth',1);otherwise break;endfor m = k:k+n-1for p = l:l+n-1PUData_Blk(16*(m-1)+p,1)=0;%当前PU分割数据清零,防止多次遍历同一个PUendendl=l+n;end endendendendend
fclose(Fid_YUV);
fclose(Fid_Pu);
编译通过后,在命令窗口输入 PU_View(‘….YUV文件路径BasketballDrill_832x480_50.yuv’,’…..Pupartion文件路径Win32\Debug\PuPartion.txt’,832,480,5),5代表帧数
得到一帧最终PU分割模式图:
这篇关于MatLab画PU分割模式图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!