混合高斯学习资料

OpenCV_基于混合高斯模型GMM的运动目标检测

http://blog.csdn.net/icvpr/article/details/8507574

OpenCV的video module中包含了几种较为常用的背景减除方法,其中混合高斯模型(Gaussian of Mixture Models, GMM)方法效果较好。 


常用的目标检测方法:1)帧间差分;2)背景减除;


其中背景减除方法的关键在于建立一个鲁棒的背景模型(背景图像),常用的建立背景模型方法有:

1)均值法;2)中值法;3)滑动平均滤波法;4)单高斯;5)混合高斯模型;6)codebook,等。


混合高斯模型的原理:


每个像素的R、G、B三个通道像素值的变化分别由一个混合高斯模型分布来刻画。这样的好处在于,同一个像素位置处可以呈现多个模态的像素值变化(例如水波纹,晃动的叶子等)。


GMM的出处:Adaptive background mixture models for real-time tracking (1999年由Chris Stau er提出)


OpenCV版本:2.4.2


下面的代码实现了基于GMM的运动目标检测,同时能够消除运动阴影; (基于文献:Improved adaptive Gausian mixture model for background subtraction)

[cpp]  view plain copy
  1. //  基于混合高斯模型的运动目标检测  
  2. //  Author: www.icvpr.com   
  3. //  Blog: http://blog.csdn.net/icvpr    
  4.   
  5. #include <iostream>  
  6. #include <string>  
  7.   
  8. #include <opencv2/opencv.hpp>  
  9.   
  10.   
  11. int main(int argc, char** argv)  
  12. {  
  13.     std::string videoFile = "../test.avi";  
  14.   
  15.     cv::VideoCapture capture;  
  16.     capture.open(videoFile);  
  17.   
  18.     if (!capture.isOpened())  
  19.     {  
  20.         std::cout<<"read video failure"<<std::endl;  
  21.         return -1;  
  22.     }  
  23.   
  24.   
  25.     cv::BackgroundSubtractorMOG2 mog;  
  26.   
  27.     cv::Mat foreground;  
  28.     cv::Mat background;  
  29.   
  30.     cv::Mat frame;  
  31.     long frameNo = 0;  
  32.     while (capture.read(frame))  
  33.     {  
  34.         ++frameNo;  
  35.   
  36.         std::cout<<frameNo<<std::endl;  
  37.   
  38.         // 运动前景检测,并更新背景  
  39.         mog(frame, foreground, 0.001);         
  40.           
  41.         // 腐蚀  
  42.         cv::erode(foreground, foreground, cv::Mat());  
  43.           
  44.         // 膨胀  
  45.         cv::dilate(foreground, foreground, cv::Mat());  
  46.   
  47.         mog.getBackgroundImage(background);   // 返回当前背景图像  
  48.   
  49.         cv::imshow("video", foreground);  
  50.         cv::imshow("background", background);  
  51.   
  52.   
  53.         if (cv::waitKey(25) > 0)  
  54.         {  
  55.             break;  
  56.         }  
  57.     }  
  58.       
  59.   
  60.   
  61.     return 0;  
  62. }  


http://blog.csdn.net/xiaowei_cqu/article/details/23689189

OpenCV中实现了两个版本的高斯混合背景/前景分割方法(Gaussian Mixture-based Background/Foreground Segmentation Algorithm)[1-2],调用接口很明朗,效果也很好。

BackgroundSubtractorMOG 使用示例

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int main(){  
  2.     VideoCapture video("1.avi");  
  3.     Mat frame,mask,thresholdImage, output;  
  4.     video>>frame;  
  5.     BackgroundSubtractorMOG bgSubtractor(20,10,0.5,false);  
  6.     while(true){  
  7.         video>>frame;  
  8.         ++frameNum;  
  9.         bgSubtractor(frame,mask,0.001);  
  10.         imshow("mask",mask);  
  11.         waitKey(10);  
  12.     }  
  13.     return 0;  
  14. }  

构造函数可以使用默认构造函数或带形参的构造函数:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. BackgroundSubtractorMOG::BackgroundSubtractorMOG()  
  2. BackgroundSubtractorMOG::BackgroundSubtractorMOG(int history, int nmixtures,   
  3. double backgroundRatio, double noiseSigma=0)  

其中history为使用历史帧的数目,nmixtures为混合高斯数量,backgroundRatio为背景比例,noiseSigma为噪声权重。

而调用的接口只有重载操作符():

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void BackgroundSubtractorMOG::operator()(InputArray image, OutputArray fgmask, double learningRate=0)  
其中image为当前帧图像,fgmask为输出的前景mask,learningRate为背景学习速率。

以下是使用BackgroundSubtractorMOG进行前景/背景检测的一个截图。


BackgroundSubtractorMOG2 使用示例

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int main(){  
  2.     VideoCapture video("1.avi");  
  3.     Mat frame,mask,thresholdImage, output;  
  4.     //video>>frame;  
  5.     BackgroundSubtractorMOG2 bgSubtractor(20,16,true);  
  6.       
  7.     while(true){  
  8.         video>>frame;  
  9.         ++frameNum;  
  10.         bgSubtractor(frame,mask,0.001);  
  11.         cout<<frameNum<<endl;  
  12.         //imshow("mask",mask);  
  13.         //waitKey(10);  
  14.     }  
  15.     return 0;  
  16. }  

同样的,构造函数可以使用默认构造函数和带形参的构造函数

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. BackgroundSubtractorMOG2::BackgroundSubtractorMOG2()  
  2. BackgroundSubtractorMOG2::BackgroundSubtractorMOG2(int history,   
  3. float varThreshold, bool bShadowDetection=true )  

history同上,varThreshold表示马氏平方距离上使用的来判断是否为背景的阈值(此值不影响背景更新速率),bShadowDetection表示是否使用阴影检测(如果开启阴影检测,则mask中使用127表示阴影)。

使用重载操作符()调用每帧检测函数:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void BackgroundSubtractorMOG2::operator()(InputArray image, OutputArray fgmask, double learningRate=-1)  
参数意义同BackgroundSubtractorMOG中的operator()函数。

同时BackgroundSubtractorMOG2提供了getBackgroundImage()函数用以返回背景图像:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage)  

另外OpenCV的refman中说新建对象以后还有其他和模型油有关的参数可以修改,不过比较坑的是opencv把这个这些函数参数声明为protected,同时没有提供访问接口,所以要修改的话还是要自己修改源文件提供访问接口。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. protected:  
  2.     Size frameSize;  
  3.     int frameType;  
  4.     Mat bgmodel;  
  5.     Mat bgmodelUsedModes;//keep track of number of modes per pixel  
  6.     int nframes;  
  7.     int history;  
  8.     int nmixtures;  
  9.     //! here it is the maximum allowed number of mixture components.  
  10.     //! Actual number is determined dynamically per pixel  
  11.     double varThreshold;  
  12.     // threshold on the squared Mahalanobis distance to decide if it is well described  
  13.     // by the background model or not. Related to Cthr from the paper.  
  14.     // This does not influence the update of the background. A typical value could be 4 sigma  
  15.     // and that is varThreshold=4*4=16; Corresponds to Tb in the paper.  
  16.     /  
  17.     // less important parameters - things you might change but be carefull  
  18.       
  19.     float backgroundRatio;  
  20.     // corresponds to fTB=1-cf from the paper  
  21.     // TB - threshold when the component becomes significant enough to be included into  
  22.     // the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0.  
  23.     // For alpha=0.001 it means that the mode should exist for approximately 105 frames before  
  24.     // it is considered foreground  
  25.     // float noiseSigma;  
  26.     float varThresholdGen;  
  27.     //correspondts to Tg - threshold on the squared Mahalan. dist. to decide  
  28.     //when a sample is close to the existing components. If it is not close  
  29.     //to any a new component will be generated. I use 3 sigma => Tg=3*3=9.  
  30.     //Smaller Tg leads to more generated components and higher Tg might make  
  31.     //lead to small number of components but they can grow too large  
  32.     float fVarInit;  
  33.     float fVarMin;  
  34.     float fVarMax;  
  35.     //initial variance  for the newly generated components.  
  36.     //It will will influence the speed of adaptation. A good guess should be made.  
  37.     //A simple way is to estimate the typical standard deviation from the images.  
  38.     //I used here 10 as a reasonable value  
  39.     // min and max can be used to further control the variance  
  40.     float fCT;//CT - complexity reduction prior  
  41.     //this is related to the number of samples needed to accept that a component  
  42.     //actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get  
  43.     //the standard Stauffer&Grimson algorithm (maybe not exact but very similar)  
  44.     //shadow detection parameters  
  45.     bool bShadowDetection;//default 1 - do shadow detection  
  46.     unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result - 127 default value  
  47.     float fTau;  
  48.     // Tau - shadow threshold. The shadow is detected if the pixel is darker  
  49.     //version of the background. Tau is a threshold on how much darker the shadow can be.  
  50.     //Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow  
  51.     //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003.  

以下是使用BackgroundSubtractorMOG2检测的前景和背景:

参考文献:

[1] KaewTraKulPong, Pakorn, and Richard Bowden. "An improved adaptive background mixture model for real-time tracking with shadow detection." Video-Based Surveillance Systems. Springer US, 2002. 135-144.
[2] Zivkovic, Zoran. "Improved adaptive Gaussian mixture model for background subtraction." Pattern Recognition, 2004. ICPR 2004. Proceedings of the 17th International Conference on. Vol. 2. IEEE, 2004.



(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu 未经允许请勿用于商业用途)




【OpenCV】高斯混合背景提取 

转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7566070

在做火灾检测时尝试了一下用OpenCV中自带的高斯混合背景建模,由于是快速应用,也没推敲太细,日后有机会再研究吧。

如果只是应用,不推敲原理是很简单的。OpenCV自己有一个高斯模型,源代码在安装目录...\opencvsetuppath\src\cvaux的cvbgfg_gaussmix.cpp文件中。

具体算法是根据P. KaewTraKulPong and R. Bowden的论文《An Improved Adaptive Background Mixture Model for Real-time Tracking with Shadow Detection》实现的

源码看起来很简单,除了构造、析构函数,不过几个函数:

//初始化函数
void BackgroundSubtractorMOG::initialize(Size _frameSize, int _frameType); 
//处理单通道图像
static void process8uC1( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fgmask, double learningRate );
//处理多通道图像
static void process8uC3( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fgmask, double learningRate );
//重载构造符(在这里转由 process8uC1 或 process8uC3 处理)
void BackgroundSubtractorMOG::operator()(const Mat& image, Mat& fgmask, double learningRate);
//释放高斯模型
icvReleaseGaussianBGModel( CvGaussBGModel** bg_model );
//更新模型
icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel*  bg_model, double learningRate );
//建立模型
cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters );

//初始化函数
void BackgroundSubtractorMOG::initialize(Size _frameSize, int _frameType); 
//处理单通道图像
static void process8uC1( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fgmask, double learningRate );
//处理多通道图像
static void process8uC3( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fgmask, double learningRate );
//重载构造符(在这里转由 process8uC1 或 process8uC3 处理)
void BackgroundSubtractorMOG::operator()(const Mat& image, Mat& fgmask, double learningRate);
//释放高斯模型
icvReleaseGaussianBGModel( CvGaussBGModel** bg_model );
//更新模型
icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel*  bg_model, double learningRate );
//建立模型
cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters );
如果我们不关心具体的参数,都是用默认值的话,很容易就能建立一个高斯背景提取的模型。

//用第一帧初始化模型
CvBGStatModel* bgModel= cvCreateGaussianBGModel(pInitFrame);


//
void FireDetector::CheckFireMove2(IplImage *pImgFrame)
{
cvUpdateBGStatModel( pImgFrame, bgModel );
// 以左下角为坐标原点
bgModel->foreground->origin = bgModel->background->origin = 1;
//滤除噪声
//cvErode(bgModel->background, bgModel->background);  
//cvErode(bgModel->foreground, bgModel->foreground);    
cvMorphologyEx( pImgMotion, pImgMotion, 0, 0, CV_MOP_CLOSE, 3);
cvMorphologyEx( pImgMotion, pImgMotion, 0, 0, CV_MOP_OPEN, 1 );
}


//用第一帧初始化模型
CvBGStatModel* bgModel= cvCreateGaussianBGModel(pInitFrame);

//
void FireDetector::CheckFireMove2(IplImage *pImgFrame)
{
	cvUpdateBGStatModel( pImgFrame, bgModel );
	// 以左下角为坐标原点
	bgModel->foreground->origin = bgModel->background->origin = 1;
	//滤除噪声
	//cvErode(bgModel->background, bgModel->background);  
	//cvErode(bgModel->foreground, bgModel->foreground);    
	cvMorphologyEx( pImgMotion, pImgMotion, 0, 0, CV_MOP_CLOSE, 3);
	cvMorphologyEx( pImgMotion, pImgMotion, 0, 0, CV_MOP_OPEN, 1 );
}
如果再简化就是
cvUpdateBGStatModel( pImgFrame, bgModel );  
cvUpdateBGStatModel( pImgFrame, bgModel );
一句话,用新的帧更新背景。

有关高斯背景的原理,日后再补上吧~






  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值