前景检测算法-SACON(SAMPLE CONSENSUS)

申明,本文非笔者原创,原文转载自:http://blog.youkuaiyun.com/STELLAR0/article/details/8740594


 SACON是Hanzi Wang and David Suter合作完成的一篇论文《Background subtraction based on a robust consensu method>>里的算法。乍看之下,算法思路很简单,后来的大作VIBE算法似乎与其有异曲同工之妙。废话少说,下面来简单介绍下该算法:

     (1)建立背景模型

           文章中背景模型的建立比较简单,就是为each pixel 保存N个background samples,这个可以很容易的提取视频序列的前N帧实现。

     (2)前景提取

       该部分分为3阶段,其实每个阶段都是相互融合的:第一步利用邻域帧差法提取可能的前景掩膜(FMForeground Mask),即时间域内连续两帧相减,提取Possible moving pixels;第二部,针对第一步的得到的possible moving pixels以及background samples给SACON算法处理,主要的处理过程是按以下两个公式得到:

                               

 

                                

其中Tr为常量(constant),N是背景样本的数目(sample number),k表示通道数目(channel number), 在实现程序中默认取值为15. Tn的取值与N相关,其值可以表示为Tn~cNTr(C is a constant)。实现程序Tn默认取值为2N.

      (3) 阴影去除(该文阴影去除算法是借鉴其他文章的,具体参考section 3.1)

      (4) 空洞填充

       考虑到提取的前景区域内部可能存在一些小的空洞,于是文章采用了空洞填充技术。在实现中,采用的是形态学的碰撞腐蚀(Dilate and erode)来进行填充的。

     (5)考虑到背景的移出或前景的停止,文章介绍了TOM(TIme OF MAP)来对其处理,可以讲移出的背景留下的区域很快的内容到背景中,而对于停止在场景中的目标,也能很快的融入到背景中去。


头文件.h:

  1. class SACON    
  2. {  
  3. public:  
  4.  SACON();  
  5.  // 构造函数,其中iteration表示样本的数目,也即用于学习的帧数N  
  6.  SACON(IplImage *img,int iteration);  
  7.  /* Description:  
  8.   To implement the function to distinguish whether a pixel is foreground or background 
  9.  and then update the background model */  
  10.  void Detect(IplImage *img);  
  11.  /* 设置当前像素是否为背景还是前景,即当前像素与背景样本比较,存在较大差异的数目 
  12.   该值与样本的数目gIteration相关,默认为gIteration*2 
  13.  */  
  14.  void SetAlpha(double al){gAlpha=al;}  
  15.  // 设置两个像素值的差异,默认为15  
  16.  void SetValDiff(int ival){valDiff=ival;}  
  17.  // 用于标记一个像素最多为  
  18.  void SetTomTh(int Count){Th_Tom=Count;}  
  19.  IplImage* getForeground(){return pForeImg;}  
  20.  virtual ~SACON();  
  21. private:  
  22.  void InnerDetect(IplImage *img);  
  23.  // 填充前景区域的空洞,思想是填充,  
  24.  void ValidateForeground(IplImage *foreImg);  
  25.  IplImage **pBkImgArr;  
  26.  IplImage *pForeImg;   
  27.  IplImage *pPreImg;  
  28.  IplImage *pGray;  
  29.  IplImage *pDiffImg;  
  30.  int gHeight;  
  31.  int gWidth;  
  32.  CvSize gSize;  
  33.  int gIteration;  
  34.  int frmNum;  
  35.  int valDiff; // 两个像素值的差异  
  36.  double gAlpha;//the value that determines a pixel whether a foreground or background  
  37.  int **Tom; //用来记录一个像素被连续判为前景的次数  
  38.  int Th_Tom; // 用于标记一个像素最多为前景的次数,默认为100  
  39. };  
下面是实现代码cpp文件:

  1. SACON::SACON(IplImage *img,int iteration)  
  2. {  
  3.  frmNum=0;   
  4.  Th_Tom=100;  
  5.  gHeight=img->height;  
  6.  gWidth=img->width;  
  7.  gIteration=iteration;  
  8.  gAlpha=gIteration*2; // 值的设置还有待商榷  
  9.  gSize=cvGetSize(img);  
  10.  pForeImg=cvCreateImage(gSize,8,1);   
  11.  pGray=cvCreateImage(gSize,8,1);   
  12.  pPreImg=cvCreateImage(gSize,8,3);  
  13.  pDiffImg=cvCreateImage(gSize,8,3);   
  14.  int i=0,j=0;  
  15.  Tom=new int *[gHeight];  
  16.  for (i=0;i<gHeight;i++)  
  17.  {  
  18.   Tom[i]=new int[gWidth];  
  19.   for (j=0;j<gWidth;j++)  
  20.   {  
  21.    Tom[i][j]=0;  
  22.   }  
  23.  }  
  24.  pBkImgArr=new IplImage*[gIteration];  
  25.  for (i=0;i<gIteration;i++)  
  26.  {  
  27.   pBkImgArr[i]=cvCreateImage(gSize,IPL_DEPTH_8U,3);  
  28.  }  
  29.  cvCopyImage(img,pBkImgArr[frmNum]);  
  30.  frmNum++;  
  31. }  
  32. // 实现前景检测,如果学习没完,则继续进行学习  
  33. void SACON::Detect(IplImage *img)  
  34. {    
  35.  if (frmNum<gIteration)  
  36.  {  
  37.   cvCopyImage(img,pBkImgArr[frmNum]);  
  38.   frmNum++;  
  39.   if (frmNum==gIteration)  
  40.   {  
  41.    cvCopyImage(img,pPreImg);  
  42.   }  
  43.  }  
  44.  else  
  45.  {  
  46.   InnerDetect(img);  
  47.   ValidateForeground(pForeImg);  
  48.  }  
  49. }  
  50. // 实现前景检测,并进行背景更新  
  51. void SACON::InnerDetect(IplImage *img)  
  52. {  
  53.  cvZero(pForeImg);  
  54.  cvZero(pGray);  
  55.  cvAbsDiff(img,pPreImg,pDiffImg);  
  56.  cvCvtColor(pDiffImg,pGray,CV_BGR2GRAY);  
  57.  cvThreshold(pGray,pGray,20,255,CV_THRESH_BINARY);  
  58.  cvCopyImage(img,pPreImg);  
  59.  int i=0,j=0,k=0,p=0;  
  60.  int cnt=0, iTom;  
  61.  CvScalar cs0,cs1,cs2,cs3;  
  62.  cs3.val[0]=255;   
  63.  for (i=0;i<gHeight;i++)  
  64.  {  
  65.   for (j=0;j<gWidth;j++)  
  66.   {  
  67.    cs0=cvGet2D(pGray,i,j);  
  68.    if (cs0.val[0]==255)  
  69.    {  
  70.     cs1=cvGet2D(img,i,j);  
  71.     cnt=0;  
  72.     for (k=0;k<gIteration;k++)  
  73.     {  
  74.      cs2=cvGet2D(pBkImgArr[k],i,j);  
  75.      for (p=0;p<3;p++)  
  76.      {  
  77.       if (fabs(cs1.val[p]-cs2.val[p])>valDiff)  
  78.       {  
  79.        cnt++;  
  80.       }  
  81.      }  
  82.     }  
  83.     //与背景比较完成  
  84.     if (cnt>gAlpha)  
  85.     {  
  86.      iTom=Tom[i][j];  
  87.      if (iTom>Th_Tom) // 如果当前像素为前景的次数超过Th_Tom,则判为背景  
  88.      {  
  89.       Tom[i][j]=0;  // 怎么更新背景  
  90.      }  
  91.      else  
  92.      {  
  93.       Tom[i][j]++;  
  94.       cvSet2D(pForeImg,i,j,cs3);       
  95.      }  
  96.     }  
  97.    }  
  98.    else  
  99.    {  
  100.     continue;  
  101.    }  
  102.   }  
  103.     
  104.  }  
  105. }  
  106. void SACON::ValidateForeground(IplImage *foreImg)  
  107. {  
  108.  // 膨胀腐蚀的默认结构元素是3×3的长方形  
  109.  cvDilate(foreImg,foreImg,NULL,1);  
  110.  cvErode(foreImg,foreImg,NULL,1);  
  111.  /* 
  112.  int i=0,j=0,p=0,q=0; 
  113.  int cnt; 
  114.  CvScalar cs0,cs; 
  115.  cs.val[0]=255; 
  116.  for (i=1;i<gHeight-1;i++) 
  117.  { 
  118.   for (j=1;j<gWidth-1;j++) 
  119.   { 
  120.    cnt=0; 
  121.    for (p=i-1;p<=i+1;p++) 
  122.    { 
  123.     for(q=j-1;q<=j+1;q++) 
  124.     { 
  125.      cs0=cvGet2D(foreImg,p,q); 
  126.      if (cs0.val[0]==255) 
  127.      { 
  128.       cnt++; 
  129.      } 
  130.     } 
  131.    } 
  132.    if (cnt>5) 
  133.    { 
  134.     cvSet2D(foreImg,i,j,cs); 
  135.    } 
  136.   } 
  137.  } 
  138.  */  
  139. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值