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 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
    end


end
fclose(Fid_YUV);
fclose(Fid_Pu);

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

这里写图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值