混合高斯模型GMM
混合高斯模型GMM我总结的有两种实现方法,一种是直接使用OPENCV中的MOG函数实现前景检测;另外一种是自己根据GMM的原理编写程序。两种方法对比,方法一比方法二简单,速度快。但是方法二后期可改动的空间大,可以结合其他算法。以下贴出两种方法的实现代码,我是在opencv2.4.10+vs2010中实验通过的。
方法一:
- // 基于混合高斯模型的运动目标检测
- // Author: www.icvpr.com
- // Blog: http://blog.csdn.net/icvpr
- #include <iostream>
- #include <string>
- #include <opencv2/opencv.hpp>
- int main(int argc, char** argv)
- {
- std::string videoFile = "../test.avi";
- cv::VideoCapture capture;
- capture.open(videoFile);
- if (!capture.isOpened())
- {
- std::cout<<"read video failure"<<std::endl;
- return -1;
- }
- cv::BackgroundSubtractorMOG2 mog;
- cv::Mat foreground;
- cv::Mat background;
- cv::Mat frame;
- long frameNo = 0;
- while (capture.read(frame))
- {
- ++frameNo;
- std::cout<<frameNo<<std::endl;
- // 运动前景检测,并更新背景
- mog(frame, foreground, 0.001);
- // 腐蚀
- cv::erode(foreground, foreground, cv::Mat());
- // 膨胀
- cv::dilate(foreground, foreground, cv::Mat());
- mog.getBackgroundImage(background); // 返回当前背景图像
- cv::imshow("video", foreground);
- cv::imshow("background", background);
- if (cv::waitKey(25) > 0)
- {
- break;
- }
- }
- return 0;
- }
实验结果:
当前帧图像
当前背景图像
前景图像
经过腐蚀和膨胀处理后的前景图像
(白色为运动目标区域;灰色为阴影区域;黑色为背景)
方法二:
MOG_BGS.h
- #pragma once
- #include <iostream>
- #include "opencv2/opencv.hpp"
- using namespace cv;
- using namespace std;
- //定义gmm模型用到的变量
- #define GMM_MAX_COMPONT 6 //每个GMM最多的高斯模型个数
- #define GMM_LEARN_ALPHA 0.005
- #define GMM_THRESHOD_SUMW 0.7
- #define TRAIN_FRAMES 60 // 对前 TRAIN_FRAMES 帧建模
- class MOG_BGS
- {
- public:
- MOG_BGS(void);
- ~MOG_BGS(void);
- void init(const Mat _image);
- void processFirstFrame(const Mat _image);
- void trainGMM(const Mat _image);
- void getFitNum(const Mat _image);
- void testGMM(const Mat _image);
- Mat getMask(void){ return m_mask;};
- private:
- Mat m_weight[GMM_MAX_COMPONT]; //权值
- Mat m_mean[GMM_MAX_COMPONT]; //均值
- Mat m_sigma[GMM_MAX_COMPONT]; //方差
- Mat m_mask;
- Mat m_fit_num;
- };
MOG_BGS.cpp
- #include "MOG_BGS.h"
- MOG_BGS::MOG_BGS(void)
- {
- }
- MOG_BGS::~MOG_BGS(void)
- {
- }
- // 全部初始化为0
- void MOG_BGS::init(const Mat _image)
- {
- /****initialization the three parameters ****/
- for(int i = 0; i < GMM_MAX_COMPONT; i++)
- {
- m_weight[i] = Mat::zeros(_image.size(), CV_32FC1);
- m_mean[i] = Mat::zeros(_image.size(), CV_8UC1);
- m_sigma[i] = Mat::zeros(_image.size(), CV_32FC1);
- }
- m_mask = Mat::zeros(_image.size(),CV_8UC1);
- m_fit_num = Mat::ones(_image.size(),CV_8UC1);
- }
- //gmm第一帧初始化函数实现
- //捕获到第一帧时对高斯分布进行初始化.主要包括对每个高斯分布的权值、期望和方差赋初值.
- //其中第一个高斯分布的权值为1,期望为第一个像素数据.其余高斯分布权值为0,期望为0.
- //每个高斯分布都被赋予适当的相等的初始方差 15
- void MOG_BGS::processFirstFrame(const