zoukankan      html  css  js  c++  java
  • [转]前景检测算法--ViBe算法

    原文:http://blog.csdn.net/zouxy09/article/details/9622285

    转自:http://blog.csdn.net/app_12062011/article/details/51866319

     

    因为监控发展的需求,目前前景检测的研究还是很多的,也出现了很多新的方法和思路。个人了解的大概概括为以下一些:

           帧差、背景减除(GMM、CodeBook、 SOBS、 SACON、 VIBE、 W4、多帧平均……)、光流(稀疏光流、稠密光流)、运动竞争(Motion Competition)、运动模版(运动历史图像)、时间熵……等等。如果加上他们的改进版,那就是很大的一个家族了。

          对于上一些方法的一点简单的对比分析可以参考下:

    http://www.cnblogs.com/ronny/archive/2012/04/12/2444053.html

           至于哪个最好,看使用环境吧,各有千秋,有一些适用的情况更多,有一些在某些情况下表现更好。这些都需要针对自己的使用情况作测试确定的。呵呵。

           推荐一个牛逼的库:http://code.google.com/p/bgslibrary/里面包含了各种背景减除的方法,可以让自己少做很多力气活。

           还有王先荣博客上存在不少的分析:

    http://www.cnblogs.com/xrwang/archive/2010/02/21/ForegroundDetection.html

           下面的博客上转载王先荣的上面几篇,然后加上自己分析了两篇:

    http://blog.csdn.net/stellar0

           本文主要关注其中的一种背景减除方法:ViBe。stellar0的博客上对ViBe进行了分析,我这里就不再啰嗦了,具体的理论可以参考:

    http://www2.ulg.ac.be/telecom/research/vibe/

    http://blog.csdn.net/stellar0/article/details/8777283

    http://blog.csdn.net/yongshengsilingsa/article/details/6659859

    http://www2.ulg.ac.be/telecom/research/vibe/download.html

    http://www.cvchina.info/2011/12/25/vibe/

    ViBe是一种像素级的背景建模、前景检测算法,该算法主要不同之处是背景模型的更新策略,随机选择需要替换的像素的样本,随机选择邻域像素进行更新。在无法确定像素变化的模型时,随机的更新策略,在一定程度上可以模拟像素变化的不确定性。

    背景模型的初始化

      初始化是建立背景模型的过程,一般的检测算法需要一定长度的视频序列学习完成,影响了检测的实时性,而且当视频画面突然变化时,重新学习背景模型需要较长时间。

      ViBe算法主要是利用单帧视频序列初始化背景模型,对于一个像素点,结合相邻像素点拥有相近像素值的空间分布特性,随机的选择它的邻域点的像素值作为它的模型样本值

      优点:不仅减少了背景模型建立的过程,还可以处理背景突然变化的情况,当检测到背景突然变化明显时,只需要舍弃原始的模型,重新利用变化后的首帧图像建立背景模型。

      缺点:由于可能采用了运动物体的像素初始化样本集,容易引入拖影(Ghost)区域。

    前景检测过程

      背景模型为每个背景点存储一个样本集,然后每个新的像素值和样本集比较判断是否属于背景。

      计算新像素值和样本集中每个样本值的距离,若距离小于阈值,则近似样本点数目增加。

      如果近似样本点数目大于阈值,则认为新的像素点为背景。

      检测过程主要由三个参数决定:样本集数目N,阈值#min和距离相近判定的阈值R,一般具体实现,参数设置为N=20,#min=2,R=20。

      

    背景模型的更新策略

    1).无记忆更新策略

      每次确定需要更新像素点的背景模型时,以新的像素值随机取代该像素点样本集的一个样本值。

    2).时间取样更新策略

      并不是每处理一帧数据,都需要更新处理,而是按一定的更新率更新背景模型。当一个像素点被判定为背景时,它有1/rate的概率更新背景模型。rate是时间采样因子,一般取值为16。

    3).空间邻域更新策略

      针对需要更新像素点,随机的选择一个该像素点邻域的背景模型,以新的像素点更新被选中的背景模型。

    ViBe的改进

      

    1).距离计算方法

      以圆椎模型代替原来的几何距离计算方法

      

      以自适应阈值代替原来固定的距离判定阈值,阈值大小与样本集的方差成正比,样本集方差越大,说明背景越复杂,判定阈值应该越大。

      

    2).分离updating mask和segmentation mask

      引入目标整体的概念,弥补基于像素级前景检测的不足。针对updating mask和segmentation mask采用不同尺寸的形态学处理方法,提高检测准确率。

    3).抑制邻域更新

      在updating mask里,计算像素点的梯度,根据梯度大小,确定是否需要更新邻域。梯度值越大,说明像素值变化越大,说明该像素值可能为前景,不应该更新。

    4).检测闪烁像素点

      引入闪烁程度的概念,当一个像素点的updating label与前一帧的updating label不一样时,blinking level增加15,否则,减少1,然后根据blinking level的大小判断该像素点是否为闪烁点。闪烁像素主要出现在背景复杂的场景,如树叶、水纹等,这些场景会出现像素背景和前景的频繁变化,因而针对这些闪烁应该单独处理,可以作为全部作为背景。

    5).增加更新因子

      ViBe算法中,默认的更新因子是16,当背景变化很快时,背景模型无法快速的更新,将会导致前景检测的较多的错误。因而,需要根据背景变化快慢程度,调整更新因子的大小,可将更新因子分多个等级,如rate = 16,rate = 5,rate = 1。

    1)VIBE-A powerful random technique to estimatie the background in video sequences.

    2) VIBE-A universal background subtraction algorithms for video sequences

       VIBE的头文件Vibe.hpp如下:

     1 #pragma once  
     2 #include "stdafx.h"  
     3 #define  WINSIZE 3  
     4   
     5 class Vibe  
     6 {  
     7 public:  
     8     Vibe(void);  
     9     Vibe(IplImage *img);  
    10     void SetMinMatch(int nthreshold){g_MinMatch=nthreshold;}  
    11     void SetRadius(int radius){g_Radius=radius;}  
    12     void SetSampleNum(int num){g_SampleNum=num;}  
    13     void SetThreshold(double t){g_threshold=t;}  
    14     IplImage* GetForeground(){return g_ForeImg;}  
    15     IplImage* GetSegMask(){return g_SegementMask;}  
    16     void Detect(IplImage *img);   
    17     void ForegroundCombineEdge(); // 结合边缘信息  
    18     void DeleteSmallAreaInForeground(double minArea=20);//删除小面积区域  
    19     // 实现背景更新机制  
    20     void Update();  
    21     // 实现后处理,主要用形态学算子  
    22     void PostProcess();  
    23   
    24 public:  
    25     ~Vibe(void);  
    26   
    27 private:      
    28     void ClearLongLifeForeground(int i_lifeLength=200); // 清除场景中存在时间较长的像素,i_lifeLength用于控制允许存在的最长时间  
    29     double AreaDense(IplImage *pFr,int AI,int AJ,int W,int H); //计算(i,j)处邻域大小为W×H的密度  
    30     int GetRandom(int istart,int iend); // 默认istart=0,iend=15  
    31     int GetRandom(int random);  
    32     int GetRandom();// 产生一个随机数  
    33     // 计算两个像素之间的欧式距离  
    34     double CalcPixelDist(CvScalar bkCs,CvScalar curCs);  
    35     // 按照Kim的方法来计算颜色畸变  
    36     double CalcuColorDist(CvScalar bkCs,CvScalar curCs);  
    37     int g_SampleNum;// Sample number for the models,默认为20  
    38     int g_MinMatch; // 当前像素与背景模型匹配的最少个数,默认为2  
    39     int g_Height;  
    40     int g_Width;  
    41     int g_Radius;// 球体的半径,默认为20  
    42     int g_offset; //边界的宽和高  
    43     double g_threshold; // 距离度量的阈值  
    44     unsigned char ***g_Model;// 保存背景模型    
    45     IplImage *g_ForeImg;// 保存前景图  
    46     IplImage *g_Edge;  
    47   
    48     IplConvKernel* element;  
    49   
    50     IplImage *g_SegementMask; //分割掩膜  
    51     IplImage *g_UpdateMask; // 更新掩膜  
    52     IplImage *g_Gray;  
    53     int ** LifeLength; // 记录前景点的生命长度,如果前景点的生命长度到达一定的阈值,则将其融入背景中去,且要随机两次。      
    54 };  

    对应的实现文件如下Vibe.cpp所示:

      1 #include "StdAfx.h"  
      2 #include "Vibe.h"  
      3   
      4 Vibe::Vibe(void)  
      5 {  
      6     g_Radius=20;  
      7     g_MinMatch=2;     
      8     g_SampleNum=20;  
      9     g_offset=(WINSIZE-1)/2;  
     10   
     11 }  
     12   
     13 Vibe::Vibe(IplImage *img)  
     14 {  
     15     if (!img)  
     16     {  
     17         cout<<" The parameter referenced to NUll Pointer!"<<endl;  
     18         return;  
     19     }  
     20     this->g_Height=img->height;  
     21     this->g_Width=img->width;  
     22   
     23     g_Radius=20;  
     24     g_MinMatch=2;     
     25     g_SampleNum=20;  
     26     g_threshold=50;  
     27     g_offset=(WINSIZE-1)/2;  
     28   
     29     g_ForeImg=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);  
     30     g_Gray=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);  
     31     g_Edge=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);  
     32     g_SegementMask=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);  
     33     g_UpdateMask=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);  
     34   
     35     element=cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL);  
     36   
     37     cvCvtColor(img,g_Gray,CV_BGR2GRAY);  
     38       
     39     // 以上完成相关的初始化操作  
     40     /**********************  以下实现第一帧在每个像素的8邻域内的采样功能,建立对应的背景模型*****************************/  
     41       
     42     int i=0,j=0,k=0;  
     43     g_Model=new unsigned char**[g_SampleNum];  
     44     for (k=0;k<g_SampleNum;k++)  
     45     {  
     46         g_Model[k]=new unsigned char *[g_Height];  
     47         for(i=0;i<g_Height;i++)  
     48         {  
     49             g_Model[k][i]=new unsigned char [g_Width];  
     50             for (j=0;j<g_Width;j++)  
     51             {  
     52                 g_Model[k][i][j]=0;  
     53             }  
     54         }  
     55     }  
     56       
     57     // 采样进行背景建模   
     58     double dVal;  
     59     int ri=0,rj=0; //随机采样的值  
     60     for (i=g_offset;i<g_Height-g_offset;i++)  
     61     {  
     62         for (j=g_offset;j<g_Width-g_offset;j++)  
     63         {  
     64             // 周围3*3的邻域内进行采样  
     65             for(k=0;k<g_SampleNum;k++)  
     66             {  
     67                 ri=GetRandom(i);  
     68                 rj=GetRandom(j);  
     69                 dVal=cvGetReal2D(g_Gray,ri,rj);       
     70                 g_Model[k][i][j]=dVal;                            
     71             }  
     72         }  
     73     }  
     74   
     75     // 初始化前景点掩膜的生命长度  
     76     LifeLength=new int *[g_Height];  
     77     for (i=0;i<g_Height;i++)  
     78     {  
     79         LifeLength[i]=new int [g_Width];  
     80         for(j=0;j<g_Width;j++)  
     81         {  
     82             LifeLength[i][j]=0;  
     83         }  
     84     }  
     85 }  
     86   
     87   
     88 void Vibe::Detect(IplImage *img)  
     89 {  
     90     cvZero(g_ForeImg);    
     91     cvCvtColor(img,g_Gray,CV_BGR2GRAY);  
     92     int i=0,j=0,k=0;  
     93     double dModVal,dCurrVal;  
     94     int tmpCount=0;// 距离比较在阈值内的次数  
     95     double tmpDist=0;     
     96     int iR1,iR2;//产生随机数  
     97     int Ri,Rj; // 产生邻域内X和Y的随机数  
     98   
     99     for (i=0;i<g_Height;i++)  
    100     {         
    101         for (j=0;j<g_Width;j++)  
    102         {             
    103             if( i < g_offset || j < g_offset || i> g_Height - g_offset || j> g_Width - g_offset )  
    104             {  
    105                 cvSetReal2D(g_ForeImg,i,j,0);  
    106                 continue;  
    107             }  
    108             else  
    109             {  
    110                 tmpCount=0;  
    111                 dCurrVal=cvGetReal2D(g_Gray,i,j);                 
    112                 for (k=0;k<g_SampleNum && tmpCount<g_MinMatch  ;k++)  
    113                 {                     
    114                     dModVal=g_Model[k][i][j];  
    115                     //tmpDist=CalcPixelDist(dCurrVal,dModVal);  
    116                     //tmpDist=CalcuColorDist(dCurrVal,dModVal);   
    117                     tmpDist=fabs(dModVal-dCurrVal);                                   
    118                     if (tmpDist<g_Radius)  
    119                     {  
    120                         tmpCount++;  
    121                     }                     
    122                 }  
    123   
    124                 //判断是否匹配上  
    125                 if (tmpCount>=g_MinMatch)  
    126                 {  
    127                     cvSetReal2D(g_ForeImg,i,j,0);  
    128                     // 背景模型的更新                    
    129                     iR1=GetRandom(0,15);  
    130                     if (iR1==0)  
    131                     {  
    132                         iR2=GetRandom();  
    133                         g_Model[iR2][i][j]=dCurrVal;                          
    134                     }  
    135   
    136                     //进一步更新邻域模型  
    137                       
    138                     iR1=GetRandom(0,15);  
    139                     if (iR1==0)  
    140                     {  
    141                         Ri=GetRandom(i);  
    142                         Rj=GetRandom(j);  
    143                         iR2=GetRandom();  
    144                         g_Model[iR2][Ri][Rj]=dCurrVal;                        
    145                     }                         
    146                 }  
    147                 else  
    148                 {  
    149                     cvSetReal2D(g_ForeImg,i,j,255);  
    150                 }  
    151             }  
    152         }         
    153     }         
    154       
    155     //ForegroundCombineEdge();  
    156     DeleteSmallAreaInForeground(80);  
    157     ClearLongLifeForeground();  
    158     //PostProcess();  
    159 }  
    160   
    161 double Vibe::AreaDense(IplImage *pFr,int AI,int AJ,int W,int H)  
    162 {  
    163     if (AI<=2 || AJ<=2 || AJ>=(g_Width-2) || AI>=(g_Height-2))  
    164     {  
    165         return 0;  
    166     }  
    167     int Num=0,i=0,j=0;  
    168     double dVal=0,dense=0;  
    169     int Total=(2*H+1)*(2*W+1);  
    170     for (i=AI-H;i<=AI+H;i++)  
    171     {  
    172         for (j=AJ-W;j<=AJ+W;j++)  
    173         {  
    174             dVal=cvGetReal2D(pFr,i,j);  
    175             if (dVal>200)  
    176             {  
    177                 Num++;  
    178             }  
    179         }  
    180     }  
    181     dense=(double)Num/(double)Total;  
    182     return dense;  
    183 }  
    184   
    185 void Vibe::ForegroundCombineEdge()  
    186 {     
    187     cvZero(g_Edge);  
    188     //cvZero(g_SegementMask);  
    189     //cvCopy(g_ForeImg,g_SegementMask);  
    190     cvCanny(g_Gray,g_Edge,30,200,3);  
    191     int i=0,j=0;  
    192     double dense;  
    193     double dVal;  
    194     for (i=g_offset;i<g_Height-g_offset;i++)  
    195     {  
    196         for (j=g_offset;j<g_Width-g_offset;j++)  
    197         {  
    198             dense=AreaDense(g_ForeImg,i,j,2,2);  
    199             dVal=cvGetReal2D(g_Edge,i,j);  
    200             if (dense>0.2 && dVal>200)  
    201             {  
    202                 cvSetReal2D(g_ForeImg,i,j,255);  
    203             }  
    204         }  
    205     }  
    206   
    207 }  
    208   
    209   
    210 void Vibe::DeleteSmallAreaInForeground(double minArea/* =20 */)  
    211 {  
    212     //cvZero(g_SegementMask);  
    213     //cvCopy(g_ForeImg,g_SegementMask);  
    214     int region_count = 0;  
    215     CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;  
    216     CvMemStorage*  storage = cvCreateMemStorage();  
    217     cvClearMemStorage(storage);  
    218     cvFindContours( g_ForeImg, storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );  
    219     for( seq = first_seq; seq; seq = seq->h_next )  
    220     {  
    221         CvContour* cnt = (CvContour*)seq;  
    222         if( cnt->rect.width * cnt->rect.height < minArea )  
    223         {  
    224             prev_seq = seq->h_prev;  
    225             if( prev_seq )  
    226             {  
    227                 prev_seq->h_next = seq->h_next;  
    228                 if( seq->h_next ) seq->h_next->h_prev = prev_seq;  
    229             }  
    230             else  
    231             {  
    232                 first_seq = seq->h_next;  
    233                 if( seq->h_next ) seq->h_next->h_prev = NULL;  
    234             }  
    235         }  
    236         else  
    237         {             
    238             region_count++;  
    239         }  
    240     }              
    241     cvZero(g_ForeImg);  
    242     cvDrawContours(g_ForeImg, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);   
    243   
    244     /* 
    245     CvContourScanner scanner = cvStartFindContours( g_ForeImg, storage,sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); 
    246     CvSeq *contours=NULL,*c=NULL; 
    247     int poly1Hull0=0; 
    248     int nContours=0; 
    249     double perimScale=100; 
    250     while( (c = cvFindNextContour( scanner )) != 0 )  
    251     { 
    252         double len = cvContourPerimeter( c ); 
    253         double q = (g_ForeImg->height + g_ForeImg->width)/perimScale; // calculate perimeter len threshold 
    254         if( len < q ) //Get rid of blob if it's perimeter is too small 
    255             cvSubstituteContour( scanner, 0 ); 
    256         else //Smooth it's edges if it's large enough 
    257         { 
    258             CvSeq* newC; 
    259             if( poly1Hull0 ) //Polygonal approximation of the segmentation  
    260                 newC = cvApproxPoly( c, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 2, 0 );  
    261             else //Convex Hull of the segmentation 
    262                 newC = cvConvexHull2( c, storage, CV_CLOCKWISE, 1 ); 
    263             cvSubstituteContour( scanner, newC ); 
    264             nContours++; 
    265         } 
    266     } 
    267     contours = cvEndFindContours( &scanner ); 
    268     // paint the found regions back into the image 
    269     cvZero( g_ForeImg ); 
    270     for( c=contours; c != 0; c = c->h_next )  
    271         cvDrawContours( g_ForeImg, c, cvScalarAll(255), cvScalarAll(0), -1, CV_FILLED, 8,cvPoint(0,0)); 
    272     */  
    273   
    274     cvReleaseMemStorage(&storage);    
    275 }  
    276   
    277 void Vibe::ClearLongLifeForeground(int i_lifeLength/* =200 */)  
    278 {  
    279     int i=0,j=0;  
    280     double dVal=0;  
    281     double dLife=0;  
    282     int iR1,iR2=0;  
    283     double dCurrVal=0;  
    284     for (i=g_offset;i<g_Height-g_offset;i++)  
    285     {  
    286         for (j=g_offset;j<g_Width-g_offset;j++)  
    287         {  
    288             dVal=cvGetReal2D(g_ForeImg,i,j);  
    289             dLife=LifeLength[i][j];  
    290             if (dLife>i_lifeLength)  
    291             {  
    292                 LifeLength[i][j]=0;  
    293                 dCurrVal=cvGetReal2D(g_Gray,i,j);  
    294                 // 更新背景模型  
    295                 iR1=GetRandom();  
    296                 iR2=GetRandom();  
    297                 g_Model[iR1][i][j]=dCurrVal;  
    298                 g_Model[iR2][i][j]=dCurrVal;  
    299             }  
    300             else  
    301             {  
    302                 LifeLength[i][j]=dLife+1;  
    303             }  
    304   
    305         }  
    306     }  
    307 }  
    308   
    309 void Vibe::Update()  
    310 {  
    311     cvZero(g_UpdateMask);     
    312   
    313 }  
    314   
    315 void Vibe::PostProcess()  
    316 {  
    317     cvZero(g_SegementMask);  
    318     cvMorphologyEx(g_ForeImg,g_SegementMask,NULL,element,CV_MOP_OPEN,1);  
    319   
    320 }  
    321   
    322 //算颜色畸变  
    323 double Vibe::CalcuColorDist(CvScalar bkCs,CvScalar curCs)  
    324 {  
    325     double r,g,b,br,bg,bb;  
    326     r=curCs.val[0];  
    327     g=curCs.val[1];  
    328     b=curCs.val[2];  
    329   
    330     br=bkCs.val[0];  
    331     bg=bkCs.val[1];  
    332     bb=bkCs.val[2];  
    333   
    334     double curDist=r*r+g*g*b*b;   
    335     double bkDist=br*br+bg*bg+bb*bb;  
    336   
    337     double curBK=r*br+g*bg+b*bb;  
    338     double curbkDist=curBK*curBK;  
    339     double SquareP;  
    340     if (bkDist==0.0)  
    341     {  
    342         SquareP=0;  
    343     }  
    344     else  
    345     {  
    346         SquareP=curbkDist/bkDist;  
    347     }  
    348     double dist=sqrtf(curDist-SquareP);  
    349     return dist;      
    350 }  
    351   
    352 double Vibe::CalcPixelDist(CvScalar bkCs,CvScalar curCs)  
    353 {  
    354     double tmpDist=pow(bkCs.val[0]-curCs.val[0],2)+pow(bkCs.val[1]-curCs.val[1],2)+pow(bkCs.val[2]-curCs.val[2],2);  
    355     return sqrtf(tmpDist);  
    356 }  
    357   
    358 int Vibe::GetRandom()  
    359 {  
    360     int val = g_SampleNum * 1.0 * rand() / RAND_MAX;      
    361     if( val == g_SampleNum )  
    362         return val - 1;  
    363     else  
    364         return val;  
    365 }  
    366   
    367 int Vibe::GetRandom(int random)  
    368 {  
    369     int val=random-g_offset+rand()%(2*g_offset);  
    370     if (val<random-g_offset)  
    371     {  
    372         val=random-g_offset;  
    373     }  
    374     if (val>random+g_offset)  
    375     {  
    376         val=random+g_offset;  
    377     }     
    378     return val;   
    379 }  
    380   
    381 int Vibe::GetRandom(int istart,int iend)  
    382 {  
    383     int val=istart+rand()%(iend-istart);  
    384     return val;  
    385 }  
    386   
    387   
    388 Vibe::~Vibe(void)  
    389 {  
    390     if (g_ForeImg)  
    391     {  
    392         cvReleaseImage(&g_ForeImg);  
    393     }  
    394     if (g_SegementMask)  
    395     {  
    396         cvReleaseImage(&g_SegementMask);  
    397     }  
    398     if (g_UpdateMask)  
    399     {  
    400         cvReleaseImage(&g_UpdateMask);  
    401     }  
    402     if (g_Gray)  
    403     {  
    404         cvReleaseImage(&g_Gray);  
    405     }  
    406   
    407     if (g_Model!=NULL)  
    408     {  
    409         delete[]g_Model;  
    410         g_Model=NULL;  
    411     }  
    412 }  

    最后附上调用的main函数:

     1 int _tmain(int argc, _TCHAR* argv[])  
     2 {     
     3     CvCapture *capture=NULL;  
     4     IplImage* frame=NULL;  
     5     IplImage* pForeImg=NULL;  
     6     IplImage* segImg=NULL;    
     7   
     8     char *file_path="E:\testVideo\VTS_01_4.avi";  // m1  test2 锦带河  VTS_01_4_2  head rear  VTS_01_6_2  VTS_01_4  
     9     //const char* file_path="E:\suntektechvideo\锦带河.avi";  //test2  
    10   
    11     capture=cvCreateFileCapture(file_path);  
    12     if (!capture)  
    13     {  
    14         //cout<<"Read Video File Error!"<<endl;  
    15         return -1;  
    16     }  
    17     frame=cvQueryFrame(capture);  
    18     frame=cvQueryFrame(capture);  
    19   
    20     cvNamedWindow("img",1);  
    21     cvNamedWindow("foreN",1);  
    22     //cvNamedWindow("seg",1);  
    23   
    24     Vibe* pV=new Vibe(frame);  
    25   
    26     while(frame=cvQueryFrame(capture))  
    27     {  
    28         pV->Detect(frame);  
    29         pForeImg=pV->GetForeground();  
    30         //segImg=pV->GetSegMask();  
    31         //frame->origin=1;  
    32         //pForeImg->origin=1;  
    33         cvShowImage("img",frame);  
    34         cvShowImage("foreN",pForeImg);  
    35         //cvShowImage("seg",segImg);  
    36         cvWaitKey(1);  
    37     }  
    38   
    39     cvReleaseImage(&frame);  
    40     cvReleaseImage(&pForeImg);  
    41     cvReleaseCapture(&capture);  
    42     return 0;     
    43 }  

    代码没做过多的注释,但现有的注释应该对于理解代码足够了。另外,对于计算机视觉里的任何一种算法都不是万能的,VIBE也不例外,只能说VIBE相对其他算法有一定的优势,但是还是有相当的不足,其pixel-wise-based的灰度建模方式解决不了pixel-wise建模算法共有的问题,其他必要辅助信息的融合是必要的。

  • 相关阅读:
    装饰者模式
    Moon.Orm总目录,及常见问题解决方案(有问题直接在这里问,我会立即作答)
    中国IT格局分析
    细说MVC框架的几大困惑
    一天学一个模式_第一天:策略模式
    一天学一个模式_第三天:单例模式
    一天学一个模式_第二天:代理模式
    News: Microsoft Released URL Rewriter 2.0 RTW
    微软一站式示例代码库 20100125 新增代码示例简介
    微软一站式示例代码库 1月小结
  • 原文地址:https://www.cnblogs.com/ydxt/p/6213601.html
Copyright © 2011-2022 走看看