H264-预测

H264-预测

在这里插入图片描述
预测分为帧内预测和帧间预测,I 帧中的宏块都是帧内预测。

帧内预测

在这里插入图片描述
帧内预测分为两部分:帧内预测模式的选择和帧内预测的执行。图中block P就是当选择intra 预测是产生的结果。block P由当前块和上一个重建块决定。

帧内预测类型

预测类型包括预测块尺寸和预测模式两个元素。
在这里插入图片描述
对于亮度分量,有三种预测块尺寸可供选择16x16,8x8(只在high profile中用到),4x4。对于色度分量,分量只有一个8x8。
当选中一种预测尺寸时,根据编码块的性质选择可用的且最优的预测模式,宏块或者子宏块的预测模式就要作为一个元素传递给解码器。
同样预测尺寸的选择也是需要做为一个元素传递给解码器。所以预测模式选择考量的两个因素是:

  1. 预测效率(还原原始图像的效率)
  2. 预测模式附件元素信息的开销(编码后的bit数)

所以有小块尺寸和大块尺寸的block:

  • 小块:小块的预测块尺寸时4x4,小块的尺寸能给出更加精确的预测(图像空间上越接近,相关性越强). 这时帧内预测的数据更加接近实际数据,就会得到更小的残差,结果就是需要更少的bit数来编码残差变换系数。不过,使用4x4的预测尺寸时,每个4x4块都需要带有预测模式选择元素,这就需要附件的bit来表示这个元素。
  • 大块:大块的预测尺寸获得稍差些的精度,会有较大的残差,但是会有更少的bit数来编码模式选择元素。

编码器需要选择最合适的预测模式来最小化预测和残差的bit数。

4*4 亮度预测模式

在这里插入图片描述
在这里插入图片描述

如上图所示是将要进行预测的4x4block,在上方和左边的像素A-M是已经编码和重建的,**变换和量化编码过程都是基于4x4block进行,在进行预测下一个4x4block时,基本上存在上边或者左边的block都已经处理过,这就是使用上边和左边进行预测的原因。**并同时存在于encoder和decoder的数据,这些数据可以用来作参考。a-p表示预测块P的像素,需要根据选择预测模式和参考数据计算得到。模式2直流预测中,在需要的sample中有可用的sample即可进行预测。其他模式必须所有需要的sample均可用时才能进行该预测。如下图所示的预测模式中,预测的方向由箭头表示。斜线穿过的sample的值有斜线起始位置三个sample决定。如在mode 4中,c和h两个位置的sample的值为 round(A/4 + B/2 + C/4)
在这里插入图片描述

预测模式matlab

mode 0 垂直模式

%-------------------------------------------------------
%% 4x4 Vertical Prediciton

function [icp,pred,sae] = pred_vert_4(Seq,Seq_r,i,j)

pred = ones(4,1)*Seq_r(i-1,j:j+3);
icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

%-------------------------------------------------------

mode 1 水平模式

%% 4x4 Horizontal prediciton

function [icp,pred,sae] = pred_horz_4(Seq,Seq_r,i,j)

pred = Seq_r(i:i+3,j-1)*ones(1,4);
icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

%-------------------------------------------------------

mode 2 直流预测

%% 4x4 DC prediction

function [icp,pred,sae] = pred_dc_4(Seq,Seq_r,i,j)

pred = bitshift(sum(Seq_r(i-1,j:j+3))+ sum(Seq_r(i:i+3,j-1))+4,-3, 'int8');
icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

%--------------------------------------------------------

mode 3 对角左下

%--------------------------------------------------------
function [icp,pred,sae] = pred_ddl_4(Seq,Seq_r,i,j)

Seq_r(i-1,j+4:j+7)=Seq_r(i,j + 3);

for x = 0:3
    for y = 0:3
        if (x==3)&(y==3)
            pred(x+1,y+1) = bitshift(Seq_r(i-1,j+6) + 3*Seq_r(i -1,j +7) + 2,-2, 'int32');
        else
            pred(x+1,y+1) = bitshift(Seq_r(i-1,j + x + y) + 2*Seq_r(i-1,j + x + y + 1) + Seq_r(i-1,j + x +y +2) + 2,-2, 'int32');
        end
    end
end
icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

mode 4 对角右下

%--------------------------------------------------------
function [icp,pred,sae] = pred_ddr_4(Seq,Seq_r,i,j)

for x = 0:3
    for y = 0:3
        if (x>y)
            pred(x+1,y+1) = bitshift(Seq_r(i+x-y-2,j-1) + 2*Seq_r(i+x-y-2,j-1) + Seq_r(i+x-y,j-1) + 2,-2);
        elseif (x<y)
            pred(x+1,y+1) = bitshift(Seq_r(i-1,j+y-x-2) + 2*Seq_r(i-1,j+y-x-1) + Seq_r(i-1,j+y-x) + 2,-2);
        else
            pred(x+1,y+1) = bitshift(Seq_r(i,j-1) + 2*Seq_r(i-1,j-1) + Seq_r(i-1,j) + 2,-2);
        end
    end
end

icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

mode 5 垂直偏右

%--------------------------------------------------------
function [icp,pred,sae] = pred_vr_4(Seq,Seq_r,i,j)

for x = 0:3
    for y = 0:3
        z = 2*x-y;
        w = bitshift(y,-1);
        if rem(z,2)==0
            pred(x+1,y+1)= bitshift(Seq_r(i+x-w-1,j-1) + Seq_r(i+x-w,j-1) + 1,-1);
        elseif rem(z,2)==1
            pred(x+1,y+1)= bitshift(Seq_r(i+x-w-2,j-1) + 2*Seq_r(i+x-w-1,j-1) + Seq_r(i+x-w,j-1) + 2,-2);
        elseif z==-1
            pred(x+1,y+1)= bitshift(Seq_r(i-1,j)+ 2*Seq_r(i-1,j-1) + Seq_r(i,j-1) + 2,-2);
        else
            pred(x+1,y+1) = bitshift(Seq_r(i-1,j+y-1)+ 2*Seq_r(i-1,j+y-2) + Seq_r(i-1,j+y-3) + 2,-2);
        end
    end
end

icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

mode 6 水平偏下

%--------------------------------------------------------
function [icp,pred,sae] = pred_hd_4(Seq,Seq_r,i,j)

for x = 0:3
    for y = 0:3
        z = 2*y-x;
        w = bitshift(x,-1);
        if rem(z,2)==0
            pred(x+1,y+1)= bitshift(Seq_r(i-1,j+y-w-1) + Seq_r(i-1,j+y-w) + 1,-1);
        elseif rem(z,2)==1
            pred(x+1,y+1)= bitshift(Seq_r(i-1,j+y-w-2) + 2*Seq_r(i-1,j+y-w-1) + Seq_r(i-1,j+y-w) + 2,-2);
        elseif z==-1
            pred(x+1,y+1)= bitshift(Seq_r(i-1,j)+ 2*Seq_r(i-1,j-1) + Seq_r(i,j-1) + 2,-2);
        else
            pred(x+1,y+1) = bitshift(Seq_r(i+x-1,j-1)+ 2*Seq_r(i+x-2,j-1) + Seq_r(i+x-3,j-1) + 2,-2);
        end
    end
end

icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

%--------------------------------------------------------

mode 7 垂直偏左

%--------------------------------------------------------
function [icp,pred,sae] = pred_vl_4(Seq,Seq_r,i,j)

Seq_r(i+4:i+7,j-1)=Seq_r(i+3,j-1);

for x = 0:3
    for y = 0:3
        w = bitshift(y,-1);
        if rem(y,2)==0
            pred(x+1,y+1) = bitshift(Seq_r(i+x+w,j-1) + Seq_r(i+x+w+1,j-1) + 1,-1);
        else
            pred(x+1,y+1) = bitshift(Seq_r(i+x+w,j-1) + 2*Seq_r(i+x+w+1,j-1) + Seq_r(i+x+w+2,j-1) + 2,-2);
        end
    end
end

icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));

mode 8 水平偏上

%--------------------------------------------------------
function [icp,pred,sae] = pred_hu_4(Seq,Seq_r,i,j)

for x = 0:3
    for y = 0:3
        z = 2*y+x;
        w = bitshift(x,-1);
        if (z==0)|(z==2)|(z==4)
            pred(x+1,y+1)= bitshift(Seq_r(i-1,j+y+w) + Seq_r(i-1,j+y+w+1) + 1,-1);
        elseif (z==1)|(z==3)
            pred(x+1,y+1)= bitshift(Seq_r(i-1,j+y+w) + 2*Seq_r(i-1,j+y+w+1) + Seq_r(i-1,j+y+w+2) + 2,-2);
        elseif z==5
            pred(x+1,y+1)= bitshift(Seq_r(i-1,j+2)+ 3*Seq_r(i-1,j+3) + 2,-2);
        else
            pred(x+1,y+1) = Seq_r(i-1,j+3);
        end
    end
end

icp = Seq(i:i+3,j:j+3,1) - pred;
sae = sum(sum(abs(icp)));
16x16亮度预测模式

上边的4x4 预测模式,是在前面的4x4块重建完成才进行下边的操作。作为一个替换方式,整个16x16宏块可以在一次操作中进行预测。四种方式如下表所示:
在这里插入图片描述

色度预测模式

色度预测模式的四种类型类似于16x16的亮度预测模式

8x8亮度预测模式

类似于4x4的9种亮度预测模式

帧内预测模式类型的传输

每个4x4块或者8x8块的帧内预测模式选择必须传输给解码器,这个需要很多bit位。block和block之间的预测模式有很大的相关性。如下图,blockE 根据block A和B进行预测。预测方法是选择A和B中最小的那个模式。如果A和B都不可用,则选择mode 2
在这里插入图片描述
每个4x4block 都带有prev_intra4×4_pred_mode标记

  • 当标记的值为1,则按照上边描述的方式选择最大可能预测模式
  • 当标记值为0时,需要使用rem_intra4×4_pred_mode标记,如果rem_intra4x4_pred_mode的值小于最大可能预测模式,则预测模式的值设置为rem_intra4x4_pred_mode; 如果rem_intra4x4_pred_mode的值大于最大可能预测模式时,预测模式设置为rem_intra4x4_pred_mode +1.

帧间预测

帧间预测是以编码过的图像为参考,预测亮度或者色度的过程。这包括选择一个预测区域、生成一个预测块、将预测块与原始图像数据相减获得将要进行编码和传输的残差数据。
参考图像是从图像缓冲中取得的之前编码的图像。这个图像的显示顺序可能在当前图像之前或者之后。当前区域和参考图像的预测区域之间的偏移是移动向量。移动向量可能指向整数个像素,半整数或者四分之一像素的单位。半像素或者四分之一像素是通过对参考图像的像素进行插值获得的。
在这里插入图片描述
如上图,当前帧的宏块分成8x16的A和B两部分,A从参考帧n-1的A区域进行预测。B从参考帧n-2的B区域预测得到。A的运动矢量为(-6.5,-5.75),B的运动矢量为(-1.25,-4)
总结帧间宏块预测的主要过程:

  • 在解码图像缓冲区中进行插值,产生四分之一亮度采样和八分之一色度采样的数据。
  • 使用下面的步骤选择帧间预测模式:
    (a) 选择参考帧
    (b) 选择宏块区域和子宏块区域,预测块尺寸
    (c)选择预测类型
  • 选择宏块区域或者子宏块区域的运动矢量。
  • 从之前传输的运动矢量中预测运动矢量
  • 编码宏块类型
  • 进行去方块滤波

参考图像

参考图像插值

每一个帧间编码宏块的区域都是从参考图像的相同尺寸的区域预测得到。两个区域的偏移,就是移动向量对于亮度来说是1/4像素精度,对于色度来说是1/8像素精度。亮度和色度在子像素位置上的采样在参考图片中是不存在的,因此它需要根据周围像素进行插值得到。
在这里插入图片描述
中间的图参考图像宏块是实际存在的宏块,右侧的图参考宏块是插值后的宏块。
插值的好处是可以更好的获得当前block和预测block的最佳匹配。

生成插值子像素
宏块分区

每一个16*16 宏块用一系列块来进行预测。宏块被分成一个,两个或者四个宏块分区。

  • 一个16*16 宏块分区
  • 两个8 *16 宏块分区
  • 两个16* 8 宏块分区
  • 四个 8* 8 宏块分区

每一个宏块分区和子宏块分区有一个或者两个移动向量(x,y), 每一个指向用来预测当前分区的参考帧的一个相同尺寸大小的区域。P宏块中的分区有一个参考帧和一个移动向量。B宏块中的分区有一个或者两个参考帧并且有一个或者两个相应的运动矢量。每一个宏块分区有可能从不同的参考帧中预测得到。

运动向量预测

对每一个分区编码一个运动向量需要很多bit数,尤其选择小分区尺寸时。相邻分区的运动向量是高度相关的,因此每一个运动向量都是从附近的运动向量中预测得到。预测向量MVP 基于之前计算的运动向量和MVD, 当前向量和预测向量之差被编码和传输
在这里插入图片描述
在这里插入图片描述
E是当前宏块,宏块分区或者子宏块分区,设A是E左边的分区或子宏块分区,设B是E上边的分区或子宏块分区。设C是E右上的分区或者子宏块分区。如果在E左边有多个分区,那么最高的那个分区被选作A. 如果在E的上边有多个分区,那么最左边的被选做B。下边的图是不同尺寸分区的选择。
在这里插入图片描述

  1. 对于16*8 和8 *16 分区尺寸来说,ABC 的MVP是A B C中中间的那个。
  2. 对于16 *8 分区,上边的16 * 8 分区从B预测得到,下边的16 * 8 分区从A 预测得到。
  3. 对于8 * 16 分区左边的 8 * 16 分区从A 预测得到,右边的8 * 16 分区从C 预测得到。
  4. 对于skipped macroblock,16 x16向量MVP由1 生成,就好像采用的是帧内编码一样。
运动补偿预测

运动补偿在这里的意思就是使用运动向量进行对参考帧block进行补偿,形成当前块的预测图像。运动向量MV是从当前block位置指向参考帧中最佳匹配的block位置。
进行运动补偿得到预测图像,预测图像与原始图像的差值是残差数据(residual data), 残差数据和mv的残差经过变换量化编码构成bit流。

P帧运动补偿例子

在这里插入图片描述
在这里插入图片描述

预测结构

提供多种方式来为帧间预测选择参考帧

低延迟最小存储

P帧编码 matlab 实例

function [Seq_r,bits_frame] = encode_p_frame(Seq,Quant,flag,block_size)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This script/function was created by 
% Abdullah Al Muhit
% contact - almuhit@gmail.com
% website - https://sites.google.com/site/almuhit/
% Please use it at your own risk. Also, Please cite the following paper:
% A A Muhit, M R Pickering, M R Frater and J F Arnold, 揤ideo Coding using Elastic Motion Model and Larger Blocks,?IEEE Trans. Circ. And Syst. for Video Technology, vol. 20, no. 5, pp. 661-672, 2010. [Impact factor ?3.18] [PDF]
% A A Muhit, M R Pickering, M R Frater and J F Arnold, 揤ideo Coding using Geometry Partitioning and an Elastic Motion Model,?accepted for publication in Journal of Visual Communication and Image Representation. [Impact factor ?1.33] [PDF]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% inputs are:
% Seq - array containing the previous frame and the current frame to be
% coded 参数包含两张图片 图片1 是参考帧, 图2是当前帧
% Quant - the quantization parameter 量化参数
% flag - flag to indicate whether to use extended cosine warping ME or not
%
% outputs are:
% Sr - the coded current frame
% mse - the mean-squared-error of the frame
% R - the output bitrate for the frame


% initialize some global variables:
% QP - the quantization parameter
% lambda_me - the lagrangian multiplier used in motion estimation
% lambda_mode - the lagrangian multiplier used in partition mode selection
% vlc_code_length - array containing code lengths for H.263 VLC tables
% vlc_code_length_last - array containing code lengths for H.263 VLC tables
% mvm - array containing previously calculated motion vectors
% S - array containing the previous frame and the current frame
% Sr - the coded current frame
% width - the width in pixels of the current frame
% height - the height in pixels of the current frame
% frame - the current frame to be coded
% extend - flag to indicate whether to use extended cosine warping ME
% is_ext - array used for results visualization

global QP lambda_me lambda_mode 
global mvm S Sr width height frame extend is_ext

% H.264 global params
global Table_coeff0 Table_coeff1 Table_coeff2 Table_coeff3
global Table_run Table_zeros
load table.mat

% copy input variables to global variables (in MATLAB you cannot define global
% variables that have the same name as input variables)

S = Seq;
QP = Quant;
extend = flag;


% find the height, width and number of frames in the current input sequence
% (u is always 2 in this implementation)

[height,width,u] = size(S); 

% calculate the lagrangian multipliers for the current value of QP 计算当前QP对应的拉格朗日率失真系数

lambda_mode = 0.85*(2^((QP-12)/3));
lambda_me = lambda_mode^.5;


% initialize output variables

Sr = zeros(height,width,u);
%1中放着重建帧,2中放着当前帧
Sr(:,:,1) = S(:,:,1);
mse = 0;
R = 0;
bits_frame = '';


% debugging and results visualization
% bits = zeros(height/16,width/16);
% 划分为以最小4 * 4 pixel 为单位的方格图
is_ext = zeros(height/4,width/4,4);

% figure(1)
% image(S(:,:,1)-S(:,:,2)+128)
% truesize([2*height 2*width])
% colormap(gray(256))
% drawnow

% in this implementation we are only coding P frames so "frame" is always 2

for frame = 2

    % initialize array for previously calulated motion vectors, infinity
    % indicates no motion vectors have been calculated for this pixel
    % horizontal vectors stored in mvm(:,:,1)
    % vertical vectors stored in mvm(:,:,2)
	% mvm 用来保存之前获得的运动向量
    mvm = inf.*ones(height+1,width+2,2);


    % debugging and results visualization
    figure(1)
    image(S(:,:,frame)-S(:,:,frame-1)+128)
    %显示两倍大小
    truesize([2*height 2*width])
    title('Encoding P Frame')
    drawnow

    % loop through the 16x16 macroblocks in the frame
    

    for i = 1:block_size:height

        for j = 1:block_size:width

            % bs - macroblock size
            % mr - motion vector search range

            bs = block_size;
            mr = 8;
            
            % MB header 0
            bits_frame = [bits_frame '0'];

            % determine the 16x16 partition mode
            % output variables:
            % rec_16 - the reconstructed 16x16 macroblock
            % R_16 - the output bitrate for this macroblock
            % ind_16 - partition index (1 = full, 2 = vert, 3 = horiz, 4 = quad)
            % full 表示16* 16 partition
            % vert 表示 16*8 partition
            % horiz 表示 8* 16 partition
            % quad 表示 8* 8 partition
			% mode_decision 模式决策函数 
            [rec_16,bits_16,ind_16,mvb] = mode_decision(bs,mr,i,j);


            if ind_16 < 4   % if the partition mode is not quad

                % write the reconstructed 16x16 macroblock to the output
                % array

                Sr(i:i+block_size-1,j:j+block_size-1,frame) = rec_16;
                bits_frame = [bits_frame bits_16];

            % write the block motion vectors to the array containing the motion vectors
            % for the frame

                mvm(i:i+bs-1,j:j+bs-1,1) = mvb(:,:,1);
                mvm(i:i+bs-1,j:j+bs-1,2) = mvb(:,:,2);

            else    % else find the partition mode for each 8x8 sub-block

                % bs - macroblock size
                % mr - motion vector search range

                bs = block_size/2;
                mr = 4;
                % add header for a quad split
                bits_frame =[bits_frame '00100'];

                % determine the 8x8 partition mode for each sub-block,
                % write the reconstructed 8x8 sub-block to the output
                % array and add the rate for this sub-block to the rate
                % for the frame

                [rec_8,bits_8,ind_8,mvb] = mode_decision(bs,mr,i,j);
                Sr(i:i+ bs -1,j:j+ bs -1,frame) = rec_8;
                bits_frame = [bits_frame bits_8];
                
                mvm(i:i+bs-1,j:j+bs-1,1) = mvb(:,:,1);
                mvm(i:i+bs-1,j:j+bs-1,2) = mvb(:,:,2);
                

                [rec_8,bits_8,ind_8,mvb] = mode_decision(bs,mr,i,j+ bs);
                Sr(i:i+ bs -1,j+ bs:j+ 2*bs -1,frame) = rec_8;
                bits_frame = [bits_frame bits_8];
                
                mvm(i:i+bs-1,j+bs:j+2*bs-1,1) = mvb(:,:,1);
                mvm(i:i+bs-1,j+bs:j+ 2*bs -1,2) = mvb(:,:,2);


                [rec_8,bits_8,ind_8,mvb] = mode_decision(bs,mr,i+ bs,j);
                Sr(i+ bs:i+ 2*bs -1,j:j+ bs -1,frame) = rec_8;
                bits_frame = [bits_frame bits_8];
                mvm(i+ bs:i+ 2*bs -1,j:j+bs-1,1) = mvb(:,:,1);
                mvm(i+ bs:i+ 2*bs -1,j:j+bs-1,2) = mvb(:,:,2);

                [rec_8,bits_8,ind_8,mvb] = mode_decision(bs,mr,i+bs,j+bs);
                Sr(i+ bs:i+ 2*bs -1,j+ bs:j+ 2*bs -1,frame) = rec_8;
                bits_frame = [bits_frame bits_8];
                
                mvm(i+ bs:i+ 2*bs -1,j+ bs:j+ 2*bs -1,1) = mvb(:,:,1);
                mvm(i+ bs:i+ 2*bs -1,j+ bs:j+ 2*bs -1,2) = mvb(:,:,2);

            end

        end
    end

Seq_r = Sr(:,:,frame);

end

模式决策函数

function [rec,bits_b,ind,mvb] = mode_decision(bs,mr,i,j)

global lambda_mode is_ext

% calculate the parameters for each partition mode
% output variables:
% mvb# - array containg motion vectors for the block
% rec# - array containing the reconstructed block
% mvr# - the bitrate required to transmit the motion vectors
% cfr# - the bitrate required to transmit the quantized coefficients
% ssd# - the sum-of-squared-difference for the block
% 计算四种模式
[mvb0,rec0,bits0,ssd0] = motion_comp_full(bs,mr,i,j);

[mvb1,rec1,bits1,ssd1] = motion_comp_vert(bs,mr,i,j);

[mvb2,rec2,bits2,ssd2] = motion_comp_horz(bs,mr,i,j);

[mvb3,rec3,bits3,ssd3] = motion_comp_quad(bs,mr,i,j);


% mbtr# - the bitrate required to transmit the macroblock_type parameter

% mbtr0 = 1;
% mbtr1 = 3;
% mbtr2 = 3;
% mbtr3 = 5;
cfr0 = length(bits0);
cfr1 = length(bits1);
cfr2 = length(bits2);
cfr3 = length(bits3);

% find the partitioning mode which gives the minimum lagrangian cost
% function

[y,ind] = min([(ssd0+lambda_mode*cfr0) ...
    (ssd1+lambda_mode*cfr1) ...
    (ssd2+lambda_mode*cfr2) ...
    (ssd3+lambda_mode*cfr3)]);


% for the chosen partitioning mode write the partition variables to
% variables for the block

switch ind
    case 1
        rec = rec0;
%         cfr = cfr0;
%         mvr = mvr0;
        bits_b = bits0;
        ssd = ssd0;
        mvb = mvb0;
%         mbtr = mbtr0;
%         disp('full mode')

        % debugging and results visualization
        figure(1)
        h_rect = rectangle('position',[j i bs-.5 bs-.5]);
        if is_ext((i+3)/4,(j+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        drawnow

    case 2
        rec = rec1;
%         cfr = cfr1;
%         mvr = mvr1;
        bits_b = bits1;
        ssd = ssd1;
        mvb = mvb1;
%         mbtr = mbtr1;
%         disp('vert mode')

        % debugging and results visualization
        figure(1)
        h_rect = rectangle('position',[j i bs/2-.5 bs-.5]);
        if is_ext((i+3)/4,(j+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        h_rect = rectangle('position',[j+bs/2 i bs/2-.5 bs-.5]);
        if is_ext((i+3)/4,(j+bs/2+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        drawnow

    case 3
        rec = rec2;
%         cfr = cfr2;
%         mvr = mvr2;
        bits_b = bits2;
        ssd = ssd2;
        mvb = mvb2;
%         mbtr = mbtr2;
%         disp('horz mode')

        % debugging and results visualization
        figure(1)
        h_rect = rectangle('position',[j i bs-.5 bs/2-.5]);
        if is_ext((i+3)/4,(j+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        h_rect = rectangle('position',[j i+bs/2 bs-.5 bs/2-.5]);
        if is_ext((i+bs/2+3)/4,(j+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        drawnow

    case 4
        rec = rec3;
%         cfr = cfr3;
%         mvr = mvr3;
        bits_b = bits3;
        ssd = ssd3;
        mvb = mvb3;
%         mbtr = mbtr3;
%         disp('quad mode')

        % debugging and results visualization
        figure(1)
        h_rect = rectangle('position',[j i bs/2-.5 bs/2-.5]);
        if is_ext((i+3)/4,(j+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        h_rect = rectangle('position',[j+bs/2 i bs/2-.5 bs/2-.5]);
        if is_ext((i+3)/4,(j+bs/2+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        h_rect = rectangle('position',[j i+bs/2 bs/2-.5 bs/2-.5]);
        if is_ext((i+bs/2+3)/4,(j+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        h_rect = rectangle('position',[j+bs/2 i+bs/2 bs/2-.5 bs/2-.5]);
        if is_ext((i+bs/2+3)/4,(j+bs/2+3)/4,ind)
            set(h_rect,'linestyle','-');
        else
            set(h_rect,'linestyle','-');
            set(h_rect,'edgecolor',[1 1 1]);
        end
        drawnow

end
%--------------------------------------------------------------------------

function [mvb,rec,bits_b,ssd] = motion_comp_full(bs,mr,i,j)

global mode


% mode - variable indicating which partitioning mode to use for the block

mode = 1;

bits_b = '1';

% calculate the motion parameters for one partition consisting of the whole
% block
% mvx - horizontal motion vector
% mvy - vertical motion vector

[mvx,mvy,rec,bits,ssd] = motion_comp_block(bs,bs,mr,i,j,'m');
bits_b = [bits_b bits];

mvb(:,:,1) = mvx.*ones(bs,bs);
mvb(:,:,2) = mvy.*ones(bs,bs);

%--------------------------------------------------------------------------

function [mvx,mvy,rec,bits_b,ssd] = motion_comp_block(bsx,bsy,mr,i,j,mvp_mode)

global lambda_mode mvm S Sr width height frame extend is_ext mode

bits_b = '0';


% extract the search window from the previous reconstructed frame
% 从参考帧中获得查找窗口的内容,有0的用镜像的方式进行padding,在这里查找窗口是32*32大小,步长为8
swr = mirror_pad(extract_object(Sr(:,:,frame-1),[j-mr i-mr bsx+2*mr bsy+2*mr],[1 1 width height]));


% extract the current block from the previous reconstructed frame
% 从当前帧中获得block内容,大小为16*16
curr = extract_object(S(:,:,frame),[j i bsx bsy],[1 1 width height]);


% calculate the motion vector predictions mvxp andmvyp
%预测 运动向量

switch mvp_mode
    case 'm'
        [mvxp,mvyp] = find_median_mv_pred(i,j,bsx);
    case 'a'
        [mvxp,mvyp] = find_mv_pred_a(i,j,bsx);
    case 'b'
        [mvxp,mvyp] = find_mv_pred_b(i,j,bsx);
    case 'c'
        [mvxp,mvyp] = find_mv_pred_c(i,j,bsx);
end


% calculate the motion vectors and the motion compensated prediction for
% the block
% mvx - horizontal motion vector
% mvy - vertical motion vector
% pred - motion compensated prediction block

[mvx,mvy,pred] = motion_comp(swr,curr,bsx,bsy,mr,mvxp,mvyp);

% figure(7)
% image([sw(mr+1:mr+bsy,mr+1:mr+bsx) pred curr])
% colormap(gray(256))
% mean(mean((curr-pred).^2))
% [mvx mvy]

% updated the frame motion vector arrays so that motion vectors from
% previously coded partitions of a block can be used as predictions

% mvm(i+1:i+bsy,j+1:j+bsx,1) = mvx.*ones(bsy,bsx);
% mvm(i+1:i+bsy,j+1:j+bsx,2) = mvy.*ones(bsy,bsx);


% calculate the bitrate required to transmit the motion vectors
% mvr = code_mv(mvx-mvxp,mvy-mvyp);
bits_b = [bits_b enc_golomb(4*(mvx-mvxp),1)];
bits_b = [bits_b enc_golomb(4*(mvy-mvyp),1)];

% calculate the motion-compensated difference block mcp

mcp = curr-pred;


% calculate the bitrate required to transmit the motion-compensated
% prediction block cfr and the reconstructed motion-compensated
% prediction block mcp_r

[mcp_r,bits] = code_block(mcp);
bits_b = [bits_b bits];

% calculate the reconstucted block rec

rec = mcp_r+pred;


% calculate the sum-of-squared-difference for the reconstructed block

ssd = round(sum(sum((curr-rec).^2)));
sad = sum(sum(abs(curr-rec)));

% mvr_n - the bitrate required for the motion vectors for normal ME
% cfr_n - the bitrate required for the quantized coefficients for normal ME

% mvr_n = mvr;
% cfr_n = cfr;


运动向量预测

function [mvxp,mvyp] = find_median_mv_pred(i,j,bs);

global mvm

for k = 1:2

    mvpa = mvm(i+1,j,k);
    mvpb = mvm(i,j+1,k);
    mvpc = mvm(i,j+bs+1,k);
    mvpd = mvm(i,j,k);

    
    switch bin2dec([num2str(isinf(mvpa)) num2str(isinf(mvpb)) num2str(isinf(mvpc)) num2str(isinf(mvpd))])
        case 0
            mvp(k) = median([mvpa mvpb mvpc]);
        case 1
            mvp(k) = median([mvpa mvpb mvpc]);
        case 2
            mvp(k) = median([mvpa mvpb mvpd]);
        case 3
            mvp(k) = median([mvpa mvpb]);
        case 4
            mvp(k) = median([mvpa mvpc mvpd]);
        case 5
            mvp(k) = median([mvpa mvpc]);
        case 6
            mvp(k) = median([mvpa mvpd]);
        case 7
            mvp(k) = mvpa;
        case 8
            mvp(k) = median([mvpb mvpc mvpd]);
        case 9
            mvp(k) = median([mvpb mvpc]);
        case 10
            mvp(k) = median([mvpb mvpd]);
        case 11
            mvp(k) = mvpb;
        case 12
            mvp(k) = median([mvpc mvpd]);
        case 13
            mvp(k) = mvpc;
        case 14
            mvp(k) = mvpd;
        case 15
            mvp(k) = 0;
    end
end

mvxp = mvp(1);
mvyp = mvp(2);
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值