日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

光流法的介紹(含C++代碼)

 盛夏流年閃耀 2015-10-27

光流法是比較經(jīng)典的運(yùn)動(dòng)估計(jì)方法,本文不僅敘述簡(jiǎn)單明了,而且附代碼,故收藏.

在空間中,運(yùn)動(dòng)可以用運(yùn)動(dòng)場(chǎng)描述。而在一個(gè)圖像平面上,物體的運(yùn)動(dòng)往往是通過(guò)圖像序列中不同圖象灰度分布的不同體現(xiàn)的。從而,空間中的運(yùn)動(dòng)場(chǎng)轉(zhuǎn)移到圖像上就表示為光流場(chǎng),光流場(chǎng)反映了圖像上每一點(diǎn)灰度的變化趨勢(shì)。

光流可以看作帶有灰度的像素點(diǎn)在圖像平面運(yùn)動(dòng)產(chǎn)生的瞬時(shí)速度場(chǎng)。下面我們推導(dǎo)光流方程:

假設(shè)E(x,y,t)為(x,y)點(diǎn)在時(shí)刻t的灰度(照度)。設(shè)t+dt時(shí)刻該點(diǎn)運(yùn)動(dòng)到(x+dx,y+dy)點(diǎn),他的照度為E(x+dx,y+dy,t+dt)。我們認(rèn)為,由于對(duì)應(yīng)同一個(gè)點(diǎn),所以

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

將上式右邊做泰勒展開(kāi),并令dt->0,則得到:Exu+Eyv+Et = 0,其中:

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

上面的Ex,Ey,Et的計(jì)算都很簡(jiǎn)單,用離散的差分代替導(dǎo)數(shù)就可以了。光流法的主要任務(wù)就是通過(guò)求解光流約束方程求出u,v。但是由于只有一個(gè)方程,所以這是個(gè)病態(tài)問(wèn)題。所以人們提出了各種其他的約束方程以聯(lián)立求解。但是由于我們用于攝像機(jī)固定的這一特定情況,所以問(wèn)題可以大大簡(jiǎn)化。

攝像機(jī)固定的情形

在攝像機(jī)固定的情形下,運(yùn)動(dòng)物體的檢測(cè)其實(shí)就是分離前景和背景的問(wèn)題。我們知道對(duì)于背景,理想情況下,其光流應(yīng)當(dāng)為0,只有前景才有光流。所以我們并不要求通過(guò)求解光流約束方程求出u,v。我么只要求出亮度梯度方向的速率就可以了,即求出sqrt(u*u+v*v)。

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

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

C++實(shí)現(xiàn)

在實(shí)現(xiàn)攝像機(jī)固定情況的光流法時(shí),需要有兩幀連續(xù)的圖像,下面的算法針對(duì)RGB24格式的圖像計(jì)算光流:

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);
 }

//////////////////////////////////////////////////////////////////////////

/另一個(gè)代碼

/

/////////////////////////////////////////////////////////////////////////////

WW_RETURN HumanMotion::ImgOpticalFlow(IplImage *pre_grey,IplImage *grey)

{

 IplImage *velx = cvCreateImage( cvSize(grey->width ,grey->height),IPL_DEPTH_32F, 1 );
 IplImage *vely = cvCreateImage( cvSize(grey->width ,grey->height),IPL_DEPTH_32F, 1 );

 velx->origin =  vely->origin = grey->origin;
 CvSize winSize = cvSize(5,5);
 cvCalcOpticalFlowLK( prev_grey, grey, winSize, velx, vely );
 
 cvAbsDiff( grey,prev_grey, abs_img );
 cvThreshold( abs_img, abs_img, 29, 255, CV_THRESH_BINARY); 

 CvScalar xc,yc; 
 for(int y =0 ;y<velx->height; y++)
  for(int x =0;x<velx->width;x++ )
  {
   xc = cvGetAt(velx,y,x);
   yc = cvGetAt(vely,y,x);

   
   float x_shift= (float)xc.val[0];
   float y_shift= (float)yc.val[0];
   const int winsize=5;  //計(jì)算光流的窗口大小


   if((x%(winsize*2)==0) && (y%(winsize*2)==0) )
   {

    if(x_shift!=0 || y_shift!=0)
    {
     
     if(x>winsize && y>winsize && x <(velx->width-winsize) && y<(velx->height-winsize) )
     {

      cvSetImageROI( velx, cvRect( x-winsize, y-winsize, 2*winsize, 2*winsize));
      CvScalar total_x = cvSum(velx);
      float xx = (float)total_x.val[0];
      cvResetImageROI(velx);

      cvSetImageROI( vely, cvRect( x-winsize, y-winsize, 2*winsize, 2*winsize));
      CvScalar total_y = cvSum(vely);
      float yy = (float)total_y.val[0];
      cvResetImageROI(vely);
      
      cvSetImageROI( abs_img, cvRect( x-winsize, y-winsize, 2*winsize, 2*winsize));
      CvScalar total_speed = cvSum(abs_img);
      float ss = (float)total_speed.val[0]/(4*winsize*winsize)/255;
      cvResetImageROI(abs_img);

      const double ZERO = 0.000001;
      const double pi = 3.1415926;
      double alpha_angle;

      if(xx<ZERO && xx>-ZERO)
       alpha_angle = pi/2;
      else
       alpha_angle = abs(atan(yy/xx));
      
      if(xx<0 && yy>0) alpha_angle = pi - alpha_angle ;
      if(xx<0 && yy<0) alpha_angle = pi + alpha_angle ;
      if(xx>0 && yy<0) alpha_angle = 2*pi - alpha_angle ;


      
      CvScalar line_color;
      float scale_factor = ss*100;
      line_color = CV_RGB(255,0,0);
      CvPoint pt1,pt2;
      pt1.x = x;
      pt1.y = y;
      pt2.x = static_cast<int>(x + scale_factor*cos(alpha_angle));
      pt2.y = static_cast<int>(y + scale_factor*sin(alpha_angle));

      cvLine( image, pt1, pt2 , line_color, 1, CV_AA, 0 );
      CvPoint p;
      p.x = (int) (pt2.x + 6 * cos(alpha_angle - pi / 4*3));
      p.y = (int) (pt2.y + 6 * sin(alpha_angle - pi / 4*3));
      cvLine( image, p, pt2, line_color, 1, CV_AA, 0 );
      p.x = (int) (pt2.x + 6 * cos(alpha_angle + pi / 4*3));
      p.y = (int) (pt2.y + 6 * sin(alpha_angle + pi / 4*3));
      cvLine( image, p, pt2, line_color, 1, CV_AA, 0 );

      

     }
    }
   }
  }


 cvShowImage( "Contour", abs_img);
 cvShowImage( "Contour2", vely);

 cvReleaseImage(&velx);
 cvReleaseImage(&vely);
 cvWaitKey(20);
 
 return WW_OK;

}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約