下面程序是使用混合高斯建模方法对目前进行检测的程序。运行时,需要传递视频文件的路径参数,或者连接摄像机,否则出错。
selected from:
http://www.opencv.org.cn/index.php/高斯背景建模
http://baike.baidu.com/view/2663975.htm
代码如下:
- #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 %sn",argv[1]);
- return-2;
- }
- //打开摄像头
- if (argc ==1)
- if( !(pCapture =cvCaptureFromCAM(0)))
- {
- fprintf(stderr, "Can not opencamera.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;
- }
程序运行情况如下:
窗口截图是有延时,所以,只能供参考。而且,我的机器运行结果是背景和前景图像都是倒立的。所以要对
- //把图像正过来
- pBkImg->origin=1;
- pFrImg->origin=1;
做修改。
算法分析:
高斯混合模型是用于背景提取的方法,OpenCV的cvaux中cvbgfg_gaussmix.cpp文件根据文献Animproved adaptive background mixture model for real-time trackingwithshadow中提供的方法编写了高斯混合模型函数。其中定义了CvGaussBGModel类用于存放高斯混合模型的各个参数。我用OpenCV使用高斯混合模型函数分以下几步:
1。需要用到icvUpdateGaussianBGModel,icvReleaseGaussianBGModel两个函数,但是源程序中将这两个函数定义为内部函数,需要做一些修改,首先将cvbgfg_gaussmix.cpp中前面两个函数的声明staticvoid CV_CDECL icvReleaseGaussianBGModel( CvGaussBGModel** bg_model);
static int CV_CDECL icvUpdateGaussianBGModel( IplImage*curr_frame, CvGaussBGModel* bg_model);两行代码注释掉。然后在cvbgfg_gaussmix.cpp中间部分两个函数的定义部分,函数头static int和staticvoid改成CV_IMPL int 和CV_IMPL void。最后在cvaux.h文件中CVAPI(CvBGStatModel*)cvCreateGaussianBGModel( IplImage* first_frame,
CvGaussBGStatModelParams* parametersCV_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);regioncount的含义我不确定,我理解是代表背景中不同颜色区域的个数,这个参数我没有用到,它只是icvUpdateGaussianBGModel函数的返回值。
3。现在bg_model已经保存了经过高斯混合模型分类后的结果,bg_model->background保存了背景图像,bg_model->foreground保存了前景图像。