MatLab画PU分割模式图

来源:互联网 发布:java常用的技术有哪些 编辑:程序博客网 时间:2024/04/24 18:01

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 Y    ImgData_U = fread(Fid_YUV ,[Width/2, Height/2], 'uint8');  % image data U    ImgData_V = fread(Fid_YUV ,[Width/2, Height/2], 'uint8');  % image data V    ImgData = 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_Size        line([i*LCU_Size, i*LCU_Size], [1 Height],'Color', 'r','LineWidth',2) %划纵向线    end    for i = 1 : Height/LCU_Size        line([1 Width], [i*LCU_Size, i*LCU_Size],'Color', 'r','LineWidth',2)%划横向线    end    for i = 1 : NumLCU_Col %纵向扫描,表示第几行        for j = 1 : NumLCU_Row %横向扫描,表示第几列            Idx = (i-1) * NumLCU_Row + j;%获取当前LCU的ID            uiPelX = (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))%寻找非对称分割PU                    uiPelXscan1 = uiPelX + (l-1) * MinOperSize;%获取NonSquare PU分割块左上角第一个像素点坐标                    uiPelYscan1 = uiPelY + (k-1) * MinOperSize;                    n=1;                    for m = l+1:l+15                        if(m>16)                            break;                        end                       if(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大小                       else                           break;                       end                    end                    line([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 %2NxN                         line([uiPelXscan1 uiPelXscan2], [uiPelYscan1 + n/2 * MinOperSize uiPelYscan1 + n/2 * MinOperSize ],'Color', 'g','LineWidth',1); %画2NxN中间分割线                      case 2                         line([uiPelXscan1 + n/2 * MinOperSize uiPelXscan1 + n/2 * MinOperSize],  [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g','LineWidth',1);                      case 4                         line([uiPelXscan1 uiPelXscan2], [uiPelYscan1 + n/4 * MinOperSize uiPelYscan1 + n/4 * MinOperSize ],'Color', 'g','LineWidth',1);                      case 5                         line([uiPelXscan1 uiPelXscan2], [uiPelYscan1 + n * 3/4 * MinOperSize uiPelYscan1 + n * 3/4  * MinOperSize ],'Color', 'g','LineWidth',1);                      case 6                         line([uiPelXscan1 + n/4 * MinOperSize uiPelXscan1 + n/4 * MinOperSize],  [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g','LineWidth',1);                      case 7                         line([uiPelXscan1 + n * 3/4 * MinOperSize uiPelXscan1 + n * 3/4 * MinOperSize],  [uiPelYscan1 uiPelYscan1 + n * MinOperSize],'Color', 'g','LineWidth',1);                        otherwise                              break;                    end                     for m = k:k+n-1                        for p = l:l+n-1                            PUData_Blk(16*(m-1)+p,1)=0;%当前PU分割数据清零,防止多次遍历同一个PU                        end                    end                    l=l+n;                end                end            end        end    endendfclose(Fid_YUV);fclose(Fid_Pu);

编译通过后,在命令窗口输入 PU_View(‘….YUV文件路径BasketballDrill_832x480_50.yuv’,’…..Pupartion文件路径Win32\Debug\PuPartion.txt’,832,480,5),5代表帧数
得到一帧最终PU分割模式图:

这里写图片描述

0 0
原创粉丝点击