運動物體檢測——光流法(攝像機固定)

 轉自http://blog.csdn.net/xlvector/article/details/589380

前面的一篇文章談了高斯背景模型在運動物體檢測中的應用。本文主要討論另一種方法——光流法。與高斯背景模型的方法不同,光流法可以用於攝像機固定和攝像機運動的情形,但本文只就攝像機固定的情況進行討論,即不涉及攝像機運動預測問題。

光流法的介紹

在空間中,運動可以用運動場描述。而在一個圖像平面上,物體的運動往往是通過圖像序列中不同圖象灰度分佈的不同體現的。從而,空間中的運動場轉移到圖像上就表示爲光流場,光流場反映了圖像上每一點灰度的變化趨勢。

光流可以看作帶有灰度的像素點在圖像平面運動產生的瞬時速度場。下面我們推導光流方程:

假設E(x,y,t)爲(x,y)點在時刻t的灰度(照度)。設t+dt時刻該點運動到(x+dx,y+dy)點,他的照度爲E(x+dx,y+dy,t+dt)。我們認爲,由於對應同一個點,所以

E(x,y,t) = E(x+dx,y+dy,t+dt)   —— 光流約束方程

將上式右邊做泰勒展開,並令dt->0,則得到:Exu+Eyv+Et = 0,其中:

Ex = dE/dx   Ey = dE/dy   Et = dE/dt   u = dx/dt   v = dy/dt

上面的Ex,Ey,Et的計算都很簡單,用離散的差分代替導數就可以了。光流法的主要任務就是通過求解光流約束方程求出u,v。但是由於只有一個方程,所以這是個病態問題。所以人們提出了各種其他的約束方程以聯立求解。但是由於我們用於攝像機固定的這一特定情況,所以問題可以大大簡化。

攝像機固定的情形

在攝像機固定的情形下,運動物體的檢測其實就是分離前景和背景的問題。我們知道對於背景,理想情況下,其光流應當爲0,只有前景纔有光流。所以我們並不要求通過求解光流約束方程求出u,v。我麼只要求出亮度梯度方向的速率就可以了,即求出sqrt(u*u+v*v)。

而由光流約束方程可以很容易求到梯度方向的光流速率爲 V = abs(Et/sqrt(Ex*Ex+Ey*Ey))。這樣我們設定一個閾值T。

V(x,y) > T 則(x,y)是前景 ,反之是背景

C++實現

在實現攝像機固定情況的光流法時,需要有兩幀連續的圖像,下面的算法針對RGB24格式的圖像計算光流:

void calculate(unsigned char* buf)
 {
  int Ex,Ey,Et;
  int gray1,gray2;
  int u;
  int i,j;
  memset(opticalflow,0,width*height*sizeof(int));
  memset(output,255,size);
  for(i=2;i<height-2;i++){
   for(j=2;j<width-2;j++){
    gray1 = int(((int)(buf[(i*width+j)*3])
     +(int)(buf[(i*width+j)*3+1])
     +(int)(buf[(i*width+j)*3+2]))*1.0/3);
    gray2 = int(((int)(prevframe[(i*width+j)*3])
     +(int)(prevframe[(i*width+j)*3+1])
     +(int)(prevframe[(i*width+j)*3+2]))*1.0/3);
    Et = gray1 - gray2;
    gray2 = int(((int)(buf[(i*width+j+1)*3])
     +(int)(buf[(i*width+j+1)*3+1])
     +(int)(buf[(i*width+j+1)*3+2]))*1.0/3);
    Ex = gray2 - gray1;
    gray2 = int(((int)(buf[((i+1)*width+j)*3])
     +(int)(buf[((i+1)*width+j)*3+1])
     +(int)(buf[((i+1)*width+j)*3+2]))*1.0/3);
    Ey = gray2 - gray1;
    Ex = ((int)(Ex/10))*10;
    Ey = ((int)(Ey/10))*10;
    Et = ((int)(Et/10))*10;
    u = (int)((Et*10.0)/(sqrt((Ex*Ex+Ey*Ey)*1.0))+0.1);
    opticalflow[i*width+j] = u;
    if(abs(u)>10){
     output[(i*width+j)*3] = 0;
     output[(i*width+j)*3+1] = 0;
     output[(i*width+j)*3+2] = 0;
    }
   }
  }
  memcpy(prevframe,buf,size);
 }

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