16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M/////////////////////////////////////////////////////////////////////////////////////// 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// By downloading, copying, installing or using the software you agree to this license. 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// If you do not agree to this license, do not download, install, 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// copy or use the software. 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Intel License Agreement 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved. 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners. 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification, 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met: 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * Redistribution's of source code must retain the above copyright notice, 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// this list of conditions and the following disclaimer. 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * Redistribution's in binary form must reproduce the above copyright notice, 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// this list of conditions and the following disclaimer in the documentation 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and/or other materials provided with the distribution. 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * The name of Intel Corporation may not be used to endorse or promote products 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// derived from this software without specific prior written permission. 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed. 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct, 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services; 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability, 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage. 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/ 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This file implements the foreground/background pixel 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// discrimination algorithm described in 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Foreground Object Detection from Videos Containing Complex Background 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Li, Huan, Gu, Tian 2003 9p 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// http://muq.org/~cynbe/bib/foreground-object-detection-from-videos-containing-complex-background.pdf 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cvaux.h" 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <math.h> 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdio.h> 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdlib.h> 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#include <algorithm> 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic double* _cv_max_element( double* start, double* end ) 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double* p = start++; 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; start != end; ++start) { 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (*p < *start) p = start; 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return p; 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void CV_CDECL icvReleaseFGDStatModel( CvFGDStatModel** model ); 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int CV_CDECL icvUpdateFGDStatModel( IplImage* curr_frame, 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFGDStatModel* model ); 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Function cvCreateFGDStatModel initializes foreground detection process 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// parameters: 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// first_frame - frame from video sequence 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// parameters - (optional) if NULL default parameters of the algorithm will be used 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// p_model - pointer to CvFGDStatModel structure 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvBGStatModel* 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateFGDStatModel( IplImage* first_frame, CvFGDStatModelParams* parameters ) 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFGDStatModel* p_model = 0; 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvCreateFGDStatModel" ); 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, pixel_count, buf_size; 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFGDStatModelParams params; 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_IMAGE(first_frame) ) 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" ); 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (first_frame->nChannels != 3) 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "first_frame must have 3 color channels" ); 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Initialize parameters: 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( parameters == NULL ) 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.Lc = CV_BGFG_FGD_LC; 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.N1c = CV_BGFG_FGD_N1C; 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.N2c = CV_BGFG_FGD_N2C; 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.Lcc = CV_BGFG_FGD_LCC; 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.N1cc = CV_BGFG_FGD_N1CC; 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.N2cc = CV_BGFG_FGD_N2CC; 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.delta = CV_BGFG_FGD_DELTA; 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.alpha1 = CV_BGFG_FGD_ALPHA_1; 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.alpha2 = CV_BGFG_FGD_ALPHA_2; 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.alpha3 = CV_BGFG_FGD_ALPHA_3; 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.T = CV_BGFG_FGD_T; 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.minArea = CV_BGFG_FGD_MINAREA; 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.is_obj_without_holes = 1; 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.perform_morphing = 1; 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params = *parameters; 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model = (CvFGDStatModel*)cvAlloc( sizeof(*p_model) )); 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( p_model, 0, sizeof(*p_model) ); 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model->type = CV_BG_MODEL_FGD; 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model->release = (CvReleaseBGStatModel)icvReleaseFGDStatModel; 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model->update = (CvUpdateBGStatModel)icvUpdateFGDStatModel;; 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model->params = params; 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Initialize storage pools: 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pixel_count = first_frame->width * first_frame->height; 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn buf_size = pixel_count*sizeof(p_model->pixel_stat[0]); 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->pixel_stat = (CvBGPixelStat*)cvAlloc(buf_size) ); 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( p_model->pixel_stat, 0, buf_size ); 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn buf_size = pixel_count*params.N2c*sizeof(p_model->pixel_stat[0].ctable[0]); 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->pixel_stat[0].ctable = (CvBGPixelCStatTable*)cvAlloc(buf_size) ); 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( p_model->pixel_stat[0].ctable, 0, buf_size ); 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn buf_size = pixel_count*params.N2cc*sizeof(p_model->pixel_stat[0].cctable[0]); 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->pixel_stat[0].cctable = (CvBGPixelCCStatTable*)cvAlloc(buf_size) ); 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( p_model->pixel_stat[0].cctable, 0, buf_size ); 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0, k = 0; i < first_frame->height; i++ ) { 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < first_frame->width; j++, k++ ) 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model->pixel_stat[k].ctable = p_model->pixel_stat[0].ctable + k*params.N2c; 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model->pixel_stat[k].cctable = p_model->pixel_stat[0].cctable + k*params.N2cc; 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Init temporary images: 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->Ftd = cvCreateImage(cvSize(first_frame->width, first_frame->height), IPL_DEPTH_8U, 1)); 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->Fbd = cvCreateImage(cvSize(first_frame->width, first_frame->height), IPL_DEPTH_8U, 1)); 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->foreground = cvCreateImage(cvSize(first_frame->width, first_frame->height), IPL_DEPTH_8U, 1)); 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->background = cvCloneImage(first_frame)); 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->prev_frame = cvCloneImage(first_frame)); 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( p_model->storage = cvCreateMemStorage()); 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cvGetErrStatus() < 0 ) 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGStatModel* base_ptr = (CvBGStatModel*)p_model; 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( p_model && p_model->release ) 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model->release( &base_ptr ); 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &p_model ); 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_model = 0; 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return (CvBGStatModel*)p_model; 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void CV_CDECL 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReleaseFGDStatModel( CvFGDStatModel** _model ) 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "icvReleaseFGDStatModel" ); 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !_model ) 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "" ); 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *_model ) 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFGDStatModel* model = *_model; 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( model->pixel_stat ) 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &model->pixel_stat[0].ctable ); 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &model->pixel_stat[0].cctable ); 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &model->pixel_stat ); 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseImage( &model->Ftd ); 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseImage( &model->Fbd ); 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseImage( &model->foreground ); 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseImage( &model->background ); 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseImage( &model->prev_frame ); 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMemStorage(&model->storage); 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( _model ); 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Function cvChangeDetection performs change detection for Foreground detection algorithm 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// parameters: 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// prev_frame - 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// curr_frame - 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// change_mask - 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvChangeDetection( IplImage* prev_frame, 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn IplImage* curr_frame, 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn IplImage* change_mask ) 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, b, x, y, thres; 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int PIXELRANGE=256; 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !prev_frame 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || !curr_frame 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || !change_mask 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || prev_frame->nChannels != 3 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || curr_frame->nChannels != 3 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || change_mask->nChannels != 1 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || prev_frame->depth != IPL_DEPTH_8U 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || curr_frame->depth != IPL_DEPTH_8U 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || change_mask->depth != IPL_DEPTH_8U 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || prev_frame->width != curr_frame->width 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || prev_frame->height != curr_frame->height 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || prev_frame->width != change_mask->width 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || prev_frame->height != change_mask->height 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ){ 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return 0; 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero ( change_mask ); 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // All operations per colour 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (b=0 ; b<prev_frame->nChannels ; b++) { 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Create histogram: 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn long HISTOGRAM[PIXELRANGE]; 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (i=0 ; i<PIXELRANGE; i++) HISTOGRAM[i]=0; 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (y=0 ; y<curr_frame->height ; y++) 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* rowStart1 = (uchar*)curr_frame->imageData + y * curr_frame->widthStep + b; 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* rowStart2 = (uchar*)prev_frame->imageData + y * prev_frame->widthStep + b; 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (x=0 ; x<curr_frame->width ; x++, rowStart1+=curr_frame->nChannels, rowStart2+=prev_frame->nChannels) { 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int diff = abs( int(*rowStart1) - int(*rowStart2) ); 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn HISTOGRAM[diff]++; 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double relativeVariance[PIXELRANGE]; 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (i=0 ; i<PIXELRANGE; i++) relativeVariance[i]=0; 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (thres=PIXELRANGE-2; thres>=0 ; thres--) 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // fprintf(stderr, "Iter %d\n", thres); 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum=0; 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sqsum=0; 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int count=0; 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // fprintf(stderr, "Iter %d entering loop\n", thres); 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (j=thres ; j<PIXELRANGE ; j++) { 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += double(j)*double(HISTOGRAM[j]); 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sqsum += double(j*j)*double(HISTOGRAM[j]); 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn count += HISTOGRAM[j]; 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn count = count == 0 ? 1 : count; 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // fprintf(stderr, "Iter %d finishing loop\n", thres); 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double my = sum / count; 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sigma = sqrt( sqsum/count - my*my); 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // fprintf(stderr, "Iter %d sum=%g sqsum=%g count=%d sigma = %g\n", thres, sum, sqsum, count, sigma); 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // fprintf(stderr, "Writing to %x\n", &(relativeVariance[thres])); 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn relativeVariance[thres] = sigma; 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // fprintf(stderr, "Iter %d finished\n", thres); 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Find maximum: 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar bestThres = 0; 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double* pBestThres = _cv_max_element(relativeVariance, relativeVariance+PIXELRANGE); 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bestThres = (uchar)(*pBestThres); if (bestThres <10) bestThres=10; 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (y=0 ; y<prev_frame->height ; y++) 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* rowStart1 = (uchar*)(curr_frame->imageData) + y * curr_frame->widthStep + b; 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* rowStart2 = (uchar*)(prev_frame->imageData) + y * prev_frame->widthStep + b; 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* rowStart3 = (uchar*)(change_mask->imageData) + y * change_mask->widthStep; 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (x = 0; x < curr_frame->width; x++, rowStart1+=curr_frame->nChannels, 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rowStart2+=prev_frame->nChannels, rowStart3+=change_mask->nChannels) { 3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // OR between different color channels 3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int diff = abs( int(*rowStart1) - int(*rowStart2) ); 3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if ( diff > bestThres) 3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *rowStart3 |=255; 3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return 1; 3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define MIN_PV 1E-10 3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define V_C(k,l) ctable[k].v[l] 3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define PV_C(k) ctable[k].Pv 3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define PVB_C(k) ctable[k].Pvb 3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define V_CC(k,l) cctable[k].v[l] 3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define PV_CC(k) cctable[k].Pv 3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define PVB_CC(k) cctable[k].Pvb 3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Function cvUpdateFGDStatModel updates statistical model and returns number of foreground regions 3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// parameters: 3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// curr_frame - current frame from video sequence 3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// p_model - pointer to CvFGDStatModel structure 3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int CV_CDECL 3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvUpdateFGDStatModel( IplImage* curr_frame, CvFGDStatModel* model ) 3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int mask_step = model->Ftd->widthStep; 3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL; 3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn IplImage* prev_frame = model->prev_frame; 3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int region_count = 0; 3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int FG_pixels_count = 0; 3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int deltaC = cvRound(model->params.delta * 256 / model->params.Lc); 3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int deltaCC = cvRound(model->params.delta * 256 / model->params.Lcc); 3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, l; 3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //clear storages 3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvClearMemStorage(model->storage); 3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero(model->foreground); 3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // From foreground pixel candidates using image differencing 3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // with adaptive thresholding. The algorithm is from: 3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // 3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Thresholding for Change Detection 3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Paul L. Rosin 1998 6p 3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // http://www.cis.temple.edu/~latecki/Courses/CIS750-03/Papers/thresh-iccv.pdf 3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // 3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvChangeDetection( prev_frame, curr_frame, model->Ftd ); 3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvChangeDetection( model->background, curr_frame, model->Fbd ); 3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < model->Ftd->height; i++ ) 3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < model->Ftd->width; j++ ) 3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ((uchar*)model->Fbd->imageData)[i*mask_step+j] || ((uchar*)model->Ftd->imageData)[i*mask_step+j] ) 3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float Pb = 0; 3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float Pv = 0; 3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float Pvb = 0; 3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelStat* stat = model->pixel_stat + i * model->Ftd->width + j; 3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelCStatTable* ctable = stat->ctable; 3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelCCStatTable* cctable = stat->cctable; 3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* curr_data = (uchar*)(curr_frame->imageData) + i*curr_frame->widthStep + j*3; 3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* prev_data = (uchar*)(prev_frame->imageData) + i*prev_frame->widthStep + j*3; 3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int val = 0; 3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Is it a motion pixel? 3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ((uchar*)model->Ftd->imageData)[i*mask_step+j] ) 3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !stat->is_trained_dyn_model ) { 3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn val = 1; 3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } else { 3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Compare with stored CCt vectors: 3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; PV_CC(k) > model->params.alpha2 && k < model->params.N1cc; k++ ) 3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if ( abs( V_CC(k,0) - prev_data[0]) <= deltaCC && 3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn abs( V_CC(k,1) - prev_data[1]) <= deltaCC && 3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn abs( V_CC(k,2) - prev_data[2]) <= deltaCC && 3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn abs( V_CC(k,3) - curr_data[0]) <= deltaCC && 3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn abs( V_CC(k,4) - curr_data[1]) <= deltaCC && 3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn abs( V_CC(k,5) - curr_data[2]) <= deltaCC) 3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Pv += PV_CC(k); 3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Pvb += PVB_CC(k); 3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Pb = stat->Pbcc; 3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( 2 * Pvb * Pb <= Pv ) val = 1; 3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( stat->is_trained_st_model ) 4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Compare with stored Ct vectors: 4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; PV_C(k) > model->params.alpha2 && k < model->params.N1c; k++ ) 4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if ( abs( V_C(k,0) - curr_data[0]) <= deltaC && 4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn abs( V_C(k,1) - curr_data[1]) <= deltaC && 4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn abs( V_C(k,2) - curr_data[2]) <= deltaC ) 4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Pv += PV_C(k); 4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Pvb += PVB_C(k); 4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Pb = stat->Pbc; 4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( 2 * Pvb * Pb <= Pv ) val = 1; 4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Update foreground: 4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((uchar*)model->foreground->imageData)[i*mask_step+j] = (uchar)(val*255); 4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn FG_pixels_count += val; 4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } // end if( change detection... 4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } // for j... 4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } // for i... 4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //end BG/FG classification 4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Foreground segmentation. 4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Smooth foreground map: 4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( model->params.perform_morphing ){ 4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvMorphologyEx( model->foreground, model->foreground, 0, 0, CV_MOP_OPEN, model->params.perform_morphing ); 4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvMorphologyEx( model->foreground, model->foreground, 0, 0, CV_MOP_CLOSE, model->params.perform_morphing ); 4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( model->params.minArea > 0 || model->params.is_obj_without_holes ){ 4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Discard under-size foreground regions: 4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // 4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFindContours( model->foreground, model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST ); 4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( seq = first_seq; seq; seq = seq->h_next ) 4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvContour* cnt = (CvContour*)seq; 4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cnt->rect.width * cnt->rect.height < model->params.minArea || 4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (model->params.is_obj_without_holes && CV_IS_SEQ_HOLE(seq)) ) 4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Delete under-size contour: 4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn prev_seq = seq->h_prev; 4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( prev_seq ) 4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn prev_seq->h_next = seq->h_next; 4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( seq->h_next ) seq->h_next->h_prev = prev_seq; 4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn first_seq = seq->h_next; 4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( seq->h_next ) seq->h_next->h_prev = NULL; 4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn region_count++; 4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn model->foreground_regions = first_seq; 4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero(model->foreground); 4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvDrawContours(model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1); 4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } else { 4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn model->foreground_regions = NULL; 4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Check ALL BG update condition: 4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ((float)FG_pixels_count/(model->Ftd->width*model->Ftd->height)) > CV_BGFG_FGD_BG_UPDATE_TRESH ) 4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < model->Ftd->height; i++ ) 4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < model->Ftd->width; j++ ) 4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelStat* stat = model->pixel_stat + i * model->Ftd->width + j; 4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stat->is_trained_st_model = stat->is_trained_dyn_model = 1; 4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Update background model: 4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < model->Ftd->height; i++ ) 4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < model->Ftd->width; j++ ) 4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelStat* stat = model->pixel_stat + i * model->Ftd->width + j; 4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelCStatTable* ctable = stat->ctable; 4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelCCStatTable* cctable = stat->cctable; 4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar *curr_data = (uchar*)(curr_frame->imageData)+i*curr_frame->widthStep+j*3; 4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar *prev_data = (uchar*)(prev_frame->imageData)+i*prev_frame->widthStep+j*3; 4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ((uchar*)model->Ftd->imageData)[i*mask_step+j] || !stat->is_trained_dyn_model ) 4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float alpha = stat->is_trained_dyn_model ? model->params.alpha2 : model->params.alpha3; 5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float diff = 0; 5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int dist, min_dist = 2147483647, indx = -1; 5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //update Pb 5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stat->Pbcc *= (1.f-alpha); 5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !((uchar*)model->foreground->imageData)[i*mask_step+j] ) 5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stat->Pbcc += alpha; 5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Find best Vi match: 5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(k = 0; PV_CC(k) && k < model->params.N2cc; k++ ) 5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Exponential decay of memory 5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_CC(k) *= (1-alpha); 5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_CC(k) *= (1-alpha); 5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( PV_CC(k) < MIN_PV ) 5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_CC(k) = 0; 5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_CC(k) = 0; 5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dist = 0; 5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < 3; l++ ) 5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int val = abs( V_CC(k,l) - prev_data[l] ); 5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( val > deltaCC ) break; 5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dist += val; 5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn val = abs( V_CC(k,l+3) - curr_data[l] ); 5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( val > deltaCC) break; 5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dist += val; 5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( l == 3 && dist < min_dist ) 5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_dist = dist; 5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn indx = k; 5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( indx < 0 ) 5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { // Replace N2th elem in the table by new feature: 5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn indx = model->params.N2cc - 1; 5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_CC(indx) = alpha; 5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_CC(indx) = alpha; 5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //udate Vt 5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < 3; l++ ) 5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn V_CC(indx,l) = prev_data[l]; 5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn V_CC(indx,l+3) = curr_data[l]; 5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { // Update: 5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_CC(indx) += alpha; 5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !((uchar*)model->foreground->imageData)[i*mask_step+j] ) 5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_CC(indx) += alpha; 5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //re-sort CCt table by Pv 5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < indx; k++ ) 5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( PV_CC(k) <= PV_CC(indx) ) 5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //shift elements 5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelCCStatTable tmp1, tmp2 = cctable[indx]; 5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = k; l <= indx; l++ ) 5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tmp1 = cctable[l]; 5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cctable[l] = tmp2; 5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tmp2 = tmp1; 5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float sum1=0, sum2=0; 5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //check "once-off" changes 5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(k = 0; PV_CC(k) && k < model->params.N1cc; k++ ) 5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum1 += PV_CC(k); 5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum2 += PVB_CC(k); 5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sum1 > model->params.T ) stat->is_trained_dyn_model = 1; 5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn diff = sum1 - stat->Pbcc * sum2; 5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Update stat table: 5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( diff > model->params.T ) 5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //printf("once off change at motion mode\n"); 5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //new BG features are discovered 5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; PV_CC(k) && k < model->params.N1cc; k++ ) 5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_CC(k) = 5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (PV_CC(k)-stat->Pbcc*PVB_CC(k))/(1-stat->Pbcc); 5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert(stat->Pbcc<=1 && stat->Pbcc>=0); 6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Handle "stationary" pixel: 6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !((uchar*)model->Ftd->imageData)[i*mask_step+j] ) 6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float alpha = stat->is_trained_st_model ? model->params.alpha2 : model->params.alpha3; 6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float diff = 0; 6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int dist, min_dist = 2147483647, indx = -1; 6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //update Pb 6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stat->Pbc *= (1.f-alpha); 6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !((uchar*)model->foreground->imageData)[i*mask_step+j] ) 6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stat->Pbc += alpha; 6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //find best Vi match 6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < model->params.N2c; k++ ) 6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Exponential decay of memory 6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_C(k) *= (1-alpha); 6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_C(k) *= (1-alpha); 6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( PV_C(k) < MIN_PV ) 6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_C(k) = 0; 6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_C(k) = 0; 6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dist = 0; 6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < 3; l++ ) 6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int val = abs( V_C(k,l) - curr_data[l] ); 6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( val > deltaC ) break; 6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dist += val; 6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( l == 3 && dist < min_dist ) 6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_dist = dist; 6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn indx = k; 6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( indx < 0 ) 6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn {//N2th elem in the table is replaced by a new features 6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn indx = model->params.N2c - 1; 6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_C(indx) = alpha; 6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_C(indx) = alpha; 6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //udate Vt 6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < 3; l++ ) 6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn V_C(indx,l) = curr_data[l]; 6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } else 6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn {//update 6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PV_C(indx) += alpha; 6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !((uchar*)model->foreground->imageData)[i*mask_step+j] ) 6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_C(indx) += alpha; 6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //re-sort Ct table by Pv 6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < indx; k++ ) 6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( PV_C(k) <= PV_C(indx) ) 6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //shift elements 6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGPixelCStatTable tmp1, tmp2 = ctable[indx]; 6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = k; l <= indx; l++ ) 6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tmp1 = ctable[l]; 6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ctable[l] = tmp2; 6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tmp2 = tmp1; 6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Check "once-off" changes: 6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float sum1=0, sum2=0; 6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; PV_C(k) && k < model->params.N1c; k++ ) 6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum1 += PV_C(k); 6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum2 += PVB_C(k); 6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn diff = sum1 - stat->Pbc * sum2; 6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sum1 > model->params.T ) stat->is_trained_st_model = 1; 6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Update stat table: 6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( diff > model->params.T ) 6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //printf("once off change at stat mode\n"); 6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //new BG features are discovered 6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; PV_C(k) && k < model->params.N1c; k++ ) 6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn PVB_C(k) = (PV_C(k)-stat->Pbc*PVB_C(k))/(1-stat->Pbc); 6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stat->Pbc = 1 - stat->Pbc; 7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } // if !(change detection) at pixel (i,j) 7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Update the reference BG image: 7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !((uchar*)model->foreground->imageData)[i*mask_step+j]) 7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* ptr = ((uchar*)model->background->imageData) + i*model->background->widthStep+j*3; 7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !((uchar*)model->Ftd->imageData)[i*mask_step+j] && 7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn !((uchar*)model->Fbd->imageData)[i*mask_step+j] ) 7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Apply IIR filter: 7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < 3; l++ ) 7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int a = cvRound(ptr[l]*(1 - model->params.alpha1) + model->params.alpha1*curr_data[l]); 7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr[l] = (uchar)a; 7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //((uchar*)model->background->imageData)[i*model->background->widthStep+j*3+l]*=(1 - model->params.alpha1); 7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //((uchar*)model->background->imageData)[i*model->background->widthStep+j*3+l] += model->params.alpha1*curr_data[l]; 7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Background change detected: 7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < 3; l++ ) 7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //((uchar*)model->background->imageData)[i*model->background->widthStep+j*3+l] = curr_data[l]; 7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr[l] = curr_data[l]; 7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } // j 7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } // i 7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Keep previous frame: 7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvCopy( curr_frame, model->prev_frame ); 7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return region_count; 7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */ 741