2014年4月3日 星期四

Build background with cvRunningAvg

  1. #include <cv.h>
  2. #include <highgui.h>
  3.  
  4. int main()
  5. {
  6.      IplImage *pFrame = NULL;
  7.      IplImage *pGrayImg = NULL;
  8.      IplImage *pFGImg = NULL;
  9.      IplImage *pBGImg_8U = NULL;
  10.      IplImage *pBGImg_32F = NULL;
  11.      IplConvKernel * pKernel = NULL;
  12.      CvCapture *pCapture = cvCreateCameraCapture(1);
  13.  
  14.      cvNamedWindow("webcam", 1);
  15.      cvNamedWindow("background", 1);
  16.      cvNamedWindow("foreground", 1);
  17.  
  18.       pKernel = cvCreateStructuringElementEx( 5, 3, 0,0
  19.         , CV_SHAPE_ELLIPSE, NULL);
  20.  
  21.      if(!(pFrame = cvQueryFrame(pCapture)))
  22.      {
  23.          fprintf(stderr, "Can not open");
  24.          return -1;
  25.      }
  26.      else
  27.      {
  28.          pGrayImg = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);
  29.          pFGImg = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);
  30.          pBGImg_8U = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);
  31.          pBGImg_32F = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_32F, 1);
  32.    
  33.          cvCvtColor(pFrame, pGrayImg, CV_BGR2GRAY);
  34.  
  35.          /* 建立背景 */
  36.          cvConvertScale(pGrayImg, pBGImg_32F);
  37.          cvConvertScale(pBGImg_32F, pBGImg_8U);
  38.      }
  39.      while(pFrame = cvQueryFrame(pCapture))
  40.      {
  41.          cvCvtColor(pFrame, pGrayImg, CV_BGR2GRAY);
  42.          cvAbsDiff(pGrayImg, pBGImg_8U, pFGImg);
  43.         
  44.          /* 前景二值化做形態學處理 */
  45.          cvThreshold(pFGImg, pFGImg, 30.0, 255, CV_THRESH_BINARY);
  46.          cvMorphologyEx(pFGImg, pFGImg, 0, pKernel, CV_MOP_OPEN,1);
  47.          cvMorphologyEx(pFGImg, pFGImg, 0, pKernel, CV_MOP_CLOSE,1);
  48.  
  49.          double t = (double)cvGetTickCount();
  50.          /* 背景更新 */
  51.          cvRunningAvg(pGrayImg, pBGImg_32F, 0.05, 0);
  52.          t = (double)cvGetTickCount()-t;
  53.          printf("%.lf\n", t / (cvGetTickFrequency()*1000));
  54.          cvScale(pBGImg_32F, pBGImg_8U);
  55.  
  56.          cvShowImage("webcam", pFrame);
  57.          cvShowImage("background", pBGImg_8U);
  58.          cvShowImage("foreground", pFGImg);
  59.          if(cvWaitKey(1) > 0)
  60.               break;
  61.      }
  62.      cvDestroyWindow("webcam");
  63.      cvDestroyWindow("background");
  64.      cvDestroyWindow("foreground");
  65.      cvReleaseImage(&pFrame);
  66.      cvReleaseImage(&pGrayImg);
  67.      cvReleaseImage(&pBGImg_8U);
  68.      cvReleaseImage(&pBGImg_32F);
  69.  
  70.      return 0;
  71. }
 程式碼解析

    將所需使用資料型態先初始化,並藉由if判斷是否偵測到webcam進行記憶體宣告,使用兩個存放背景的資料的變數pBGImg_8U、pBGImg_32F,因為若要顯示背景影像則只能用8-bit 無號數資料顯示,若要進行之後的cvRunningAvg()背景更新則僅能使用32-bit 浮點數資料運算。迴圈中不斷進行影像相減在做二值化及形態學處理得到前景,最後使用cvRunningAvg()進行背景更新。


函示說明
cvConvertScale
cvConvertScale(來源影像輸出影像);
#define cvScale  cvConvertScale
 進行縮放型態的轉換


cvAbsDiff()
cvAbsDiff(目前影像, 背景影像, 前景影像);
將當前的frame當作目前影像,而把已建置好的背景影像作為參數,兩個影像作相減並取絕對值得到前景。

cvMorphologyEx()
void cvMorphologyEx(const CvArr* src, CvArr* dst, CvArr* temp, IplConvKernel* element, int operation, int iteration = 1)


Parameters:
  • src – Source image. The number of channels can be arbitrary
  • dst – Destination image of the same size and type as src .
  • element – Structuring element.
  • op –

         Type of a morphological operation that can be one of the following:
    • CV_MOP_OPEN - an opening operation
    • CV_MOP_CLOSE - a closing operation
    • CV_MOP_GRADIENT - a morphological gradient
    • CV_MOP_TOPHAT - “top hat”
    • CV_MOP_BLACKHAT - “black hat”

  • iterations – Number of times erosion and dilation are applied.

Opening operation:
        \texttt{dst} = \mathrm{open} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \mathrm{erode} ( \texttt{src} , \texttt{element} ))
Closing operation:
        \texttt{dst} = \mathrm{close} ( \texttt{src} , \texttt{element} )= \mathrm{erode} ( \mathrm{dilate} ( \texttt{src} , \texttt{element} ))
Morphological gradient:
       \texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )
“Top hat”:
       \texttt{dst} = \mathrm{tophat} ( \texttt{src} , \texttt{element} )= \texttt{src} - \mathrm{open} ( \texttt{src} , \texttt{element} )
“Black hat”:
       \texttt{dst} = \mathrm{blackhat} ( \texttt{src} , \texttt{element} )= \mathrm{close} ( \texttt{src} , \texttt{element} )- \texttt{src}

cvRunningAvg()
void cvRunningAvg(const CvArr* src, CvArr* dst, double alpha, const CvArr* mask=NULL )

Parameters:
  • src – Input image as 1- or 3-channel, 8-bit or 32-bit floating point.
  • dst – Accumulator image with the same number of channels as input image, 32-bit or 64-bit floating-point.
  • alpha – Weight of the input image.
  • mask – Optional operation mask.
該函數計算輸入圖像src和dst的累加器的加權總合,使dst成為一個偵序列的連續平均值


     \texttt{dst} (x,y)  \leftarrow (1- \texttt{alpha} )  \cdot \texttt{dst} (x,y) +  \texttt{alpha} \cdot \texttt{src} (x,y)  \quad \text{if} \quad \texttt{mask} (x,y)  \ne 0

也就是說,參數α用來調節更新速度多快(速度有多快累加器“忘記”前面的圖像)。該功能支持多通道圖像。每個通道獨立處理。

沒有留言:

張貼留言