Motion detection (foreground detection) (1) vibe
Zouxy09@qq.com
Http://blog.csdn.net/zouxy09
Due to the needs of the development of monitoring, there are still a lot of research on foreground detection, and there are also a lot of new methods and ideas. My personal knowledge is summarized as follows:
Frame Difference and background subtraction (GMM, codebook, sobs, sacon, vibe, W4, multi-frame average ......) , Optical flow (sparse optical flow, dense optical flow), motion competition (motion competition), motion templates (motion history images), time entropy ...... And so on. If their ultimate version is added, it is a huge family.
For a simple comparative analysis of some of the above methods, refer:
Http://www.cnblogs.com/ronny/archive/2012/04/12/2444053.html
For which one is the best, let's look at the use environment. There are some applicable situations, and some have better performance in some cases. These must be tested and determined based on your own usage. Haha.
We recommend a awesome Library: Awesome.
There are also many analyses on Wang Xianrong's blog:
Http://www.cnblogs.com/xrwang/archive/2010/02/21/ForegroundDetection.html
Wang Xianrong's previous articles are reproduced on the blog below, and then added two articles for analysis:
Http://blog.csdn.net/stellar0
This article focuses on one of the Background Subtraction Methods: vibe. I have analyzed vibe on stellar0's blog. I will not be so embarrassed here. The specific theory can be referred:
Http://www2.ulg.ac.be/telecom/research/vibe/
Http://blog.csdn.net/stellar0/article/details/8777283
Http://blog.csdn.net/yongshengsilingsa/article/details/6659859
Http://www2.ulg.ac.be/telecom/research/vibe/download.html
Http://www.cvchina.info/2011/12/25/vibe/
Vibe: A Universal Background Subtraction Algorithm for Video Sequences
Vibe: a powerful technique for background detection and subtraction in Video Sequences
Vibe is a pixel-level video background modeling or foreground detection algorithm. It is superior to several well-known algorithms and consumes less hardware memory. I used to rewrite the stellar0 code into a mat format based on the stellar0 code (here, I am very grateful to stellar0). Now I will discuss it with you, as shown below: (passed the test in vs2010 + opencv2.4.2)
Vibe. h
# Pragma once # include <iostream> # include "opencv2/opencv. HPP "using namespace CV; using namespace STD; # define num_samples 20 // number of samples per pixel # define min_matches 2 // # min index # define radius 20 // sqthere radius # define subsample_factor 16 // subsampling probability class vibe_bgs {public: vibe_bgs (void );~ Vibe_bgs (void); void Init (const mat _ image); // initialize void processfirstframe (const mat _ image); void testandupdate (const mat _ image ); // update mat getmask (void) {return m_mask;}; private: mat m_samples [num_samples]; MAT m_foregroundmatchcount; MAT m_mask ;};
Vibe. cpp
# Include <opencv2/opencv. HPP> # include <iostream> # include "vibe. H "using namespace STD; using namespace CV; int c_xoff [9] = {-1, 0, 1,-1, 1,-1, 0, 1, 0 }; // X neighbor point int c_yoff [9] = {-1, 0, 1,-1, 1,-1, 0, 1, 0 }; // y neighbor: vibe_bgs (void) {} vibe_bgs ::~ Vibe_bgs (void) {}/**************** assign space and init ***************** * ********/void vibe_bgs:: Init (const mat _ image) {for (INT I = 0; I <num_samples; I ++) {m_samples [I] = mat: zeros (_ image. size (), cv_8uc1);} m_mask = mat: zeros (_ image. size (), cv_8uc1); m_foregroundmatchcount = mat: zeros (_ image. size (), cv_8uc1 );} /*************** init model from first frame ****************** **/void vibe_bgs:: processfirstframe (const mat _ image) {RNG; int row, Col; For (INT I = 0; I <_ image. rows; I ++) {for (Int J = 0; j <_ image. cols; j ++) {for (int K = 0; k <num_samples; k ++) {// Random pick up num_samples pixel in neighborhood to construct the model int random = RNG. uniform (0, 9); ROW = I + c_yoff [random]; If (row <0) Row = 0; If (row> = _ image. rows) Row = _ image. rows-1; Col = J + c_xoff [random]; If (COL <0) COL = 0; If (COL> = _ image. cols) COL = _ image. cols-1; m_samples [K]. at <uchar> (I, j) = _ image. at <uchar> (row, col );}}}} /*************** test a new frame and update model **************** * ***/void vibe_bgs:: testandupdate (const mat _ image) {RNG; For (INT I = 0; I <_ image. rows; I ++) {for (Int J = 0; j <_ image. cols; j ++) {int matches (0), count (0); float Dist; while (matches <min_matches & count <num_samples) {Dist = ABS (m_samples [count]. at <uchar> (I, j)-_ image. at <uchar> (I, j); If (Dist <radius) matches ++; count ++;} If (matches> = min_matches) {// It is a background pixelm_foregroundmatchcount.at <uchar> (I, j) = 0; // Set background pixel to 0m_mask.at <uchar> (I, j) = 0; // If a pixel is a background point, it has the probability of 1/defaultsubsamplingfactor to update its model sample value int random = RNG. uniform (0, subsample_factor); If (random = 0) {random = RNG. uniform (0, num_samples); m_samples [random]. at <uchar> (I, j)-_ image. at <uchar> (I, j);} // At the same time, there is also a probability of 1/defasubsubsamplingfactor to update the model sample value of its neighbor point random = RNG. uniform (0, subsample_factor); If (random = 0) {int row, Col; random = RNG. uniform (0, 9); ROW = I + c_yoff [random]; If (row <0) Row = 0; If (row> = _ image. rows) Row = _ image. rows-1; random = RNG. uniform (0, 9); Col = J + c_xoff [random]; If (COL <0) COL = 0; If (COL> = _ image. cols) COL = _ image. cols-1; random = RNG. uniform (0, num_samples); m_samples [random]. at <uchar> (row, col) = _ image. at <uchar> (I, j) ;}} else {// It is a foreground pixelm_foregroundmatchcount.at <uchar> (I, j) ++; // Set background pixel to 255m_mask.at <uchar> (I, j) = 255; // If a pixel is detected as foreground n times in a row, A static area is regarded as a motion and updated to the background point if (m_foregroundmatchcount.at <uchar> (I, j)> 50) {int random = RNG. uniform (0, num_samples); If (random = 0) {random = RNG. uniform (0, num_samples); m_samples [random]. at <uchar> (I, j) = _ image. at <uchar> (I, j );}}}}}}
Main. cpp
// This is based on // "VIBE: A POWERFUL RANDOM TECHNIQUE TO ESTIMATE THE BACKGROUND IN VIDEO SEQUENCES"// by Olivier Barnich and Marc Van Droogenbroeck// Author : zouxy// Date : 2013-4-13// HomePage : http://blog.csdn.net/zouxy09// Email : zouxy09@qq.com#include "opencv2/opencv.hpp"#include "ViBe.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;}ViBe_BGS Vibe_Bgs;int count = 0;while (1){count++;capture >> frame;if (frame.empty())break;cvtColor(frame, gray, CV_RGB2GRAY);if (count == 1){Vibe_Bgs.init(gray);Vibe_Bgs.processFirstFrame(gray);cout<<" Training GMM complete!"<<endl;}else{Vibe_Bgs.testAndUpdate(gray);mask = Vibe_Bgs.getMask();morphologyEx(mask, mask, MORPH_OPEN, Mat());imshow("mask", mask);}imshow("input", frame);if ( cvWaitKey(10) == 'q' )break;}return 0;}