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 is based on the "An Improved Adaptive Background Mixture Model for 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Real-time Tracking with Shadow Detection" by P. KaewTraKulPong and R. Bowden 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// http://personal.ee.surrey.ac.uk/Personal/R.Bowden/publications/avbs01/avbs01.pdf 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// The windowing method is used, but not the shadow detection. I make some of my 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// own modifications which make more sense. There are some errors in some of their 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// equations. 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//IplImage values of image that are useful 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//int nSize; /* sizeof(IplImage) */ 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//int depth; /* pixel depth in bits: IPL_DEPTH_8U ...*/ 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//int nChannels; /* OpenCV functions support 1,2,3 or 4 channels */ 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//int width; /* image width in pixels */ 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//int height; /* image height in pixels */ 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//int imageSize; /* image data size in bytes in case of interleaved data)*/ 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//char *imageData; /* pointer to aligned image data */ 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//char *imageDataOrigin; /* pointer to very origin of image -deallocation */ 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//Values useful for gaussian integral 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//0.5 - 0.19146 - 0.38292 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//1.0 - 0.34134 - 0.68268 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//1.5 - 0.43319 - 0.86638 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//2.0 - 0.47725 - 0.95450 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//2.5 - 0.49379 - 0.98758 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//3.0 - 0.49865 - 0.99730 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//3.5 - 0.4997674 - 0.9995348 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//4.0 - 0.4999683 - 0.9999366 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cvaux.h" 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//internal functions for gaussian background detection 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvInsertionSortGaussians( CvGaussBGPoint* g_point, double* sort_key, CvGaussBGStatModelParams *bg_model_params ); 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Test whether pixel can be explained by background model; 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Return -1 if no match was found; otherwise the index in match[] is returned 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvMatchTest(...) assumes what all color channels component exhibit the same variance 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvMatchTest2(...) accounts for different variances per color channel 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int icvMatchTest( double* src_pixel, int nChannels, int* match, 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGPoint* g_point, const CvGaussBGStatModelParams *bg_model_params ); 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*static int icvMatchTest2( double* src_pixel, int nChannels, int* match, 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGPoint* g_point, const CvGaussBGStatModelParams *bg_model_params );*/ 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn The update procedure differs between 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * the initialization phase (named *Partial* ) and 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * the normal phase (named *Full* ) 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn The initalization phase is defined as not having processed <win_size> frames yet 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvUpdateFullWindow( double* src_pixel, int nChannels, 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* match, 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point, 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params ); 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvUpdateFullNoMatch( IplImage* gm_image, int p, 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* match, 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point, 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params); 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvUpdatePartialWindow( double* src_pixel, int nChannels, int* match, 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point, const CvGaussBGStatModelParams *bg_model_params ); 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvUpdatePartialNoMatch( double* src_pixel, int nChannels, 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* match, 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point, 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params); 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvGetSortKey( const int nChannels, double* sort_key, const CvGaussBGPoint* g_point, 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params ); 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvBackgroundTest( const int nChannels, int n, int i, int j, int *match, CvGaussBGModel* bg_model ); 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void CV_CDECL icvReleaseGaussianBGModel( CvGaussBGModel** bg_model ); 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int CV_CDECL icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel* bg_model ); 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#define for if(0);else for 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//g = 1 for first gaussian in list that matches else g = 0 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//Rw is the learning rate for weight and Rg is leaning rate for mean and variance 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//Ms is the match_sum which is the sum of matches for a particular gaussian 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//Ms values are incremented until the sum of Ms values in the list equals window size L 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//SMs is the sum of match_sums for gaussians in the list 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//Rw = 1/SMs note the smallest Rw gets is 1/L 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//Rg = g/Ms for SMs < L and Rg = g/(w*L) for SMs = L 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//The list is maintained in sorted order using w/sqrt(variance) as a key 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//If there is no match the last gaussian in the list is replaced by the new gaussian 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//This will result in changes to SMs which results in changes in Rw and Rg. 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//If a gaussian is replaced and SMs previously equaled L values of Ms are computed from w 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//w[n+1] = w[n] + Rw*(g - w[n]) weight 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//u[n+1] = u[n] + Rg*(x[n+1] - u[n]) mean value Sg is sum n values of g 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//v[n+1] = v[n] + Rg*((x[n+1] - u[n])*(x[n+1] - u[n])) - v[n]) variance 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvBGStatModel* 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters ) 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGModel* bg_model = 0; 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvCreateGaussianBGModel" ); 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double var_init; 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGStatModelParams params; 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, m, n; 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //init parameters 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( parameters == NULL ) 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { /* These constants are defined in cvaux/include/cvaux.h: */ 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.win_size = CV_BGFG_MOG_WINDOW_SIZE; 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.bg_threshold = CV_BGFG_MOG_BACKGROUND_THRESHOLD; 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.std_threshold = CV_BGFG_MOG_STD_THRESHOLD; 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.weight_init = CV_BGFG_MOG_WEIGHT_INIT; 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.variance_init = CV_BGFG_MOG_SIGMA_INIT*CV_BGFG_MOG_SIGMA_INIT; 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.minArea = CV_BGFG_MOG_MINAREA; 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params.n_gauss = CV_BGFG_MOG_NGAUSSIANS; 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn params = *parameters; 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_IMAGE(first_frame) ) 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" ); 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( bg_model = (CvGaussBGModel*)cvAlloc( sizeof(*bg_model) )); 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( bg_model, 0, sizeof(*bg_model) ); 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->type = CV_BG_MODEL_MOG; 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->release = (CvReleaseBGStatModel)icvReleaseGaussianBGModel; 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->update = (CvUpdateBGStatModel)icvUpdateGaussianBGModel; 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->params = params; 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //prepare storages 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( bg_model->g_point = (CvGaussBGPoint*)cvAlloc(sizeof(CvGaussBGPoint)* 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((first_frame->width*first_frame->height) + 256))); 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( bg_model->background = cvCreateImage(cvSize(first_frame->width, 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn first_frame->height), IPL_DEPTH_8U, first_frame->nChannels)); 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( bg_model->foreground = cvCreateImage(cvSize(first_frame->width, 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn first_frame->height), IPL_DEPTH_8U, 1)); 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( bg_model->storage = cvCreateMemStorage()); 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //initializing 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn var_init = 2 * params.std_threshold * params.std_threshold; 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( bg_model->g_point[0].g_values = 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (CvGaussBGValues*)cvAlloc( sizeof(CvGaussBGValues)*params.n_gauss* 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (first_frame->width*first_frame->height + 128))); 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0, n = 0; i < first_frame->height; i++ ) 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < first_frame->width; j++, n++ ) 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int p = i*first_frame->widthStep+j*first_frame->nChannels; 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values = 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[0].g_values + n*params.n_gauss; 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[0].weight = 1; //the first value seen has weight one 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[0].match_sum = 1; 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( m = 0; m < first_frame->nChannels; m++) 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[0].variance[m] = var_init; 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[0].mean[m] = (unsigned char)first_frame->imageData[p + m]; 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 1; k < params.n_gauss; k++) 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[k].weight = 0; 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[k].match_sum = 0; 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( m = 0; m < first_frame->nChannels; m++){ 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[k].variance[m] = var_init; 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->g_point[n].g_values[k].mean[m] = 0; 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->countFrames = 0; 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cvGetErrStatus() < 0 ) 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBGStatModel* base_ptr = (CvBGStatModel*)bg_model; 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( bg_model && bg_model->release ) 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->release( &base_ptr ); 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &bg_model ); 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model = 0; 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return (CvBGStatModel*)bg_model; 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void CV_CDECL 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReleaseGaussianBGModel( CvGaussBGModel** _bg_model ) 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "icvReleaseGaussianBGModel" ); 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !_bg_model ) 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "" ); 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *_bg_model ) 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGModel* bg_model = *_bg_model; 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( bg_model->g_point ) 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &bg_model->g_point[0].g_values ); 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &bg_model->g_point ); 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseImage( &bg_model->background ); 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseImage( &bg_model->foreground ); 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMemStorage(&bg_model->storage); 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( bg_model, 0, sizeof(*bg_model) ); 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( _bg_model ); 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int CV_CDECL 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel* bg_model ) 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, n; 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int region_count = 0; 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL; 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->countFrames++; 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0, n = 0; i < curr_frame->height; i++ ) 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < curr_frame->width; j++, n++ ) 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int match[CV_BGFG_MOG_MAX_NGAUSSIANS]; 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sort_key[CV_BGFG_MOG_MAX_NGAUSSIANS]; 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int nChannels = curr_frame->nChannels; 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int p = curr_frame->widthStep*i+j*nChannels; 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // A few short cuts 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point = &bg_model->g_point[n]; 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams bg_model_params = bg_model->params; 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double pixel[4]; 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int no_match; 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < nChannels; k++ ) 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pixel[k] = (uchar)curr_frame->imageData[p+k]; 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn no_match = icvMatchTest( pixel, nChannels, match, g_point, &bg_model_params ); 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( bg_model->countFrames >= bg_model->params.win_size ) 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvUpdateFullWindow( pixel, nChannels, match, g_point, &bg_model->params ); 3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( no_match == -1) 3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvUpdateFullNoMatch( curr_frame, p, match, g_point, &bg_model_params ); 3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvUpdatePartialWindow( pixel, nChannels, match, g_point, &bg_model_params ); 3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( no_match == -1) 3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvUpdatePartialNoMatch( pixel, nChannels, match, g_point, &bg_model_params ); 3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvGetSortKey( nChannels, sort_key, g_point, &bg_model_params ); 3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvInsertionSortGaussians( g_point, sort_key, (CvGaussBGStatModelParams *)&bg_model_params ); 3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvBackgroundTest( nChannels, n, i, j, match, bg_model ); 3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //foreground filtering 3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //filter small regions 3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvClearMemStorage(bg_model->storage); 3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 ); 3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 ); 3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST ); 3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( seq = first_seq; seq; seq = seq->h_next ) 3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvContour* cnt = (CvContour*)seq; 3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea ) 3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //delete small contour 3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn prev_seq = seq->h_prev; 3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( prev_seq ) 3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn prev_seq->h_next = seq->h_next; 3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( seq->h_next ) seq->h_next->h_prev = prev_seq; 3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn first_seq = seq->h_next; 3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( seq->h_next ) seq->h_next->h_prev = NULL; 3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn region_count++; 3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->foreground_regions = first_seq; 3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero(bg_model->foreground); 3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1); 3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return region_count; 3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvInsertionSortGaussians( CvGaussBGPoint* g_point, double* sort_key, CvGaussBGStatModelParams *bg_model_params ) 3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j; 3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i < bg_model_params->n_gauss; i++ ) 3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double index = sort_key[i]; 3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = i; j > 0 && sort_key[j-1] < index; j-- ) //sort decending order 3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double temp_sort_key = sort_key[j]; 3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sort_key[j] = sort_key[j-1]; 3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sort_key[j-1] = temp_sort_key; 3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGValues temp_gauss_values = g_point->g_values[j]; 3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[j] = g_point->g_values[j-1]; 3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[j-1] = temp_gauss_values; 3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// sort_key[j] = index; 3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int icvMatchTest( double* src_pixel, int nChannels, int* match, 3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGPoint* g_point, 3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params ) 3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int k; 3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int matchPosition=-1; 3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for ( k = 0; k < bg_model_params->n_gauss; k++) match[k]=0; 3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for ( k = 0; k < bg_model_params->n_gauss; k++) { 3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum_d2 = 0.0; 3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double var_threshold = 0.0; 3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(int m = 0; m < nChannels; m++){ 3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double d = g_point->g_values[k].mean[m]- src_pixel[m]; 3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum_d2 += (d*d); 3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn var_threshold += g_point->g_values[k].variance[m]; 3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } //difference < STD_LIMIT*STD_LIMIT or difference**2 < STD_LIMIT*STD_LIMIT*VAR 3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn var_threshold = bg_model_params->std_threshold*bg_model_params->std_threshold*var_threshold; 3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if(sum_d2 < var_threshold){ 3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn match[k] = 1; 3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn matchPosition = k; 3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return matchPosition; 4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int icvMatchTest2( double* src_pixel, int nChannels, int* match, 4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGPoint* g_point, 4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params ) 4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int k, m; 4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int matchPosition=-1; 4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < bg_model_params->n_gauss; k++ ) 4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn match[k] = 0; 4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < bg_model_params->n_gauss; k++ ) 4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum_d2 = 0.0, var_threshold; 4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( m = 0; m < nChannels; m++ ) 4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double d = g_point->g_values[k].mean[m]- src_pixel[m]; 4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum_d2 += (d*d) / (g_point->g_values[k].variance[m] * g_point->g_values[k].variance[m]); 4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } //difference < STD_LIMIT*STD_LIMIT or difference**2 < STD_LIMIT*STD_LIMIT*VAR 4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn var_threshold = bg_model_params->std_threshold*bg_model_params->std_threshold; 4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sum_d2 < var_threshold ) 4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn match[k] = 1; 4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn matchPosition = k; 4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return matchPosition; 4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/ 4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvUpdateFullWindow( double* src_pixel, int nChannels, int* match, 4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point, 4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params ) 4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const double learning_rate_weight = (1.0/(double)bg_model_params->win_size); 4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(int k = 0; k < bg_model_params->n_gauss; k++){ 4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].weight = g_point->g_values[k].weight + 4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (learning_rate_weight*((double)match[k] - 4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].weight)); 4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if(match[k]){ 4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double learning_rate_gaussian = (double)match[k]/(g_point->g_values[k].weight* 4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (double)bg_model_params->win_size); 4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(int m = 0; m < nChannels; m++){ 4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const double tmpDiff = src_pixel[m] - g_point->g_values[k].mean[m]; 4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].mean[m] = g_point->g_values[k].mean[m] + 4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (learning_rate_gaussian * tmpDiff); 4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].variance[m] = g_point->g_values[k].variance[m]+ 4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (learning_rate_gaussian*((tmpDiff*tmpDiff) - g_point->g_values[k].variance[m])); 4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvUpdatePartialWindow( double* src_pixel, int nChannels, int* match, CvGaussBGPoint* g_point, const CvGaussBGStatModelParams *bg_model_params ) 4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int k, m; 4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int window_current = 0; 4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < bg_model_params->n_gauss; k++ ) 4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn window_current += g_point->g_values[k].match_sum; 4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < bg_model_params->n_gauss; k++ ) 4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].match_sum += match[k]; 4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double learning_rate_weight = (1.0/((double)window_current + 1.0)); //increased by one since sum 4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].weight = g_point->g_values[k].weight + 4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (learning_rate_weight*((double)match[k] - g_point->g_values[k].weight)); 4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( g_point->g_values[k].match_sum > 0 && match[k] ) 4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double learning_rate_gaussian = (double)match[k]/((double)g_point->g_values[k].match_sum); 4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( m = 0; m < nChannels; m++ ) 4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const double tmpDiff = src_pixel[m] - g_point->g_values[k].mean[m]; 4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].mean[m] = g_point->g_values[k].mean[m] + 4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (learning_rate_gaussian*tmpDiff); 4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].variance[m] = g_point->g_values[k].variance[m]+ 4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (learning_rate_gaussian*((tmpDiff*tmpDiff) - g_point->g_values[k].variance[m])); 4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvUpdateFullNoMatch( IplImage* gm_image, int p, int* match, 4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point, 4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params) 4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int k, m; 4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double alpha; 4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int match_sum_total = 0; 4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //new value of last one 4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[bg_model_params->n_gauss - 1].match_sum = 1; 5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //get sum of all but last value of match_sum 5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < bg_model_params->n_gauss ; k++ ) 5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn match_sum_total += g_point->g_values[k].match_sum; 5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[bg_model_params->n_gauss - 1].weight = 1./(double)match_sum_total; 5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( m = 0; m < gm_image->nChannels ; m++ ) 5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // first pass mean is image value 5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[bg_model_params->n_gauss - 1].variance[m] = bg_model_params->variance_init; 5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[bg_model_params->n_gauss - 1].mean[m] = (unsigned char)gm_image->imageData[p + m]; 5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn alpha = 1.0 - (1.0/bg_model_params->win_size); 5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < bg_model_params->n_gauss - 1; k++ ) 5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].weight *= alpha; 5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( match[k] ) 5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].weight += alpha; 5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void 5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvUpdatePartialNoMatch(double *pixel, 5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int nChannels, 5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* /*match*/, 5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point, 5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params) 5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int k, m; 5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //new value of last one 5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[bg_model_params->n_gauss - 1].match_sum = 1; 5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //get sum of all but last value of match_sum 5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int match_sum_total = 0; 5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(k = 0; k < bg_model_params->n_gauss ; k++) 5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn match_sum_total += g_point->g_values[k].match_sum; 5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(m = 0; m < nChannels; m++) 5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //first pass mean is image value 5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[bg_model_params->n_gauss - 1].variance[m] = bg_model_params->variance_init; 5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[bg_model_params->n_gauss - 1].mean[m] = pixel[m]; 5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(k = 0; k < bg_model_params->n_gauss; k++) 5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn g_point->g_values[k].weight = (double)g_point->g_values[k].match_sum / 5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (double)match_sum_total; 5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvGetSortKey( const int nChannels, double* sort_key, const CvGaussBGPoint* g_point, 5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvGaussBGStatModelParams *bg_model_params ) 5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int k, m; 5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < bg_model_params->n_gauss; k++ ) 5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Avoid division by zero 5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( g_point->g_values[k].match_sum > 0 ) 5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Independence assumption between components 5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double variance_sum = 0.0; 5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( m = 0; m < nChannels; m++ ) 5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_sum += g_point->g_values[k].variance[m]; 5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sort_key[k] = g_point->g_values[k].weight/sqrt(variance_sum); 5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sort_key[k]= 0.0; 5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvBackgroundTest( const int nChannels, int n, int i, int j, int *match, CvGaussBGModel* bg_model ) 5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int m, b; 5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar pixelValue = (uchar)255; // will switch to 0 if match found 5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double weight_sum = 0.0; 5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvGaussBGPoint* g_point = bg_model->g_point; 5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( m = 0; m < nChannels; m++) 5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->background->imageData[ bg_model->background->widthStep*i + j*nChannels + m] = (unsigned char)(g_point[n].g_values[0].mean[m]+0.5); 5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( b = 0; b < bg_model->params.n_gauss; b++) 5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn weight_sum += g_point[n].g_values[b].weight; 5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( match[b] ) 5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pixelValue = 0; 5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( weight_sum > bg_model->params.bg_threshold ) 5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bg_model->foreground->imageData[ bg_model->foreground->widthStep*i + j] = pixelValue; 5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */ 598