matlab實現視頻運動向量搜索

轉載https://blog.csdn.net/RachelKong/article/details/54376979

實驗四 運動向量的預測

一、問題描述

利用matlab,導入YUV格式的視頻,選擇第一幀的某一位置爲目標宏塊,第2、3、5、10、20、50、100幀爲參考幀,實現順序搜索算法(採用絕對誤差測量)對目標宏塊進行運動向量的預測,再實現2D對數搜索算法(採用絕對誤差測量)對目標宏塊進行運動向量的預測。實驗中自行設置搜索窗口的大小和9個參考點的位置,並對這兩個參數對實驗結果的影響進行分析。(視頻的分辨率352*288,共300幀。展示在不同參考幀上得到的結果並進行分析,分析不同的搜索窗口大小和參考點位置對實驗性能的影響,解釋順序搜索和2D對數搜索得到的結果是否最優。)

二、問題分析

一段視頻的時間冗餘是比較顯著的,利用這個特徵,可以將當前幀與其他幀的差值進行編碼,探測相應像素或區域的移動並測量它們的差值來“補償”這些運動。採用該方法的視頻壓縮算法被稱爲基於運動補償(MC)的壓縮算法,算法一般有三步:(1)運動估計(2)基於運動補償的預測(3)預測誤差的生成——差值。本次實驗,需要實現運動向量的搜索。

搜索的目標是找到一個向量(i,j)作爲運動向量MV(u,v),使得平均絕對誤差(MAD)最小。(書本P201公式)

2.1順序搜索

尋找運動向量最簡單的方法是順序搜索參考幀中整個(2p+1)(2p+1)大小的窗口。將該窗口中的每一個宏塊逐個像素地和目標幀中的宏塊進行比較,得到各自的MAD值,MAD最小的向量即爲目標幀中宏塊的運動向量。

2.2 2D對數搜索

對數搜索雖然不是最優方法, 通常卻是非常有效的一個辦法,且代價較低。在搜索窗口中只有9個位置被標記爲1,它們作爲基於MAD搜索的起始位置。當MAD最小值的位置確定後,將新的搜索區域中心移動到該位置,搜索的步長(偏移)減半。在下一次迭代中,9個新的位置爲標記爲2,依次類推。

計算複雜度爲O(logp·N^2),與順序搜索的O(p^2N^2)相比,有很大的改善。

三、算法分析與詳細設計

3.1順序搜索算法

在-p到p的窗口範圍內搜索最小MAD的宏塊進行運動向量的匹配。

Min_MAD=LARGE_NUMBER;

For i=-p to p

   For j=-p to p

{

  Cur_MAD=MAD(i,j);

  If cur_MAD<min_MAAD

    {

   Min_MAD=cur_MAD;

   u=i;//get the coordinates for MV

   v=j;

}

}

Matlab實現:

function [ u,v ] = SequenceSearch(target,ref,p,N,x0,y0)

%SequenceSearch 順序搜索

%  依次搜索宏塊,找到全局中的最優解

%target爲目標幀,ref爲參考幀,p指示窗口大小(2*p+1),

%N指示宏塊大小,x0,y0爲宏塊中心座標

%u v爲找到的匹配宏塊中心座標

 

%擴大尺寸,防止窗口越界

target=EnlargeSize(target,p);

ref=EnlargeSize(ref,p);

 

%全搜索算法

 

LARGE_NUM=9999999999999;

min_MAD=LARGE_NUM;

cur_MAD=0;%當前的平均絕對誤差

x=x0-N/2;

y=y0-N/2;%目標宏塊的左上角頂點座標,作爲原點

 

diff=zeros(N,N);%誤差圖

 

      for  i=-p:p

           for j=-p:p%(i,j)表示子塊在參考幀搜索的位置

             cur_MAD=sum(sum(target(x:x+N,y:y+N)-ref(x +i:x+i+N,y+j:y+j+N)))/(N^2);

            if cur_MAD<min_MAD

                min_MAD=cur_MAD;

                u=i;

                v=j;

            end;

           end;

      end;

 

      %繪製誤差圖

      for i=1:N

          for j=1:N

              diff(i,j)=target(x+i,y+j)-ref(x+u+i,y+v+j);

          end;

      end;

     

      figure,imshow(target,[]);

      title('target frame');

      figure,imshow(ref,[]);

      title('reference frame');

      frmdiff=target-ref;

      figure,imshow(frmdiff,[]);

      title('difference between two frames');

      figure,imshow(diff,[]);

      disp('順序搜索 運動向量 ');disp(u);disp(v);

      title('difference in the macroblock');

 

end

 

3.2 2D對數搜索

每次選取9個位置進行對比,找到最小MAD所在的中心點,將搜索範圍折半,繼續搜索,直到偏置值爲1,進行最後一次搜索,確定匹配宏塊。

Offset=;

Specify 9 macroblocks within the search window in the Reference frame,

They are centered at (x0,y0) and separated by offset horizontally and/or vertically;

WHILE last!=TRUE

  {

    Find one of the 9 specified macroblocks that yields minimum MAD;

    If offset=1 then last=TRUE;

    Offset=;

    Form a search region with the new offset and new center found;

}

Matlab實現:

function [ u,v ] = LogSearch( target,ref,p,N,x0,y0 )

%LogSearch 2D對數搜索函數

%   進行2D對數搜索,每次選取9個位置進行對比

 

%擴大尺寸,防止窗口越界

target=EnlargeSize(target,p);

ref=EnlargeSize(ref,p);

 

%2D對數搜索

LARGE_NUM=9999999999999;

min_MAD=LARGE_NUM;

cur_MAD=0;%當前的平均絕對誤差

x=x0-N/2;

y=y0-N/2;%目標宏塊的左上角頂點座標,作爲原點

diff=zeros(N,N);%誤差圖

 

offset=ceil(p/2);

 

%9個點的位置自行定義。

%這裏以target裏目標宏塊的中心位置作爲中心擴展開來

%cp0  cp1  cp2

%cp3 cp4 cp5

%cp6 cp7 cp8

cp=cell(1,9);

cp0.val=ref(x0-offset,y0-offset);cp0.x=x0-offset;cp0.y=y0-offset;

cp1.val=ref(x0,y0-offset);cp1.x=x0;cp1.y=y0-offset;

cp2.val=ref(x0+offset,y0-offset);cp2.x=x0+offset;cp2.y=y0-offset;

cp3.val=ref(x0-offset,y0);cp3.x=x0-offset;cp3.y=y0;

cp4.val=ref(x0,y0);cp4.x=x0;cp4.y=y0;

cp5.val=ref(x0+offset,y0);cp5.x=x0+offset;cp5.y=y0;

cp6.val=ref(x0-offset,y0+offset);cp6.x=x0-offset;cp6.y=y0+offset;

cp7.val=ref(x0,y0+offset);cp7.x=x0;cp7.y=y0+offset;

cp8.val=ref(x0+offset,y0+offset);cp8.x=x0+offset;cp8.y=y0+offset;

cp{1}=cp0;

cp{2}=cp1;

cp{3}=cp2;

cp{4}=cp3;

cp{5}=cp4;

cp{6}=cp5;

cp{7}=cp6;

cp{8}=cp7;

cp{9}=cp8;

 

last=0;

while(last~=1)

    for i=1:9

        cur_MAD=sum(sum(target(x:x+N,y:y+N)-ref(cp{i}.x-N/2:cp{i}.x+N/2,cp{i}.y-N/2:cp{i}.y+N/2)))/(N^2);

        if cur_MAD<min_MAD

            min_MAD=cur_MAD;

            u=cp{i}.x;

            v=cp{i}.y;

        end;

    end;

    if offset==1

        last=1;

    end;

    offset=ceil(offset/2);

    cp{1}.x=u-offset;cp{1}.y=v-offset;

    cp{2}.x=u;cp{2}.y=v-offset;

    cp{3}.x=u+offset;cp{3}.y=v-offset;

    cp{4}.x=u-offset;cp{4}.y=v;

    cp{5}.x=u;cp{5}.y=v;

    cp{6}.x=u+offset;cp{6}.y=v;

    cp{7}.x=u-offset;cp{7}.y=v+offset;

    cp{8}.x=u;cp{8}.y=v+offset;

    cp{9}.x=u+offset;cp{9}.y=v+offset;

   

end;

 

  %繪製誤差圖

      for i=1:N

          for j=1:N

              diff(i,j)=target(x+i,y+j)-ref(u-N/2+i,v-N/2+j);

          end;

      end;

      

       figure,imshow(target,[]);

      title('target frame');

      figure,imshow(ref,[]);

      title('reference frame');

      frmdiff=target-ref;

      figure,imshow(frmdiff,[]);

      title('difference between two frames');

      figure,imshow(diff,[]);

      disp('對數搜索 運動向量 ');disp(u-x0);disp(v-y0);

      title('difference in the macroblock');

     

end

 

3.3主體程序

讀取視頻文件,提取指定幀。

首先查詢了matlab的VideoReader方法,得到的obj結構體有如下元素:

Name - -視頻文件名

Path – 視頻文件路徑

Duration – 視頻的總時長(秒)

FrameRate - -視頻幀速(幀/秒)

NumberOfFrames – 視頻的總幀數

Height – 視頻幀的高度

Width – 視頻幀的寬度

BitsPerPixel – 視頻幀每個像素的數據長度(比特)

VideoFormat – 視頻的類型, 如 ‘RGB24’.

Tag – 視頻對象的標識符,默認爲空字符串”

Type – 視頻對象的類名,默認爲’VideoReader’.

Read(obj,i)可以獲取該視頻對象的第i幀。

但是該方法不支持YUV格式的視頻,搜索後得知,必須自己編寫讀取YUV格式視頻的函數。

打開文件後,計算一幀圖像中的總圖像個數,通過fseek函數定位到視頻中,分別創建Y U V分量,將每一幀的對應數值存放進分量中。

function [ Y,U,V ] = yuv_import(filename,dims,numfrm,startfrm)

%yuv_import 讀取YUV格式的視頻

%   讀入YUV視頻分別獲得Y U V分量的數據

%filename爲文件路徑,dims爲圖像的分辨率大小[width height],numfrm爲幀數

fid=fopen(filename,'r');

if(fid<0)

    error('File does not exist!');

end;

Yd=zeros(dims(1),dims(2));

UVd=zeros(dims(1)/2,dims(2)/2);

 

frelem=numel(Yd)+2*numel(UVd);%一幀圖像總的像素個數

%if we have the 'starting frame'

if(nargin==4)

    fseek(fid,startfrm*frelem,0);

end;

Y=cell(1,numfrm);

U=cell(1,numfrm);

V=cell(1,numfrm);

for i=1:numfrm

    Yd=fread(fid,[dims(1) dims(2)],'uint8');

    Y{i}=Yd';

    UVd=fread(fid,[dims(1)/2 dims(2)/2],'uint8');

    U{i}=UVd';

    UVd=fread(fid,[dims(1)/2 dims(2)/2],'uint8');

    V{i}=UVd';

end;

end

 

四、實驗結果分析

4.1 順序搜索算法

參考幀

窗口大小參數P

宏塊大小N

所得運動向量

2

5

16

5 5

2

20

16

-6 -18

2

5

32

5 5

10

5

16

5 5

100

5

16

5 1

3

5

16

5 5

5

5

16

5 5

20

5

16

5 5

50

5

16

5 1

 

參考幀爲第二幀,選取中央的宏塊,p=5,N=16,用順序搜索算法得到的結果是:

 

運動向量爲(5,5)。

p=20,N=16,得出運動向量爲(-6,-18):

 

p=5,N=32,得到運動向量爲(5,5):

 

參考幀爲第10幀,p=5,N=16,運動向量爲(5,5):

 

參考幀爲第100幀,運動向量爲(5,1):

 

4.2 2D對數搜索

參考幀

窗口大小參數P

宏塊大小N

所得運動向量

2

5

16

6 6

2

20

16

-6 -18

2

5

32

6 6

10

5

16

6 6

100

5

16

6 0

3

5

16

6 6

5

5

16

6 6

20

5

16

6 6

50

5

16

6 1

2

10

16

11 11

2

50

16

-26 13

對應的圖像顯示:

 

 

 

 

 

4.3綜合分析

通過多組實驗數據的比較,可以發現,宏塊大小對運動向量的預測結果影響較小,對運算速度產生一定的影響,宏塊擴大後運算量增大,速度減慢。而窗口大小對運動向量的預測結果影響是較大的,不同的窗口大小會導致預測的運動向量發生較大幅度的改變,這可能是因爲相較於宏塊大小,窗口過大時,較爲單一的畫面會引導算法找到不正確的匹配宏塊,窗口過小時,可能會找不到匹配的宏塊,而選取了其他相似的宏塊。

對於2D對數搜索算法,點的選取對實驗結果有一定影響,如果選取的點很密集,範圍很小,可能會導致較差的結果,找不到正確的匹配宏塊、從而得到錯誤的運動向量。選取的點分佈較散時,能夠通過折半查找迅速找到更接近匹配宏塊的區域,這是因爲區域之間的亮度值具有一定的連續性。

順序搜索是一種全局搜索,得到的結果是最優的,但是運算速度很慢,隨着宏塊、窗口大小的增大,運算量會迅速增大,代價極高。而2D對數搜索雖然未必得到最優結果,性能卻較好,能夠在較短的時間內找到與目標宏塊近似匹配的宏塊。

五、實驗總結

通過本次實驗,瞭解了YUV格式視頻的讀取與處理,深入理解了兩種運動向量搜索的算法,並進行了運動向量的預測。提取出Y通道的灰度值進行宏塊的匹配與運動向量的預測,因爲灰度值能夠基本代表幀中像素的情況,從而反映運動趨勢。通過改變窗口大小、宏塊大小、特徵點的選取等參數,對實驗結果進行了一定的比對分析,得到了以下結論:(1)宏塊大小對於運動向量的搜索結果產生的影響較小,對運算速度會造成一定影響。(2)窗口大小對於運動向量的順序搜索結果產生的影響較大,時間開銷增大的同時、精確度也降低;對於對數搜索時間方面的影響不大,但是精確度也降低。(3)點的位置的選取對於對數搜索的實驗結果有一定影響,當選取的點過於密集時,可能會產生錯誤的匹配結果。

另外,雖然Y通道的亮度值基本可以代表圖像特徵,也可以對UV通道進行運動向量的搜索,因爲顏色也是重要的圖像特徵之一。搜索方法是類似的,只是針對不同採樣的視頻,UV通道的數據量不同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章