博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

混合高斯模型

Posted on 2010-11-16 01:02  编著人  阅读(842)  评论(0编辑  收藏  举报

http://blog.csdn.net/wqvbjhc/archive/2010/04/15/5485242.aspx

混合高斯模型跟高斯变量之和看起来有一点像, 注意不要把它们弄混淆了. 混合高斯模型给出的概率密度函数实际上是几个高斯概率密度函数的加权和:

  p(x) = /sum_{i=1}^n p_i N(x; /bar{x}_i, P_i)

其中/sum_{i=1}^np_i = 1 . 定义事件A_i = /{x /sim N(/bar{x}_i, P_i)/} , 则/mathbb{P}/{A_i/} = p_i . 据此可以产生服从上述混合高斯概率密度分布的样本.

混合分布的均值为

  /bar{x} = /sum_{i=1}^n p_i /bar{x}_i

方差为

  /mathbb{E}((x - /bar{x})(x - /bar{x})') = 
/sum_{i=1}^n p_i P_i + /sum_{i=1}^n p_i /bar{x}_i /bar{x}_i' - 
/bar{x}/bar{x}'

计算均值和方差的公式不仅适用于几个(多维)高斯分布混合的情况, 还适用于非高斯分布的情况.

高斯变量之和就没什么好说的了, 几个高斯变量之和是一个新的高斯变量.

高斯背景模型在 运动检测中的应用


     原理 : 高斯模型就是用高斯概率密度函数(正态分布曲线)精确地量化事物,将一个事物分解为若干的基于高斯概率密度函数(正态分布曲线)形成的模型。
    对图像背景建立高斯模型的原理及过程:图像灰度直方图反映的是图像中某个灰度值出现的频次,也可以认为是图像灰度概率密度的估计。如果图像所包含的目标区域和背景区域相比比较大,且背景区域和目标区域在灰度上有一定的差异,那么该图像的灰度直方图呈现双峰-谷形状,其中一个峰对应于目标,另一个峰对应于背景的中心灰度。对于复杂的图像,尤其是医学图像,一般是多峰的。通过将直方图的多峰特性看作是多个高斯分布的叠加,可以解决图像的分割问题。

    在智能监控系统中,对于运动目标的检测是中心内容,而在运动目标检测提取中,背景目标对于目标的识别和跟踪至关重要。而建模正是背景目标提取的一个重要环节。

    我们首先要提起背景和前景的概念,前景是指在假设背景为静止的情况下,任何有意义的运动物体即为前景。建模的基本思想是从当前帧中提取前景,其目的是使背景更接近当前视频帧的背景。即利用当前帧和视频序列中的当前背景帧进行加权平均来更新背景,但是由于光照突变以及其他外界环境的影响,一般的建模后的背景并非十分干净清晰,而高斯混合模型是是建模最为成功的方法之一。

     混合高斯模型使用K(基本为3到5个)个高斯模型来表征图像中各个像素点的特征,在新一帧图像获得后更新混合高斯模型, 用当前图像中的每个像素点与混合高斯模型匹配,如果成功则判定该点为背景点, 否则为前景点。 通观整个高斯模型,主要是有方差和均值两个参数决定,对均值和方差的学习,采取不同的学习机制,将直接影响到模型的稳定性、精确性和收敛性 。由于我们是对运动目标的背景提取建模,因此需要对高斯模型中方差和均值两个参数实时更新。为提高模型的学习能力,改进方法对均值和方差的更新采用不同的学习率;为 提高在繁忙的场景下,大而慢的运动目标的检测效果,引入权值均值的概念,建立背景图像并实时更新,然后结合权值、权值均值和背景图像对像素点进行前景和背景的分类。

       到这里为止,混合高斯模型的建模基本完成,我在归纳一下其中的流程,首先初始化预先定义的几个高斯模型,对高斯模型中的参数进行初始化,并求出之后将要用到的参数。其次,对于每一帧中的每一个像素进行处理,看其是否匹配某个模型,若匹配,则将其归入该模型中,并对该模型根据新的像素值进行更新,若不匹配,则以该像素建立一个高斯模型,初始化参数,代理原有模型中最不可能的模型。最后选择前面几个最有可能的模型作为背景模型,为背景目标提取做铺垫。

 

    方法: 目前,运动物体检测的问题主要分为两类,摄像机固定和摄像机运动。对于摄像机运动的运动物体检 测问题,比较著名的解决方案是光流法,通过求解偏微分方程求的图像序列的光流场,从而预测摄像机的运动状态。对于摄像机固定的情形,当然也可以用光流法, 但是由于光流法的复杂性,往往难以实时的计算,所以我采用高斯背景模型。因为,在摄像机固定的情况下,背景的变化是缓慢的,而且大都是光照,风等等的影响,通过对背景建模,对一幅给定图像分离前景和背景,一般来说,前景就是运动物体,从而达到运动物体检测的目的。
  单分布高斯背景模型
  单分布高斯背景模型认为,对一个背景图像,特定像素亮度的分布满足高斯分布,即对背景图像B, (x,y)点的亮度满足:
  IB (x,y) ~ N(u,d)
  这样我们的背景模型的每个象素属性包括两个参数:平均值u 和 方差d。
  对于一幅给定的图像G,如果 Exp(-(IG (x,y)-u(x,y))^2/(2*d^2)) > T,认为(x,y)是背景点,反之是前景点。
  同时,随着时间的变化,背景图像也会发生缓慢的变化,这时我们要不断更新每个象素点的参数
  u(t+1,x,y) = a*u(t,x,y) + (1-a)*I(x,y)
  这里,a称为更新参数,表示背景变化的速度,一般情况下,我们不更新d(实验中发现更不更新 d,效果变化不大)。

openCV中高斯混合模型的应用

  高斯混合模型是用于背景提取的方法,OpenCV的cvaux中 cvbgfg_gaussmix.cpp文件根据文献"An improved adaptive background mixture model for real-time tracking with shadow"中提供的方法编写了高斯混合模型函数。其中定义了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 );regioncount的含义我不确定,我理解是代表背景中不同颜色区域的个数,这个参数我没有用到,它只是 icvUpdateGaussianBGModel函数的返回值。
  3。现在bg_model已经保存了经过高斯混合模型分类后的结 果,bg_model->background保存了背景图像,bg_model->foreground保存了前景图像。
 

  1. include <stdio.h>  
  2. #include <cv.h>  
  3. #include <cxcore.h>  
  4. #include <highgui.h>  
  5. #include <cvaux.h>//必须引此头文件  
  6. int main( int argc, char** argv )  
  7. {  
  8. IplImage* pFrame = NULL;    
  9. IplImage* pFrImg = NULL;  
  10. IplImage* pBkImg = NULL;    
  11. CvCapture* pCapture = NULL;    
  12. int nFrmNum = 0;  
  13. cvNamedWindow("video", 1);  
  14. cvNamedWindow("background",1);  
  15. cvNamedWindow("foreground",1);    
  16. cvMoveWindow("video", 30, 0);  
  17. cvMoveWindow("background", 360, 0);  
  18. cvMoveWindow("foreground", 690, 0);  
  19. if( argc > 2 )    
  20. {     
  21. fprintf(stderr, "Usage: bkgrd [video_file_name]\n");     
  22. return -1;    
  23. }  
  24. //打开视频文件  
  25. if(argc == 2)    
  26. if( !(pCapture = cvCaptureFromFile(argv[1])))     
  27. {    
  28. fprintf(stderr, "Can not open video file %s\n", argv[1]);    
  29. return -2;     
  30. }  
  31. //打开摄像头  
  32. if (argc == 1)    
  33. if( !(pCapture = cvCaptureFromCAM(-1)))     
  34. {    
  35. fprintf(stderr, "Can not open camera.\n");    
  36. return -2;     
  37. }    
  38. //初始化高斯混合模型参数  
  39. CvGaussBGModel* bg_model=NULL;  
  40. while(pFrame = cvQueryFrame( pCapture ))    
  41. {     
  42. nFrmNum++;           
  43. if(nFrmNum == 1)    
  44. {     
  45. pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,3);    
  46. pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);     
  47. //高斯背景建模,pFrame可以是多通道图像也可以是单通道图像  
  48. //cvCreateGaussianBGModel函数返回值为 CvBGStatModel*,  
  49. //需要强制转换成CvGaussBGModel*  
  50. bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame, 0);  
  51. }     
  52. else  
  53. {     
  54. //更新高斯模型  
  55. cvUpdateBGStatModel(pFrame, (CvBGStatModel *)bg_model );  
  56. //pFrImg为前景图像,只能为单通道  
  57. //pBkImg为背景图像,可以为单通道或与pFrame通道数相同  
  58. cvCopy(bg_model->foreground,pFrImg,0);  
  59. cvCopy(bg_model->background,pBkImg,0);  
  60. //把图像正过来  
  61. pBkImg->origin=1;  
  62. pFrImg->origin=1;  
  63. cvShowImage("video", pFrame);     
  64. cvShowImage("background", pBkImg);     
  65. cvShowImage("foreground", pFrImg);        
  66. if( cvWaitKey(2) >= 0 )       
  67. break;     
  68. }     
  69. }  
  70. //释放高斯模型参数占用内存    
  71.  cvReleaseBGStatModel((CvBGStatModel**)&bg_model);  
  72. cvDestroyWindow("video");  
  73. cvDestroyWindow("background");  
  74. cvDestroyWindow("foreground");    
  75. cvReleaseImage(&pFrImg);  
  76. cvReleaseImage(&pBkImg);    
  77. cvReleaseCapture(&pCapture);    
  78. return 0;  
  79. }