混合高斯模型是用于背景提取的方法,OpenCV的cvaux中cvbgfg_gaussmix.cpp 文件根据文献 "An Improved Adaptive Background Mixture Model for Real-time Tracking and Shadow Detection" by P. KaewTraKulPong and R. Bowden
中提供的方法编写了高斯混合模型函数(The windowing method is used, but not the shadow detection )。其中定义了CvGaussBGModel 类用于存放高斯混合模型的各个参数。我用OpenCV使用高斯混合模型函数分一下几步:
1. 需要用到icvUpdateGaussianBGModel, icvReleaseGaussianBGModel两个函数,但是源程序中将这两个函数定义为内部函数,需要做一些修改,首先将cvbgfg_gaussmix.cpp中前两个函数的声明
static void CV_CDECL icvReleaseGaussianBGModel(CvGaussBGModel**bg_model);
static int CV_CDECL icvUpdateGaussianBGModel(IplImage * curr_frame,CvGaussBGModel* bg_model);
两行代码注释掉。然后在cvbgfg_gaussmix.cpp中间部分两个函数的定义部分,函数头static int 和 static void 改成
CV_IMPL int 和CV_IMPL void.
最后在cvaux.h 文件中
CVAPI(CvBGStatModel*) cvCreateGaussianBGModel(IplImage * first_frame, CvGaussBGStatModelParams* parameters CV_DEFAULT(NULL)); 这句后面加上以下两句
CVAPI(void) icvReleaseGaussianBGModel(CvGaussBGModel ** bg_model);
CVAPI(int) icvUpdateGaussianBGModel( IplImage *curr_frame, CvGaussBGModel *bg_model );
程序修改完毕,点rebuild all, 全部重新编译。
2. 在程序初始化部分定义高斯混合模型参数CvGaussBGModel * bg_model=NULL;
在读取第一帧图像(背景图像)时,进行高速背景建模bg_model=(CvGaussBGModel *) cvCreateGaussianBGModel(image,0); image 可以使灰度图像也可以使彩色图像。接下来再读取当前帧时,更新高斯模型
regioncount=icvUpdateGaussianBGModel(currframe, bg_model);
3. 现在bg_model 已经保存了经过高斯混合模型分类后的结果,bg_model->background 保存了背景图像,bg_model->foreground 保存了前景图像。
#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <cvaux.h>
int main ( int argc, char ** argv)
{
IplImage* pFrame = NULL;
IplImage* pFrImg = NULL;
IplImage* pBkImg = NULL;
CvCapture* pCapture = NULL;
int nFrmNum = 0;
cvNamedWindow("video",1);
cvNamedWindow("background",1);
cvNamedWindow("foreground",1);
cvMoveWindow("video",30,0);
cvMoveWindow("background",360,0);
cvMoveWindow("foreground",690,0);
if (argc > 2)
{
fprintf(stderr, "Usage:bkgrd [video_file_name]/n");
return -1;
}
//打开视频文件
if (argc == 2)
if ( !( pCapture = cvCaptureFromFile( argv[1])))
{
fprintf (stderr, "Can not open video file %s/n", argv[1]);
return -2;
}
//打开摄像头
if ( argc ==1 )
if ( !( pCapture = cvCaptureFromCAM(-1)))
{
fprintf ( stderr, "Can not open camera./n");
return -2;
}
// 初始化高斯混合模型参数
CvGaussBGModel * bg_model=NULL;
while(pFrame = cvQueryFrame( pCapture ))
{
nFrmNum++;
if (nFrmNum ==1)
{
pBkImg = cvCreateImage (cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,3);
pFrImg = cvCreateImage( cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1);
//高斯背景建模,pFrame 可以使多通道图像也可以使单通道图像
// cvCreateGaussianBGModel 函数返回值为CvBGStatModel*,
// 需要强制转换成CvGaussBGModel*
bg_model = (CvGaussBGModel *) cvCreateGaussianBGModel( pFrame,0);
}
else
{
// 更新高斯模型
cvUpdateBGStatModel (pFrame, (CvBGStatModel *) bg_model );
//pFrImg 为前景图像,只能为单通道
// pBkImg 为背景图像,可以为单通道或与pFrame 通道数相同
cvCopy (bg_model ->foreground, pFrImg, 0);
cvCopy (bg_model->background,pBkImg, 0);
//把图像正过来
pBkImg->origin=1;
pFrImg->origin=1;
cvShowImage ("video", pFrame);
cvShowImage ("background",pBkImg);
cvShowImage ("foreground", pFrImg);
if ( cvWaitKey(2) >=0)
break;
}
}
// 释放高斯模型参数占用内存
cvReleaseBGStatModel ((CvBGStatModel **) &bg_model);
cvDestroyWindow ("video");
cvDestroyWindow ("background"):
cvDestroyWindow ("foreground");
cvReleaseImage (&pFrImg);
cvReleaseImage (&pBkImg);
cvReleaseCapture(&pCapture):
return 0;
}