一、GMM发展历史及现状
背景建模方法有很多种,如中值法、均值法、卡尔曼滤波器模型、码本背景模型等,其中混合高斯模型是最经典的算法。GMM最早是由CHris Stauffer等在[1]中提出的,该方法是按照高斯分布对每个像素建立模型, 并通过基于回归滤波的在线 EM 近似方法对模型参数进行更新,它能鲁棒地克服光照变化、 树枝摇动等造成的影响,但该方法也存在一些问题:1)该方法对运动物体在场景中停止不动或者长时间停止时检测失效,而且带有初始学习速度慢,在线更新费时、计算量大;2)无法完整准确地检测大并且运动缓慢的运动目标,运动目标的像素点不集中,只能检测到运动目标的部分轮廓,无法提取出目标对象的完整区域;3)无法将背景显露区域与运动目标区域很好地区分开;4)当运动目标由静止缓慢转化为运动时,易将背景显露区检测为前景,出现“影子”现象。
二、GMM缺点及改进方法
针对上述问题,一些科学研究者又在GMM算法的基础上做了很多的改进:张、白等人[2]引入分块思想,把图像分为L*L块;黄、胡等人[3]也引入了分块的思想,但是他们的分块理念是以当前像素点的8邻域作为一块;华、刘[4]把GMM与改进的帧差法(相邻两帧图像对应像素点8邻域像素值相减之和)相结合,提高了计算效率;Suo等人[5]是将混合高斯模型中的模型个数采改进为自适应的;刘等人[6]融合帧间差分法,检测背景显露区域和运动区域,很好的解决了问题4。除此之外,还有基于纹理的混合高斯模。
三、GMM算法流程
四、代码实现
代码是下部分使用了下面网页的代码:http://blog.youkuaiyun.com/xw20084898/article/details/41826445自己在阅读的时候因为变量太多有些分不清,在参数更新中,和自己阅读的论文有些不同。注释部分是原作参数更新算法:
#include<opencv.hpp>
#include<highgui.h>
#include<cv.h>
using namespace cv;
using namespace std;
#define COMPONET 5 //混合高斯模型个数
#define ALPHA 0.03 //学习率
#define SD_INIT 6 //方差初始值
#define THRESHOLD 0.25 //前景所占比例
#define D 2.5
int main()
{
CvCapture *capture = cvCreateFileCapture("E:\\project2\\videos\\video.avi");
IplImage *frame, *grayFrame, *foreground, *background;
int *foreg, *backg, *rank_index;
double *weight, *mean, *sigma, *u_diff, *rank;
double p = ALPHA / (1 / (double)COMPONET);
double rank_temp = 0;
int rank_index_temp = 0;
CvRNG state; //随机生成状态器
int match, height, width;
frame = cvQueryFrame(capture);
grayFrame = cvCreateImage(CvSize(frame->width, frame->height), IPL_DEPTH_8U, 1);
foreground = cvCreateImage(CvSize(frame->width, frame->height), IPL_DEPTH_8U, 1);
background = cvCreateImage(CvSize(frame->width, frame->height), IPL_DEPTH_8U, 1);
height = grayFrame->height;
width = grayFrame->widthStep;
foreg = (int*)malloc(sizeof(int)*width*height);
backg = (int*)malloc(sizeof(int)*width*height);
rank = (double*)malloc(sizeof(double) * 1 * COMPONET); //优先级
weight = (double*)malloc(sizeof(double)*width*height*COMPONET); //权重
mean = (double *)malloc(sizeof(doub