1.简介
众所周知,GMM(Gaussian Mixture-based Model)是用来分离场景中前景和背景的,或者叫做背景扣除,那么什么叫做背景扣除(Background Subtraction)呢?我们知道所谓的监控系统中,通常都是利用静态相机来捕捉场景的,因此其中比较具有挑战的一步就是如何检测出场景中的突然闯入者,传统的应用中都会假设场景中没有这样的闯入者,而在实际监控场景中,这种情况却是实实在在存在发生的,所以我们不能忽略。对于闯入者的检测,如果我们知道一个场景的统计模型,那些不服从该模型分布的目标像素是不是就可以当做背景,这样的一个过程就叫做背景扣除。
GMM,顾名思义,就是多个高斯的混合,它于1997年由Friedman和Russel提出,1999年才有人给出了它的更新方程,2004年Zoran Zivkovic提出了改进(论文地址)。
2.基本原理
2.1 决策问题
与贝叶斯估计一样,GMM也是一种密度函数的参数估计,只不过模型较贝叶斯而言要复杂的多,应用的场景也不同。
GMM是基于像素的背景扣除,我们需要对一个像素做出是属于背景(Back Ground)还是属于前景(Fore Ground)的决策,因此首先定义如下决策规则:
如果上式大于1,则决策为背景,反之决策为前景;其中是某一个像素的像素值(RGB),为背景模型,为前景模型,而前者正是我们需要通过大量的训练样本集X来估计得到的。想象下贝叶斯决策的基本思想,是不是差不多的。
如果我们是在做一个目标跟踪,并且我们事先知道该跟踪目标的一些相关知识,比如appearance,那么这些知识就可以用来改善背景的扣除。但是在一般情况下,这些相关知识是无法得知的,我们根本不知道它能否被看到,或者它到底是以怎样的形式出现,这时我们有必要对目标的appearance模型做一个假设。假设前景目标满足一个均匀分布,那我们有如下决策:
只要满足上式,我们就判断该像素是属于背景,其中cthr是设置的阈值。
实际实践中,训练集会受到场景中光线的影响,比如白天室外天气状况,还有室内灯光的渐变或开关灯的情况,为了能够适应这些变化,我们需要通过增加新样本或去除旧样本来实时更新样本集,这里我们假设各样本是独立的,因此我们的核心问题就变成如何有效的在线估计出背景模型密度函数。
2.2 GMM模型
对于每一个新的样本,我们都要更新训练集,并重新估计背景模型密度函数,由于样本里面可能包含有前景目标,所以我们先定义为如下密度函数形式:,并使用一个含有m个高斯分量的GMM模型来估计它,即:
其中,和分别是每一个高斯分量的均值和方差的估计值,T是我们选择的一个适应化的周期间隔,满足,是一个混合权重的估计值,>0,≤1;可以看出,这里我们要更新三个参数,均值,方差和权重,接下来大家就会发现,这一更新过程很像卡尔曼滤波,但是却比卡尔曼滤波简单好多好多。
2.3 更新方程
当在t时刻新来一个样本像素时,给出更新方程:
其中,,alpha是一个常量,等于周期T的倒数,它是一个指数的衰减包络,用来控制旧样本带来的影响;是一个二值量,表示属于哪一个高斯分量。
更新过程如下:
当有一个新样本,我们通过计算它与每一个高斯分量的马氏距离(Mahalanobis distance )来判断是否close于该高斯分量,通常只要距离小于3就认为close,这里为方便计算,我们使用距离的平方来表示样本到第m个分量的距离:
如果没有任何一个高斯分量与其close,那么我们就会新生成一个高斯分量,生成的过程为:
,
其中,sigma0是一个初始值;如果这时高斯分量数目超过了我们预先选择的分量总数的话,我们需要去掉一些权重小的高斯分量,以保证我们的高斯分量总数不变。
这个过程可以看做是一个聚类的过程,那些个高斯分量就是我们聚类得到的聚类;通常来说,前景目标拥有小权重的高斯分量,所以我们可以用分量中最大的前B个来近似得到背景密度模型:
再者,如果所有的高斯分量预先按照降序排列好,那么有:
其中,cf是一个属于前景模型但不影响背景模型的最大比例度量;如果一个目标长时间保持不动,它的权重就会变的比cf大,那么就认为是背景的一部分。因此,从公式(4)可以得出结论,如果一个目标在近似n个历史帧中都是静态的,那么就可以认为该目标是背景,其中n近似等于:
3.OpenCV中的GMM使用
Opencv2.0中提供了两个算子,BackgroundSubtractorMOG和BackgroundSubtractorMOG2,而在3.0版本中已经摒弃了前者:
cv::Mat frame,fore_ground; bool stop1(false); Ptr<BackgroundSubtractorMOG2> mog = createBackgroundSubtractorMOG2(20,9,true); while(!stop1){ if(!vp.read_next_frame(frame))break; mog->apply(frame,fore_ground); threshold(fore_ground, fore_ground, 128, 255, THRESH_BINARY_INV); imshow("extracted foreground",fore_ground); if(waitKey(10) >= 0) stop1 = true; }
其中,第一个参数int history是更新时使用的历史帧数目,第二个参数double varThreshold是像素与背景模型之间的距离平方阈值,这个阈值用来确定该像素是否是背景像素,该参数不影响背景的更新;第三个参数bool
detectShadows=true表示是否使用阴影检测。
4.后记
GMM模型中,还有一个比较关键的问题,就是如何选择高斯分量的数目,由于要计算距离,所以数目大的话计算量肯定大,太小也不行,会导致扣除不完整,因此要合理选择,不过在Opencv中已经不要设置该参数。另外,还有一个不能忽视的问题是阴影问题,有时候闯入者可能会对背景造成阴影,因此必要时需要进行阴影检测。