/////////////////////////cvUpdateBGStatModel//////////////////////////////////
//函数功能:背景模型的更新,不仅要更新高斯分布函数的参数,还要更新各高斯函数的权重
#include "stdafx.h"
#include "GMM.h"
using namespace std;
CvBGStatModel *CreateGaussianBGModel( IplImage*first_frame,CvGaussBGStatModelParams* parameters )
{
CvGaussBGModel* bg_model = 0;
CV_FUNCNAME( "cvCreateGaussianBGModel" );
__BEGIN__;
double var_init;
CvGaussBGStatModelParams params;
int i, j, k, m, n;
// init parameters
if( parameters == NULL )
{
params.win_size = CV_BGFG_MOG_WINDOW_SIZE; // 初始化阶段的帧数;用户自定义模型学 习率a=1/win_size;
params.bg_threshold = CV_BGFG_MOG_BACKGROUND_THRESHOLD;
params.std_threshold = CV_BGFG_MOG_STD_THRESHOLD;
params.weight_init = CV_BGFG_MOG_WEIGHT_INIT;
params.variance_init = CV_BGFG_MOG_SIGMA_INIT*CV_BGFG_MOG_SIGMA_INIT; //方差
params.minArea = CV_BGFG_MOG_MINAREA;
params.n_gauss = CV_BGFG_MOG_NGAUSSIANS; //高斯分布函数的个数
}
else
{
params = *parameters; //用户自定义参数
}
if( !CV_IS_IMAGE(first_frame) )
CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" );
CV_CALL( bg_model = (CvGaussBGModel*)cvAlloc( sizeof(*bg_model) ));
memset( bg_model, 0, sizeof(*bg_model) );
bg_model->type = CV_BG_MODEL_MOG; //CV_BG_MODEL_MOG为高斯背景模型
//bg_model->release = (CvReleaseBGStatModel)ReleaseGaussianBGModel;
bg_model->update = (CvUpdateBGStatModel)UpdateGaussianBGModel;
bg_model->params = params;
//prepare storages
CV_CALL( bg_model->g_point = (CvGaussBGPoint*)cvAlloc(sizeof(CvGaussBGPoint)*
((first_frame->width*first_frame->height) + 256)));
CV_CALL( bg_model->background = cvCreateImage(cvSize(first_frame->width,
first_frame->height), IPL_DEPTH_8U, first_frame->nChannels));
CV_CALL( bg_model->foreground = cvCreateImage(cvSize(first_frame->width,
first_frame->height), IPL_DEPTH_8U, 1));
CV_CALL( bg_model->storage = cvCreateMemStorage());
//initializing
var_init = 2 * params.std_threshold * params.std_threshold; //初始化方差
CV_CALL( bg_model->g_point[0].g_values =
(CvGaussBGValues*)cvAlloc( sizeof(CvGaussBGValues)*params.n_gauss*
(first_frame->width*first_frame->height + 128)));
for( i = 0, n = 0; i < first_frame->height; i++ ) //行
{
for( j = 0; j < first_frame->width; j++, n++ ) //列
{
const int p = i*first_frame->widthStep+j*first_frame->nChannels;
//以下几步是对第一个高斯函数做初始化
bg_model->g_point[n].g_values = bg_model->g_point[0].g_values + n*params.n_gauss;
bg_model->g_point[n].g_values[0].weight = 1; //权值赋为1
bg_model->g_point[n].g_values[0].match_sum = 1; //高斯函数被匹配的次数
for( m = 0; m < first_frame->nChannels; m++)
{
bg_model->g_point[n].g_values[0].variance[m] = var_init;
//均值赋为当前像素的值
bg_model->g_point[n].g_values[0].mean[m] = (unsigned char)first_frame->imageData[p + m];
}
//除第一以外的高斯分布函数的初始化(均值、权值和匹配次数都置零)
for( k = 1; k < params.n_gauss; k++)
{
bg_model->g_point[n].g_values[k].weight = 0;
bg_model->g_point[n].g_values[k].match_sum = 0;
for( m = 0; m < first_frame->nChannels; m++){
bg_model->g_point[n].g_values[k].variance[m] = var_init;
bg_model->g_point[n].g_values[k].mean[m] = 0;
}
}
}
} //g_point[]:像素,g_values[]:高斯分布函数,mean[]:通道
bg_model->countFrames = 0;
__END__;
if( cvGetErrStatus() < 0 )
{
CvBGStatModel* base_ptr = (CvBGStatModel*)bg_model;
if( bg_model && bg_model->release )
bg_model->release( &base_ptr );
else
cvFree( &bg_model );
bg_model = 0;
}
return (CvBGStatModel*)bg_model;
}
void UpdateGaussianBGModel( IplImage* curr_frame,IplImage* pImg, CvGaussBGModel* bg_model )
{
int i, j, k, n;
int region_count = 0;
CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;
bg_model->countFrames++;
for( i = 0, n = 0; i < curr_frame->height; i++ )
{
for( j = 0; j < curr_frame->width; j++, n++ )
{
int match[CV_BGFG_MOG_MAX_NGAUSSIANS]; //对高斯函数做标记,match[m]=1表示函数m为匹配的高斯分布函数
double sort_key[CV_BGFG_MOG_MAX_NGAUSSIANS]; //此数组存贮每个高斯函数的均值与方差比值
const int nChannels = curr_frame->nChannels;
const int p = curr_frame->widthStep*i+j*nChannels;
CvGaussBGPoint* g_point = &bg_model->g_point[n];
const CvGaussBGStatModelParams bg_model_params = bg_model->params;
double pixel[4]; // pixel[]存贮当前像素的各通道RGB值
int no_match;
for( k = 0; k < nChannels; k++ )
pixel[k] = (uchar)curr_frame->imageData[p+k];
no_match = MatchTest( pixel, nChannels, match, g_point, &bg_model_params ); //检查是否有与当前像素匹配的高斯函数1,表示匹配上,为背景;
if( bg_model->countFrames >= bg_model->params.win_size )
{
UpdateFullWindow( pixel, nChannels, match, g_point, &bg_model->params );
if( no_match == -1)
UpdateFullNoMatch( curr_frame, p, match, g_point, &bg_model_params );
}
else
{
UpdatePartialWindow( pixel, nChannels, match, g_point, &bg_model_params );
if( no_match == -1)
UpdatePartialNoMatch( pixel, nChannels, match, g_point, &bg_model_params );
}
GetSortKey( nChannels, sort_key, g_point, &bg_model_params );
InsertionSortGaussians( g_point, sort_key, (CvGaussBGStatModelParams *)&bg_model_params );
BackgroundTest(pImg,nChannels, n, i, j, match, bg_model );
cvReleaseBGStatModel((CvBGStatModel**)&bg_model);
}
}
//foreground filtering
//filter small regions
//cvClearMemStorage(bg_model->storage);
////cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 );
////cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 );
//cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );
//for( seq = first_seq; seq; seq = seq->h_next )
//{
// CvContour* cnt = (CvContour*)seq;
// if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea )
// {
// //delete small contour
// prev_seq = seq->h_prev;
// if( prev_seq )
// {
// prev_seq->h_next = seq->h_next;
// if( seq->h_next ) seq->h_next->h_prev = prev_seq;
// }
// else
// {
// first_seq = seq->h_next;
// if( seq->h_next ) seq->h_next->h_prev = NULL;
// }
// }
// else
// {
// region_count++;
// }
//}
//bg_model->foreground_regions = first_seq;
//cvZero(bg_model->foreground);
//cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);
//cvDrawContours(curr_frame, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);
//return t;
}
/////////////////////////////////////MatchTest//////////////////////////////////////////
//函数功能:拿当前像素的值与已存在的高斯分布函数比较,查找是否存在匹配的的高斯分布函数,如果有则返回 k值(高斯分布函数的序号)
int MatchTest( double* src_pixel, int nChannels, int* match,
const CvGaussBGPoint* g_point,
const CvGaussBGStatModelParams *bg_model_params )
{ //参数的传递:src_pixel为piexl[]:即当前像素的各通道值
int k;
int matchPosition=-1;
for ( k = 0; k < bg_model_params->n_gauss; k++)
match[k]=0;
for ( k = 0; k < bg_model_params->n_gauss; k++)
if (g_point->g_values[k].match_sum > 0)
{
double sum_d2 = 0.0;
double var_threshold = 0.0;
for(int m = 0; m < nChannels; m++)
{
double d = g_point->g_values[k].mean[m]- src_pixel[m]; //通道m的原始模型值与当前像素的值之差
sum_d2 += (d*d);
var_threshold += g_point->g_values[k].variance[m];
}
//当前sum_d2为d0,d1,d2的平方和,var_threshold的值为像素各通道方差之和
var_threshold = bg_model_params->std_threshold* bg_model_params->std_threshold * var_threshold;
if(sum_d2 < var_threshold) //查看是否可以与某高斯分�
评论0