OpenCV混合高斯模型前景分離


運動檢測的一般方法

  目前,運動物體檢測的問題主要分為兩類,攝像機固定和攝像機運動。對於攝像機運動的運動物體檢測問題,比較著名的解決方案是光流法,通過求解偏微分方程求的圖像序列的光流場,從而預測攝像機的運動狀態。對於攝像機固定的情形,當然也可以用光流法,但是由於光流法的復雜性,往往難以實時的計算,所以我采用 高斯背景模型。因為,在攝像機固定的情況下,背景的變化是緩慢的,而且大都是光照,風等等的影響,通過對背景建模,對一幅給定圖像分離前景和背景,一般來說,前景就是運動物體,從而達到運動物體檢測的目的
 
單分布高斯背景模型
單分布高斯背景模型認為,對一個背景圖像,特定像素亮度的分布滿足高斯分布,即對背景圖像B,(x,y)點的亮度滿足:
  IB(x,y) ~ N(u,d)
  這樣我們的背景模型的每個象素屬性包括兩個參數:平均值u 和 方差d。
  對於一幅給定的圖像G,如果 Exp(-(IG(x,y)-u(x,y))^2/(2*d^2)) > T,認為(x,y)是背景點,反之是前景點。
  同時,隨着時間的變化,背景圖像也會發生緩慢的變化,這時我們要不斷更新每個象素點的參數
  u(t+1,x,y) = a*u(t,x,y) + (1-a)*I(x,y)
  這里,a稱為更新參數,表示背景變化的速度,一般情況下,我們不更新d(實驗中發現更不更新d,效果變化不大)。
   高斯混合模型是用於背景提取的方法,OpenCV的cvaux中cvbgfg_gaussmix.cpp文件根據文獻An improved adaptive background mixture model for real-time tracking with shadow中提供的方法編寫了高斯混合模型函數。其中定義了CvGaussBGModel類用於存放高斯混合模型的各個參數。我用OpenCV使用高斯混合模型函數分以下幾步:
  1。在程序初始化部分定義高斯混合模型參數CvGaussBGModel* bg_model=NULL;在讀取第一幀圖像(背景圖像)時,進行高斯背景建模bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(image, 0);image可以是灰度圖象也可以是彩色圖像。接下來再讀取當前幀時,更新高斯模型
  regioncount=icvUpdateGaussianBGModel(currframe, bg_model );regioncount的含義我不確定,我理解是代表背景中不同顏色區域的個數,這個參數我沒有用到,它只是icvUpdateGaussianBGModel函數的返回值。
  2。現在bg_model已經保存了經過高斯混合模型分類后的結果,bg_model->background保存了背景圖像,bg_model->foreground保存了前景圖像。
#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <cvaux.h>//必須引此頭文件
int main( int argc, char** argv )
{ 

   IplImage* pFrame = NULL;   
   IplImage* pFrImg = NULL; 
   IplImage* pBkImg = NULL;   
   CvCapture* pCapture = NULL;   
   int nFrmNum = 0;

   cvNamedWindow("video", 1); 
   cvNamedWindow("background",1); 
   cvNamedWindow("foreground",1);   
   cvMoveWindow("video", 30, 0); 
   cvMoveWindow("background", 360, 0); 
   cvMoveWindow("foreground", 690, 0);

   //打開視頻文件 

   pCapture = cvCaptureFromFile("bike.avi");
   //pCapture = cvCaptureFromFile("20120726.avi");
   if( !pCapture )     
   {   
      fprintf(stderr, "Can not open video file %s\n", argv[1]);   
      return -2;     
   }


   //初始化高斯混合模型參數
   CvGaussBGModel* bg_model=NULL;

   while(pFrame = cvQueryFrame( pCapture ))   
   {     
      nFrmNum++;           
      if(nFrmNum == 1)   
      {    
         pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  pFrame->depth, pFrame->nChannels /*IPL_DEPTH_8U,3*/);   
         pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);     


         //高斯背景建模,pFrame可以是多通道圖像也可以是單通道圖像
         //cvCreateGaussianBGModel函數返回值為CvBGStatModel*,
         //需要強制轉換成CvGaussBGModel*
         bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame, 0);
      }     
      else
      {    
         //更新高斯模型
         cvUpdateBGStatModel(pFrame, (CvBGStatModel *)bg_model );

         //pFrImg為前景圖像,只能為單通道
         //pBkImg為背景圖像,可以為單通道或與pFrame通道數相同
         cvCopy(bg_model->foreground,pFrImg,0);
         cvCopy(bg_model->background,pBkImg,0);
         cvThreshold(pFrImg, pFrImg, 128, 255, CV_THRESH_BINARY_INV);

         //把圖像正過來
      //   pBkImg->origin=1;
      //   pFrImg->origin=1;

         cvShowImage("video", pFrame);    
         cvShowImage("background", pBkImg);    
         cvShowImage("foreground", pFrImg);       
         if( cvWaitKey(100) >= 0 )      
            break;     
      }     

   }

   //釋放高斯模型參數占用內存   
   cvReleaseBGStatModel((CvBGStatModel**)&bg_model);
   cvDestroyWindow("video"); 
   cvDestroyWindow("background"); 
   cvDestroyWindow("foreground");   
   cvReleaseImage(&pFrImg); 
   cvReleaseImage(&pBkImg);   
   cvReleaseCapture(&pCapture);   
   return 0;
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM