In order to learn, on the one hand, according to the requirements of the teacher and the project to contact the perspective of the relevant knowledge, there are many specific methods, frame difference, background subtraction (GMM, CodeBook, sobs, Sacon, VIBE, W4, multi-frame average ...) ), optical flow (sparse optical flow, dense optical flow), motion competition (Motion Competition), motion template (Motion history image), Time entropy ... Wait a minute.
More specific information can refer to the link, the author made a very good summary. Click on the Open link http://blog.csdn.net/zouxy09/article/details/9622285
I just for the source code provided by the author, plus my understanding the most code caught to do the relevant comments, to facilitate their own code reading and communication with you, if the wrong place, rare everyone put forward, common progress
ViBe.h (header file, generally make a declaration function, class use, do not make a specific definition)
#pragma once
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace CV;
using namespace std;
#define The number of samples per pixel
#define Min_matches 2 //#min指数
#define RADIUS //sqthere radius (num_samples)
#define Subsample_factor 16//Sub sampling probability, the probability
class Vibe_bgs
{public
:
vibe_bgs (void) of background update is decided; Constructor
~vibe_bgs (void); destructor, do the necessary cleanup work on the memory that is opened
void init (const Mat _image); Initialize
void processfirstframe (const Mat _image)//////////////(const MAT _image) by using the first frame model
void testandupdate; Judge the foreground and background, and background with the new
Mat getmask (void) {return m_mask;}; Get the foreground
private:
Mat m_samples[num_samples]; Each frame image has a sample set of each pixel
Mat m_foregroundmatchcount; Statistical pixels are judged to be the number of prospects, easy to m_mask with the new
Mat; A frame image after the foreground is extracted
};
ViBe.cpp (the specific definition of the statement mentioned above)
#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's neighbor point, 9 c_yoff[9 int] = {1, 0, 1,-1, 1,-1, 0, 1, 0}; The neighbor point of y vibe_bgs::vibe_bgs (void) {} vibe_bgs::~vibe_bgs (void) {}/**************** Assign Spac E and init ***************************/void Vibe_bgs::init (const Mat _image)//member function initialization {for (int i = 0; i < Num_samples; i++)//It can be understood that for a frame image, 20 frames of the sample set {M_samples[i] = Mat::zeros (_image.size (), CV_8UC1) are established; Initialized to 8-bit unsigned 0 for each pixel of each frame sample set, Single channel} M_mask = Mat::zeros (_image.size (), CV_8UC1); Initialize M_foregroundmatchcount = Mat::zeros (_image.size (), CV_8UC1); Each pixel is judged as the number of prospects, initialized}/**************** init model from the first frame ********************/void Vibe_bgs::p rocessfi
Rstframe (const Mat _image) {RNG RNG;//random number generator 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_sampl ES;
k++) {//Random pick up num_samples pixel into neighbourhood to construct the model int random = rng.uniform (0, 9); Randomly generated 0-9 random numbers, mainly used to locate central pixels in the neighborhood pixels row = i + c_yoff[random];
The neighborhood pixels of the locating center pixel if (row < 0)//The following four sentences are mainly used to judge whether the boundary row = 0 is exceeded;
if (row >= _image.rows) row = _image.rows-1;
Col = j + c_xoff[random];
if (Col < 0)//The following four sentences are mainly used to judge whether the boundary col = 0 is exceeded;
if (Col >= _image.cols) col = _image.cols-1; M_samples[k].at<uchar> (i, j) = _image.at<uchar> (row, col); Copy the corresponding pixel values to the sample set}}}/**************** Test a new frame and update model ********************/void Vibe_bgs::testandupdate (const Mat _image) {RNG 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)//pixels-by-pixel, when the number of matches is greater than the threshold min_matches, or the entire sample set traversal complete jumps out { DIST = ABS (M_samples[count].at<uchar> (i, J)-_image.at<uchar> (i, j));
The current frame pixel value is not the same as the value in the sample set, and the absolute value if (Dist < RADIUS)///When the absolute is less than the threshold is, representing the similarity matches++ between the current frame pixel and the sample value; count++;
Sample the next element of this value as a comparison} if (matches >= min_matches)///Match number greater than the threshold min_matches number, represented as background {//It is a background pixel m_foregroundmatchcount.at<uchar> (i, j) = 0;
The number of values detected as a foreground is 0//Set background pixel to 0 M_mask.at<uchar> (i, j) = 0; The pixel value is also 0//If a pixel is a background point, then it has 1/defaultsubsamplingfactor probability to update its model sample value int random = Rng.uniform (0, Subsample_factor); To 1/defaultsubsamplingfactor probability with the new background if (random = = 0) {random =
Rng.uniform (0, Num_samples);
M_samples[random].at<uchar> (i, j) = _image.at<uchar> (i, j); //There is also a 1/defaultsubsamplingfactor probability to update the model sample value of its neighbor point random = rng.uniform (0, SU
Bsample_factor);
if (random = = 0) {int row, col;
Random = Rng.uniform (0, 9);
row = i + c_yoff[random];
if (Row < 0)//The following four sentences are mainly used to determine whether the boundary row = 0 is exceeded;
if (row >= _image.rows) row = _image.rows-1; Random = Rng.uniform (0, 9);
Col = j + c_xoff[random];
if (Col < 0)//The following four sentences are mainly used to judge whether the boundary col = 0 is exceeded;
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); If the else//match number is less than the number of threshold min_matches, it is represented as foreground {//It is a Foregroun
D Pixel m_foregroundmatchcount.at<uchar> (i, j) + +;
Set background pixel to 255 m_mask.at<uchar> (i, j) = 255;
If a pixel is detected continuously n times as the foreground, a stationary region is considered to be a motion and updated to the background point if (m_foregroundmatchcount.at<uchar> (i, J) > 50).
{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); }
}
}
}
}
}
Main.cpp (You know ...). )
#include <opencv2/opencv.hpp> #include "ViBe.h" #include <iostream> #include <cstdio> #include <
Stdlib.h> using namespace CV;
using namespace Std;
int main (int argc, char* argv[]) {Mat frame, gray, mask;
Videocapture capture;
Capture.open ("E:\\overpass\\11.avi");
if (!capture.isopened ()) {cout<< "No camera or video input!\n" <<endl;
return-1; } VIBE_BGS Vibe_bgs; Defines a background differential object int count = 0;
Frame counter, statistics for frame while (1) {count++;
Capture >> frame;
if (Frame.empty ()) break; Cvtcolor (frame, Gray, Cv_rgb2gray);
Convert to Grayscale image if (count = 1)//If first frame {vibe_bgs.init (gray); Vibe_bgs.processfirstframe (gray); Background model initialization 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) = = ' Q ') break;
System ("pause");
return 0; }