标签:
因为监控发展的需求,目前前景检测的研究还是很多的,也出现了很多新的方法和思路。个人了解的大概概括为以下一些:
帧差、背景减除(GMM、CodeBook、 SOBS、 SACON、 VIBE、 W4、多帧平均……)、光流(稀疏光流、稠密光流)、运动竞争(Motion Competition)、运动模版(运动历史图像)、时间熵……等等。如果加上他们的改进版,那就是很大的一个家族了。
对于上一些方法的一点简单的对比分析可以参考下:
http://www.cnblogs.com/ronny/archive/2012/04/12/2444053.html
至于哪个最好,看使用环境吧,各有千秋,有一些适用的情况更多,有一些在某些情况下表现更好。这些都需要针对自己的使用情况作测试确定的。呵呵。
推荐一个牛逼的库:http://code.google.com/p/bgslibrary/里面包含了各种背景减除的方法,可以让自己少做很多力气活。
还有王先荣博客上存在不少的分析:
http://www.cnblogs.com/xrwang/archive/2010/02/21/ForegroundDetection.html
下面的博客上转载王先荣的上面几篇,然后加上自己分析了两篇:
http://blog.csdn.net/stellar0
本文主要关注其中的一种背景减除方法:GMM。tornadomeet的博客上对ViBe进行了分析,我这里就不再啰嗦了,具体的理论分析可以参考:
http://www.cnblogs.com/tornadomeet/archive/2012/06/02/2531565.html
里面有了GMM的代码,并有了详细的注释。我之前根据这个代码(在这里,非常感谢tornadomeet)改写了一个Mat格式的版本,现在发上来和大家交流,具体如下:(在VS2010+OpenCV2.4.2中测试通过)。(当然了,OpenCV也已经提供了MOG的背景减除方法)
MOG_BGS.h
- #pragma once
- #include <iostream>
- #include "opencv2/opencv.hpp"
-
- using namespace cv;
- using namespace std;
-
- #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)
- {
-
- }
-
- void MOG_BGS::init(const Mat _image)
- {
-
- 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);
- }
-
- void MOG_BGS::processFirstFrame(const Mat _image)
- {
- for(int i = 0; i < GMM_MAX_COMPONT; i++)
- {
- if (i == 0)
- {
- m_weight[i].setTo(1.0);
- _image.copyTo(m_mean[i]);
- m_sigma[i].setTo(15.0);
- }
- else
- {
- m_weight[i].setTo(0.0);
- m_mean[i].setTo(0);
- m_sigma[i].setTo(15.0);
- }
- }
- }
-
- void MOG_BGS::trainGMM(const Mat _image)
- {
- for(int i = 0; i < _image.rows; i++)
- {
- for(int j = 0; j < _image.cols; j++)
- {
- int num_fit = 0;
-
-
- for(int k = 0 ; k < GMM_MAX_COMPONT; k++)
- {
- int delm = abs(_image.at<uchar>(i, j) - m_mean[k].at<uchar>(i, j));
- long dist = delm * delm;
-
- if( dist < 3.0 * m_sigma[k].at<float>(i, j))
- {
-
-
- m_weight[k].at<float>(i, j) += GMM_LEARN_ALPHA * (1 - m_weight[k].at<float>(i, j));
-
-
- m_mean[k].at<uchar>(i, j) += (GMM_LEARN_ALPHA / m_weight[k].at<uchar>(i, j)) * delm;
-
-
- m_sigma[k].at<float>(i, j) += (GMM_LEARN_ALPHA / m_weight[k].at<float>(i, j)) * (dist - m_sigma[k].at<float>(i, j));
- }
- else
- {
-
- m_weight[k].at<float>(i, j) += GMM_LEARN_ALPHA * (0 - m_weight[k].at<float>(i, j));
- num_fit++;
- }
- }
-
-
-
-
-
- for(int kk = 0; kk < GMM_MAX_COMPONT; kk++)
- {
- for(int rr=kk; rr< GMM_MAX_COMPONT; rr++)
- {
- if(m_weight[rr].at<float>(i, j)/m_sigma[rr].at<float>(i, j) > m_weight[kk].at<float>(i, j)/m_sigma[kk].at<float>(i, j))
- {
-
- float temp_weight = m_weight[rr].at<float>(i, j);
- m_weight[rr].at<float>(i, j) = m_weight[kk].at<float>(i, j);
- m_weight[kk].at<float>(i, j) = temp_weight;
-
-
- uchar temp_mean = m_mean[rr].at<uchar>(i, j);
- m_mean[rr].at<uchar>(i, j) = m_mean[kk].at<uchar>(i, j);
- m_mean[kk].at<uchar>(i, j) = temp_mean;
-
-
- float temp_sigma = m_sigma[rr].at<float>(i, j);
- m_sigma[rr].at<float>(i, j) = m_sigma[kk].at<float>(i, j);
- m_sigma[kk].at<float>(i, j) = temp_sigma;
- }
- }
- }
-
-
-
-
- if(num_fit == GMM_MAX_COMPONT && 0 == m_weight[GMM_MAX_COMPONT - 1].at<float>(i, j))
- {
-
-
- for(int k = 0 ; k < GMM_MAX_COMPONT; k++)
- {
- if(0 == m_weight[k].at<float>(i, j))
- {
- m_weight[k].at<float>(i, j) = GMM_LEARN_ALPHA;
- m_mean[k].at<uchar>(i, j) = _image.at<uchar>(i, j);
- m_sigma[k].at<float>(i, j) = 15.0;
-
-
- for(int q = 0; q < GMM_MAX_COMPONT && q != k; q++)
- {
-
-
- m_weight[q].at<float>(i, j) *= (1 - GMM_LEARN_ALPHA);
- }
- break;
- }
- }
- }
- else if(num_fit == GMM_MAX_COMPONT && m_weight[GMM_MAX_COMPONT -1].at<float>(i, j) != 0)
- {
-
- m_mean[GMM_MAX_COMPONT-1].at<uchar>(i, j) = _image.at<uchar>(i, j);
- m_sigma[GMM_MAX_COMPONT-1].at<float>(i, j) = 15.0;
- }
-
- }
- }
- }
-
-
-
-
- void MOG_BGS::getFitNum(const Mat _image)
- {
- for(int i = 0; i < _image.rows; i++)
- {
- for(int j = 0; j < _image.cols; j++)
- {
- float sum_w = 0.0;
- for(uchar k = 0; k < GMM_MAX_COMPONT; k++)
- {
- sum_w += m_weight[k].at<float>(i, j);
- if(sum_w >= GMM_THRESHOD_SUMW)
- {
- m_fit_num.at<uchar>(i, j) = k + 1;
- break;
- }
- }
- }
- }
- }
-
-
- void MOG_BGS::testGMM(const Mat _image)
- {
- for(int i = 0; i < _image.rows; i++)
- {
- for(int j = 0; j < _image.cols; j++)
- {
- int k = 0;
- for( ; k < m_fit_num.at<uchar>(i, j); k++)
- {
- if(abs(_image.at<uchar>(i, j) - m_mean[k].at<uchar>(i, j)) < (uchar)( 2.5 * m_sigma[k].at<float>(i, j)))
- {
- m_mask.at<uchar>(i, j) = 0;
- break;
- }
- }
- if(k == m_fit_num.at<uchar>(i, j))
- {
- m_mask.at<uchar>(i, j) = 255;
- }
- }
- }
- }
Main.cpp
-
- #include "opencv2/opencv.hpp"
- #include "MOG_BGS.h"
- #include <iostream>
- #include <cstdio>
-
- using namespace cv;
- using namespace std;
-
- int main(int argc, char* argv[])
- {
- Mat frame, gray, mask;
- VideoCapture capture;
- capture.open("video.avi");
-
- if (!capture.isOpened())
- {
- cout<<"No camera or video input!\n"<<endl;
- return -1;
- }
-
- MOG_BGS Mog_Bgs;
- int count = 0;
-
- while (1)
- {
- count++;
- capture >> frame;
- if (frame.empty())
- break;
- cvtColor(frame, gray, CV_RGB2GRAY);
-
- if (count == 1)
- {
- Mog_Bgs.init(gray);
- Mog_Bgs.processFirstFrame(gray);
- cout<<" Using "<<TRAIN_FRAMES<<" frames to training GMM..."<<endl;
- }
- else if (count < TRAIN_FRAMES)
- {
- Mog_Bgs.trainGMM(gray);
- }
- else if (count == TRAIN_FRAMES)
- {
- Mog_Bgs.getFitNum(gray);
- cout<<" Training GMM complete!"<<endl;
- }
- else
- {
- Mog_Bgs.testGMM(gray);
- mask = Mog_Bgs.getMask();
- morphologyEx(mask, mask, MORPH_OPEN, Mat());
- erode(mask, mask, Mat(7, 7, CV_8UC1), Point(-1, -1));
- dilate(mask, mask, Mat(7, 7, CV_8UC1), Point(-1, -1));
- imshow("mask", mask);
- }
-
- imshow("input", frame);
-
- if ( cvWaitKey(10) == ‘q‘ )
- break;
- }
-
- return 0;
- }
运动检测(前景检测)之(二)混合高斯模型GMM
标签:
原文地址:http://www.cnblogs.com/ywsoftware/p/4434309.html