int main(int argc, char** argv)
{
	IplImage* temp1 = NULL;
    IplImage* temp2 = NULL;
    IplImage* result = NULL;
    IplImage* result1 = NULL;
    IplImage* result2 = NULL;

	CvBGStatModel* bg_model=0;
	CvBGStatModel* bg_model1=0;

    IplImage* rawImage = 0; 
	IplImage* yuvImage = 0; 
	IplImage* rawImage1 = 0;
    IplImage* pFrImg = 0;
	IplImage* pFrImg1= 0;
	IplImage* pFrImg2= 0;
	IplImage* ImaskCodeBookCC = 0;
    CvCapture* capture = 0;

	int c,n;

	maxMod[0] = 25; 
	minMod[0] = 35;
	maxMod[1] = 8;
	minMod[1] = 8;
	maxMod[2] = 8;
	minMod[2] = 8;

    argc=2;
    argv[1]="intelligentroom_raw.avi";
    if( argc > 2 )
	{
		fprintf(stderr, "Usage: bkgrd [video_file_name]\n");
		return -1;
	}
 
    if (argc ==1)
		if( !(capture = cvCaptureFromCAM(-1)))
		{
			fprintf(stderr, "Can not open camera.\n");
			return -2;
		}

    if(argc == 2)
		if( !(capture = cvCaptureFromFile(argv[1])))
		{
			fprintf(stderr, "Can not open video file %s\n", argv[1]);
			return -2;
		}

	bool pause = false;
	bool singlestep = false;

    if( capture )
    {
        cvNamedWindow( "原视频序列图像", 1 );
		cvNamedWindow("不实时更新的Codebook算法[本文]",1);
		cvNamedWindow("实时更新的Codebook算法[本文]",1);
		cvNamedWindow("基于MOG的方法[Chris Stauffer'2001]",1);
		cvNamedWindow("三帧差分", 1);
		cvNamedWindow("基于Bayes decision的方法[Liyuan Li'2003]", 1);
        
		cvMoveWindow("原视频序列图像", 0, 0);
		cvMoveWindow("不实时更新的Codebook算法[本文]", 360, 0);
		cvMoveWindow("实时更新的Codebook算法[本文]", 720, 350);
		cvMoveWindow("基于MOG的方法[Chris Stauffer'2001]", 0, 350);
		cvMoveWindow("三帧差分", 720, 0);
        cvMoveWindow("基于Bayes decision的方法[Liyuan Li'2003]",360, 350);
        int nFrmNum = -1;
        for(;;)
        {
    		if(!pause)
			{
				rawImage = cvQueryFrame( capture );
				++nFrmNum;
				printf("第%d帧\n",nFrmNum);
				if(!rawImage) 
					break;
			}
			if(singlestep)
			{
				pause = true;
			}
			if(0 == nFrmNum) 
			{
				printf(". . . wait for it . . .\n"); 
				
				temp1 = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 3);
				temp2 = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 3);
				result1 = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 1);
				result2 = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 1);
				result = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 1);

				bg_model = cvCreateGaussianBGModel(rawImage);
                bg_model1 = cvCreateFGDStatModel(rawImage);
				rawImage1 = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 3 );

				yuvImage = cvCloneImage(rawImage);
				pFrImg  = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
				pFrImg1 = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
				pFrImg2 = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
				ImaskCodeBookCC = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );

				imageLen = rawImage->width*rawImage->height;

				cA = new codeBook [imageLen];
				cC = new codeBook [imageLen];
				cD = new codeBook [imageLen];

				for(int f = 0; f<imageLen; f++)
				{
					cA[f].numEntries = 0; cA[f].t = 0;
					cC[f].numEntries = 0; cC[f].t = 0;
					cD[f].numEntries = 0; cD[f].t = 0;
				}
				for(int nc=0; nc<nChannels;nc++)
				{
					cbBounds[nc] = 10;
				}
				ch[0] = true;
				ch[1] = true;
				ch[2] = true;
			}
             
        	if( rawImage )
        	{
				if(!pause)
				{					
					cvSmooth(rawImage, rawImage1, CV_GAUSSIAN,3,3);

					cvChangeDetection(temp1, temp2, result1);
					cvChangeDetection(rawImage1, temp1, result2);
					cvAnd(result1, result2, result, NULL);
					cvCopy(temp1,temp2, NULL);
					cvCopy(rawImage,temp1, NULL);

					
					cvUpdateBGStatModel( rawImage, bg_model );
					cvUpdateBGStatModel( rawImage, bg_model1 );
				}

				cvCvtColor( rawImage1, yuvImage, CV_BGR2YCrCb );
				if( !pause && nFrmNum >= 1 && nFrmNum < T  )
				{
					pColor = (uchar *)((yuvImage)->imageData);
					for(int c=0; c<imageLen; c++)
					{
						update_codebook_model(pColor, cA[c],cbBounds,nChannels);
					    trainig_codebook(pColor, cC[c],cbBounds,nChannels);
						pColor += 3;
					}
				}

				if( nFrmNum == T)
				{
					for(c=0; c<imageLen; c++)
					{
						clear_stale_entries(cA[c]);
						training_clear_stale_entries(cC[c]);
					}
				}

				if(nFrmNum > T) 
				{
					pColor = (uchar *)((yuvImage)->imageData);
					uchar maskPixelCodeBook;
					uchar maskPixelCodeBook1;
					uchar maskPixelCodeBook2;
					uchar *pMask = (uchar *)((pFrImg)->imageData);
					uchar *pMask1 = (uchar *)((pFrImg1)->imageData);
					uchar *pMask2 = (uchar *)((pFrImg2)->imageData);
					for(int c=0; c<imageLen; c++)
					{
						//本文中不带自动背景更新的算法输出
						maskPixelCodeBook1=background_Diff(pColor, cA[c],nChannels,minMod,maxMod);
                        *pMask1++ = maskPixelCodeBook1;
						
						//本文中带自动背景更新的算法输出
						if ( !pause && det_update_codebook_cC(pColor, cC[c],cbBounds,nChannels))
						{	
							det_update_codebook_cD(pColor, cD[c],cbBounds,nChannels, nFrmNum); 
							realtime_clear_stale_entries_cD(cD[c], nFrmNum);
							cD_to_cC(cD[c], cC[c], (nFrmNum - T)/5);
							
						}
						else
						{
							realtime_clear_stale_entries_cC(cC[c], nFrmNum);
						
						} 

						maskPixelCodeBook2=background_Diff(pColor, cC[c],nChannels,minMod,maxMod);
						*pMask2++ = maskPixelCodeBook2;  
						pColor += 3;
					}

					cvCopy(pFrImg2,ImaskCodeBookCC);
					if(!pause)
					{
						count_Segmentation(cC,yuvImage,nChannels,minMod,maxMod);
						forgratio = (float) (fgcount)/ imageLen;
					}
				}
				bg_model1->foreground->origin=1;
				bg_model->foreground->origin=1;				
				pFrImg->origin=1;
                pFrImg1->origin=1;
				pFrImg2->origin=1;
				ImaskCodeBookCC->origin=1;
				result->origin=1;
				//connected_Components(pFrImg1,1,40);
				//connected_Components(pFrImg2,1,40);
				
                cvShowImage("基于MOG的方法[Chris Stauffer'2001]", bg_model->foreground);
           		cvShowImage( "原视频序列图像", rawImage );
				cvShowImage("三帧差分", result);
 				cvShowImage( "不实时更新的Codebook算法[本文]",pFrImg1);
				cvShowImage("实时更新的Codebook算法[本文]",pFrImg2);
				cvShowImage("基于Bayes decision的方法[Liyuan Li'2003]", bg_model1->foreground);

	         	c = cvWaitKey(1)&0xFF;
				//End processing on ESC, q or Q
				if(c == 27 || c == 'q' || c == 'Q')
					break;
				//Else check for user input
				switch(c)
				{
					case 'h':
						help();
						break;
					case 'p':
						pause ^= 1;
						break;
					case 's':
						singlestep = 1;
						pause = false;
						break;
					case 'r':
						pause = false;
						singlestep = false;
						break;
				//CODEBOOK PARAMS
                case 'y':
                case '0':
                        ch[0] = 1;
                        ch[1] = 0;
                        ch[2] = 0;
                        printf("CodeBook YUV Channels active: ");
                        for(n=0; n<nChannels; n++)
                                printf("%d, ",ch[n]);
                        printf("\n");
                        break;
                case 'u':
                case '1':
                        ch[0] = 0;
                        ch[1] = 1;
                        ch[2] = 0;
                        printf("CodeBook YUV Channels active: ");
                        for(n=0; n<nChannels; n++)
                                printf("%d, ",ch[n]);
                        printf("\n");
                        break;
                case 'v':
                case '2':
                        ch[0] = 0;
                        ch[1] = 0;
                        ch[2] = 1;
                        printf("CodeBook YUV Channels active: ");
                        for(n=0; n<nChannels; n++)
                                printf("%d, ",ch[n]);
                        printf("\n");
                        break;
                case 'a': //All
                case '3':
                        ch[0] = 1;
                        ch[1] = 1;
                        ch[2] = 1;
                        printf("CodeBook YUV Channels active: ");
                        for(n=0; n<nChannels; n++)
                                printf("%d, ",ch[n]);
                        printf("\n");
                        break;
                case 'b':  //both u and v together
                        ch[0] = 0;
                        ch[1] = 1;
                        ch[2] = 1;
                        printf("CodeBook YUV Channels active: ");
                        for(n=0; n<nChannels; n++)
                                printf("%d, ",ch[n]);
                        printf("\n");
                        break;
                case 'z': 
					printf(" Fadd加1 ");
					Fadd += 1;
					printf("Fadd=%.4d\n",Fadd);										
					break;
				case 'x':
					printf(" Fadd减1 "); 
					Fadd -= 1;					
					printf("Fadd=%.4d\n",Fadd);										
					break;
				case 'n': 
					printf(" Tavgstale加1 ");
					Tavgstale += 1;
					printf("Tavgstale=%.4d\n",Tavgstale);										
					break;
				case 'm': 
					printf(" Tavgstale减1 ");
					Tavgstale -= 1;
					printf("Tavgstale=%.4d\n",Tavgstale);										
					break;
				case 'i': //modify max classification bounds (max bound goes higher)
					for(n=0; n<nChannels; n++)
					{
						if(ch[n])
							maxMod[n] += 1;
						printf("%.4d,",maxMod[n]);
					}
					printf(" CodeBook High Side\n");
					break;
				case 'o': //modify max classification bounds (max bound goes lower)
					for(n=0; n<nChannels; n++)
					{
						if(ch[n])
							maxMod[n] -= 1;
						printf("%.4d,",maxMod[n]);
					}
					printf(" CodeBook High Side\n");
					break;
				case 'k': //modify min classification bounds (min bound goes lower)
					for(n=0; n<nChannels; n++)
					{
						if(ch[n])
							minMod[n] += 1;
						printf("%.4d,",minMod[n]);
					}
					printf(" CodeBook Low Side\n");
					break;
				case 'l': //modify min classification bounds (min bound goes higher)
					for(n=0; n<nChannels; n++)
					{
						if(ch[n])
							minMod[n] -= 1;
						printf("%.4d,",minMod[n]);
					}
					printf(" CodeBook Low Side\n");
					break;
				}
            }
		}		
		cvReleaseCapture( &capture );
		cvReleaseBGStatModel((CvBGStatModel**)&bg_model);
		cvReleaseBGStatModel((CvBGStatModel**)&bg_model1);

        cvDestroyWindow( "原视频序列图像" );
		cvDestroyWindow( "不实时更新的Codebook算法[本文]");
		cvDestroyWindow( "实时更新的Codebook算法[本文]");
		cvDestroyWindow( "基于MOG的方法[Chris Stauffer'2001]");
		cvDestroyWindow( "三帧差分" );
		cvDestroyWindow( "基于Bayes decision的方法[Liyuan Li'2003]");

		cvReleaseImage(&temp1);
		cvReleaseImage(&temp2);
		cvReleaseImage(&result);
		cvReleaseImage(&result1);
		cvReleaseImage(&result2);
		cvReleaseImage(&pFrImg);
		cvReleaseImage(&pFrImg1);
		cvReleaseImage(&pFrImg2);

		if(yuvImage) cvReleaseImage(&yuvImage);
		if(rawImage) cvReleaseImage(&rawImage);
		if(rawImage1) cvReleaseImage(&rawImage1);
		if(ImaskCodeBookCC) cvReleaseImage(&ImaskCodeBookCC);
		delete [] cA;
		delete [] cC;
		delete [] cD;
    }
	else
	{ 
		printf("\n\nDarn, Something wrong with the parameters\n\n"); help();
	}
    return 0;
}
Beispiel #2
0
// Function cvUpdateFGDStatModel updates statistical model and returns number of foreground regions
// parameters:
//      curr_frame  - current frame from video sequence
//      p_model     - pointer to CvFGDStatModel structure
static int CV_CDECL
icvUpdateFGDStatModel( IplImage* curr_frame, CvFGDStatModel*  model, double )
{
    int            mask_step = model->Ftd->widthStep;
    CvSeq         *first_seq = NULL, *prev_seq = NULL, *seq = NULL;
    IplImage*      prev_frame = model->prev_frame;
    int            region_count = 0;
    int            FG_pixels_count = 0;
    int            deltaC  = cvRound(model->params.delta * 256 / model->params.Lc);
    int            deltaCC = cvRound(model->params.delta * 256 / model->params.Lcc);
    int            i, j, k, l;

    //clear storages
    cvClearMemStorage(model->storage);
    cvZero(model->foreground);

    // From foreground pixel candidates using image differencing
    // with adaptive thresholding.  The algorithm is from:
    //
    //    Thresholding for Change Detection
    //    Paul L. Rosin 1998 6p
    //    http://www.cis.temple.edu/~latecki/Courses/CIS750-03/Papers/thresh-iccv.pdf
    //
    cvChangeDetection( prev_frame, curr_frame, model->Ftd );
    cvChangeDetection( model->background, curr_frame, model->Fbd );

    for( i = 0; i < model->Ftd->height; i++ )
    {
        for( j = 0; j < model->Ftd->width; j++ )
        {
            if( ((uchar*)model->Fbd->imageData)[i*mask_step+j] || ((uchar*)model->Ftd->imageData)[i*mask_step+j] )
            {
	        float Pb  = 0;
                float Pv  = 0;
                float Pvb = 0;

                CvBGPixelStat* stat = model->pixel_stat + i * model->Ftd->width + j;

                CvBGPixelCStatTable*   ctable = stat->ctable;
                CvBGPixelCCStatTable* cctable = stat->cctable;
    
                uchar* curr_data = (uchar*)(curr_frame->imageData) + i*curr_frame->widthStep + j*3;
                uchar* prev_data = (uchar*)(prev_frame->imageData) + i*prev_frame->widthStep + j*3;

                int val = 0;

                // Is it a motion pixel?
                if( ((uchar*)model->Ftd->imageData)[i*mask_step+j] )
                {
		    if( !stat->is_trained_dyn_model ) {

                        val = 1;

		    } else {

                        // Compare with stored CCt vectors:
                        for( k = 0;  PV_CC(k) > model->params.alpha2 && k < model->params.N1cc;  k++ )
                        {
                            if ( abs( V_CC(k,0) - prev_data[0]) <=  deltaCC &&
                                 abs( V_CC(k,1) - prev_data[1]) <=  deltaCC &&
                                 abs( V_CC(k,2) - prev_data[2]) <=  deltaCC &&
                                 abs( V_CC(k,3) - curr_data[0]) <=  deltaCC &&
                                 abs( V_CC(k,4) - curr_data[1]) <=  deltaCC &&
                                 abs( V_CC(k,5) - curr_data[2]) <=  deltaCC)
                            {
                                Pv += PV_CC(k);
                                Pvb += PVB_CC(k);
                            }
                        }
                        Pb = stat->Pbcc;
                        if( 2 * Pvb * Pb <= Pv ) val = 1;
                    }
                }
                else if( stat->is_trained_st_model )
                {
                    // Compare with stored Ct vectors:
                    for( k = 0;  PV_C(k) > model->params.alpha2 && k < model->params.N1c;  k++ )
                    {
                        if ( abs( V_C(k,0) - curr_data[0]) <=  deltaC &&
                             abs( V_C(k,1) - curr_data[1]) <=  deltaC &&
                             abs( V_C(k,2) - curr_data[2]) <=  deltaC )
                        {
                            Pv += PV_C(k);
                            Pvb += PVB_C(k);
                        }
                    }
                    Pb = stat->Pbc;
                    if( 2 * Pvb * Pb <= Pv ) val = 1;
                }

                // Update foreground:
                ((uchar*)model->foreground->imageData)[i*mask_step+j] = (uchar)(val*255);
                FG_pixels_count += val;

            }		// end if( change detection...
        }		// for j...
    }			// for i...
    //end BG/FG classification

    // Foreground segmentation.
    // Smooth foreground map:
    if( model->params.perform_morphing ){
        cvMorphologyEx( model->foreground, model->foreground, 0, 0, CV_MOP_OPEN,  model->params.perform_morphing );
        cvMorphologyEx( model->foreground, model->foreground, 0, 0, CV_MOP_CLOSE, model->params.perform_morphing );
    }
   
   
    if( model->params.minArea > 0 || model->params.is_obj_without_holes ){

        // Discard under-size foreground regions:
	//
        cvFindContours( model->foreground, model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );
        for( seq = first_seq; seq; seq = seq->h_next )
        {
            CvContour* cnt = (CvContour*)seq;
            if( cnt->rect.width * cnt->rect.height < model->params.minArea || 
                (model->params.is_obj_without_holes && CV_IS_SEQ_HOLE(seq)) )
            {
                // Delete under-size contour:
                prev_seq = seq->h_prev;
                if( prev_seq )
                {
                    prev_seq->h_next = seq->h_next;
                    if( seq->h_next ) seq->h_next->h_prev = prev_seq;
                }
                else
                {
                    first_seq = seq->h_next;
                    if( seq->h_next ) seq->h_next->h_prev = NULL;
                }
            }
            else
            {
                region_count++;
            }
        }        
        model->foreground_regions = first_seq;
        cvZero(model->foreground);
        cvDrawContours(model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);

    } else {

        model->foreground_regions = NULL;
    }

    // Check ALL BG update condition:
    if( ((float)FG_pixels_count/(model->Ftd->width*model->Ftd->height)) > CV_BGFG_FGD_BG_UPDATE_TRESH )
    {
         for( i = 0; i < model->Ftd->height; i++ )
             for( j = 0; j < model->Ftd->width; j++ )
             {
                 CvBGPixelStat* stat = model->pixel_stat + i * model->Ftd->width + j;
                 stat->is_trained_st_model = stat->is_trained_dyn_model = 1;
             }
    }


    // Update background model:
    for( i = 0; i < model->Ftd->height; i++ )
    {
        for( j = 0; j < model->Ftd->width; j++ )
        {
            CvBGPixelStat* stat = model->pixel_stat + i * model->Ftd->width + j;
            CvBGPixelCStatTable* ctable = stat->ctable;
            CvBGPixelCCStatTable* cctable = stat->cctable;

            uchar *curr_data = (uchar*)(curr_frame->imageData)+i*curr_frame->widthStep+j*3;
            uchar *prev_data = (uchar*)(prev_frame->imageData)+i*prev_frame->widthStep+j*3;

            if( ((uchar*)model->Ftd->imageData)[i*mask_step+j] || !stat->is_trained_dyn_model )
            {
                float alpha = stat->is_trained_dyn_model ? model->params.alpha2 : model->params.alpha3;
                float diff = 0;
                int dist, min_dist = 2147483647, indx = -1;

                //update Pb
                stat->Pbcc *= (1.f-alpha);
                if( !((uchar*)model->foreground->imageData)[i*mask_step+j] )
                {
                    stat->Pbcc += alpha;
                }

                // Find best Vi match:
                for(k = 0; PV_CC(k) && k < model->params.N2cc; k++ )
                {
                    // Exponential decay of memory
                    PV_CC(k)  *= (1-alpha);
                    PVB_CC(k) *= (1-alpha);
                    if( PV_CC(k) < MIN_PV )
                    {
                        PV_CC(k) = 0;
                        PVB_CC(k) = 0;
                        continue;
                    }

                    dist = 0;
                    for( l = 0; l < 3; l++ )
                    {
                        int val = abs( V_CC(k,l) - prev_data[l] );
                        if( val > deltaCC ) break;
                        dist += val;
                        val = abs( V_CC(k,l+3) - curr_data[l] );
                        if( val > deltaCC) break;
                        dist += val;
                    }
                    if( l == 3 && dist < min_dist )
                    {
                        min_dist = dist;
                        indx = k;
                    }
                }


                if( indx < 0 )
                {   // Replace N2th elem in the table by new feature:
                    indx = model->params.N2cc - 1;
                    PV_CC(indx) = alpha;
                    PVB_CC(indx) = alpha;
                    //udate Vt
                    for( l = 0; l < 3; l++ )
                    {
                        V_CC(indx,l) = prev_data[l];
                        V_CC(indx,l+3) = curr_data[l];
                    }
                }
                else
                {   // Update:
                    PV_CC(indx) += alpha;
                    if( !((uchar*)model->foreground->imageData)[i*mask_step+j] )
                    {
                        PVB_CC(indx) += alpha;
                    }
                }

                //re-sort CCt table by Pv
                for( k = 0; k < indx; k++ )
                {
                    if( PV_CC(k) <= PV_CC(indx) )
                    {
                        //shift elements
                        CvBGPixelCCStatTable tmp1, tmp2 = cctable[indx];
                        for( l = k; l <= indx; l++ )
                        {
                            tmp1 = cctable[l];
                            cctable[l] = tmp2;
                            tmp2 = tmp1;
                        }
                        break;
                    }
                }


                float sum1=0, sum2=0;
                //check "once-off" changes
                for(k = 0; PV_CC(k) && k < model->params.N1cc; k++ )
                {
                    sum1 += PV_CC(k);
                    sum2 += PVB_CC(k);
                }
                if( sum1 > model->params.T ) stat->is_trained_dyn_model = 1;
                
                diff = sum1 - stat->Pbcc * sum2;
                // Update stat table:
                if( diff >  model->params.T )
                {
                    //printf("once off change at motion mode\n");
                    //new BG features are discovered
                    for( k = 0; PV_CC(k) && k < model->params.N1cc; k++ )
                    {
                        PVB_CC(k) =
                            (PV_CC(k)-stat->Pbcc*PVB_CC(k))/(1-stat->Pbcc);
                    }
                    assert(stat->Pbcc<=1 && stat->Pbcc>=0);
                }
            }

            // Handle "stationary" pixel:
            if( !((uchar*)model->Ftd->imageData)[i*mask_step+j] )
            {
                float alpha = stat->is_trained_st_model ? model->params.alpha2 : model->params.alpha3;
                float diff = 0;
                int dist, min_dist = 2147483647, indx = -1;

                //update Pb
                stat->Pbc *= (1.f-alpha);
                if( !((uchar*)model->foreground->imageData)[i*mask_step+j] )
                {
                    stat->Pbc += alpha;
                }

                //find best Vi match
                for( k = 0; k < model->params.N2c; k++ )
                {
                    // Exponential decay of memory
                    PV_C(k) *= (1-alpha);
                    PVB_C(k) *= (1-alpha);
                    if( PV_C(k) < MIN_PV )
                    {
                        PV_C(k) = 0;
                        PVB_C(k) = 0;
                        continue;
                    }
                    
                    dist = 0;
                    for( l = 0; l < 3; l++ )
                    {
                        int val = abs( V_C(k,l) - curr_data[l] );
                        if( val > deltaC ) break;
                        dist += val;
                    }
                    if( l == 3 && dist < min_dist )
                    {
                        min_dist = dist;
                        indx = k;
                    }
                }

                if( indx < 0 )
                {//N2th elem in the table is replaced by a new features
                    indx = model->params.N2c - 1;
                    PV_C(indx) = alpha;
                    PVB_C(indx) = alpha;
                    //udate Vt
                    for( l = 0; l < 3; l++ )
                    {
                        V_C(indx,l) = curr_data[l];
                    }
                } else
                {//update
                    PV_C(indx) += alpha;
                    if( !((uchar*)model->foreground->imageData)[i*mask_step+j] )
                    {
                        PVB_C(indx) += alpha;
                    }
                }

                //re-sort Ct table by Pv
                for( k = 0; k < indx; k++ )
                {
                    if( PV_C(k) <= PV_C(indx) )
                    {
                        //shift elements
                        CvBGPixelCStatTable tmp1, tmp2 = ctable[indx];
                        for( l = k; l <= indx; l++ )
                        {
                            tmp1 = ctable[l];
                            ctable[l] = tmp2;
                            tmp2 = tmp1;
                        }
                        break;
                    }
                }

                // Check "once-off" changes:
                float sum1=0, sum2=0;
                for( k = 0; PV_C(k) && k < model->params.N1c; k++ )
                {
                    sum1 += PV_C(k);
                    sum2 += PVB_C(k);
                }
                diff = sum1 - stat->Pbc * sum2;
                if( sum1 > model->params.T ) stat->is_trained_st_model = 1;

                // Update stat table:
                if( diff >  model->params.T )
                {
                    //printf("once off change at stat mode\n");
                    //new BG features are discovered
                    for( k = 0; PV_C(k) && k < model->params.N1c; k++ )
                    {
                        PVB_C(k) = (PV_C(k)-stat->Pbc*PVB_C(k))/(1-stat->Pbc);
                    }
                    stat->Pbc = 1 - stat->Pbc;
                }
            }		// if !(change detection) at pixel (i,j)

            // Update the reference BG image:
            if( !((uchar*)model->foreground->imageData)[i*mask_step+j])
            {
                uchar* ptr = ((uchar*)model->background->imageData) + i*model->background->widthStep+j*3;
                
                if( !((uchar*)model->Ftd->imageData)[i*mask_step+j] &&
                    !((uchar*)model->Fbd->imageData)[i*mask_step+j] )
                {
                    // Apply IIR filter:
                    for( l = 0; l < 3; l++ )
                    {
                        int a = cvRound(ptr[l]*(1 - model->params.alpha1) + model->params.alpha1*curr_data[l]);
                        ptr[l] = (uchar)a;
                        //((uchar*)model->background->imageData)[i*model->background->widthStep+j*3+l]*=(1 - model->params.alpha1);
                        //((uchar*)model->background->imageData)[i*model->background->widthStep+j*3+l] += model->params.alpha1*curr_data[l];
                    }
                }
                else
                {
                    // Background change detected:
                    for( l = 0; l < 3; l++ )
                    {
                        //((uchar*)model->background->imageData)[i*model->background->widthStep+j*3+l] = curr_data[l];
                        ptr[l] = curr_data[l];
                    }
                }
            }
        }		// j
    }			// i

    // Keep previous frame:
    cvCopy( curr_frame, model->prev_frame );

    return region_count;
}
Beispiel #3
0
// Function updateBGMeanStatModel updates model and returns number of foreground regions
// parameters:
//      curr_frame  - current frame from video sequence
//      p_model     - pointer to BGMeanStatModel structure
int
updateBGMeanStatModel( IplImage* curr_frame, BGMeanStatModel*  model ){
  int region_count = 0;

  if (model->bg_frame_count >= model->params.bg_update_rate){
    model->bg_frame_count = 0;//reset counter
    //update model
    //insert curr_frame in circular buffer
    int i,j,k;
    int frame_cbuffer_pixelcluster_step = model->params.n_frames*model->background->nChannels;
    int frame_cbuffer_cbufferpixel_offset = model->cbuffer_idx*model->background->nChannels;
    int frame_cbuffer_width_step = model->background->width*frame_cbuffer_pixelcluster_step;
    
    cv::Scalar mean, std_dev;

    //idx_last is used to avoid calc mean over not initialized values
    if (model->cbuffer_nentries_init < model->params.n_frames)
      model->cbuffer_nentries_init++;

    //bg and curr_frame have same size
    for (i = 0; i < model->background->height; i++){//rows
      uchar* frame_cbuffer_row_p = model->frame_cbuffer + i*frame_cbuffer_width_step;
      uchar* curr_frame_row_p = (uchar*)curr_frame->imageData + i*curr_frame->widthStep;
      uchar* bg_frame_row_p = (uchar*)model->background->imageData + i*model->background->widthStep;
      for (j = 0; j < model->background->width; j++){//cols
	uchar* pixel_cluster_p = frame_cbuffer_row_p + j*frame_cbuffer_pixelcluster_step;
	uchar* pixel_to_update_p = pixel_cluster_p + frame_cbuffer_cbufferpixel_offset;//pointer to pixel in circular buffer to update
	uchar* curr_pixel_p = curr_frame_row_p + j*model->background->nChannels;//pixel from curr_frame
	//update circular buffer
	for (k=0; k<model->background->nChannels; k++)
	  pixel_to_update_p[k] = curr_pixel_p[k];
	
	//calc mean and std dev   
	cv::Mat pixel_cluster(1, std::min(model->params.n_frames,model->cbuffer_nentries_init), 
			      CV_MAKETYPE(CV_8U,model->background->nChannels),
			      pixel_cluster_p);/*cv::Mat with pixel cluster with last n frames*/
	cv::meanStdDev(pixel_cluster, mean, std_dev);
	
	int pixel_offset = j*model->background->nChannels + (i * model->background->width * model->background->nChannels);
	//double* mean_p = model->mean + pixel_offset;
	//double* std_dev_p = model->std_dev + pixel_offset;
	uchar* bg_p = bg_frame_row_p + j*model->background->nChannels;
	/*copy mean and std dev to each channel*/
	for (k=0; k<model->background->nChannels; k++){
	  //mean_p[k] = mean[k];
	  //std_dev_p[k] = std_dev[k];
	  double mean_weight = get_mean_weight(std_dev[k]);
	  double a = ((double)bg_p[k])*(1-mean_weight);
	  double b = mean[k]*mean_weight;
	  bg_p[k] = cv::saturate_cast<uchar>(a+b);
	}
      }
    }
    //update circular buffer idx
    model->cbuffer_idx++;
    if (model->cbuffer_idx >= model->params.n_frames)
      model->cbuffer_idx = 0;
  }
  
  if (model->fg_frame_count >= model->params.fg_update_rate){
    model->fg_frame_count = 0;//reset counter
    //clear fg
    cvZero(model->foreground);

    //difference bg - curr_frame. Adaptative threshold
    cvChangeDetection( model->background, curr_frame, model->foreground );//FIXME: just 3 channel support

    //segmentation if required
    if (model->params.perform_segmentation)
      region_count = bgfgSegmentation((CvBGStatModel*)model, &model->params.sg_params);
  }

  //update counters
  model->fg_frame_count++;
  model->bg_frame_count++;

  return region_count;
}