Commit b8f0d1a0 authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

refactored MOG2 algorithm

parent a2adab72
......@@ -73,6 +73,27 @@ CV_EXPORTS Ptr<gpu::BackgroundSubtractorMOG>
createBackgroundSubtractorMOG(int history = 200, int nmixtures = 5,
double backgroundRatio = 0.7, double noiseSigma = 0);
////////////////////////////////////////////////////
// MOG2
class CV_EXPORTS BackgroundSubtractorMOG2 : public cv::BackgroundSubtractorMOG2
{
public:
using cv::BackgroundSubtractorMOG2::apply;
using cv::BackgroundSubtractorMOG2::getBackgroundImage;
virtual void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream) = 0;
virtual void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const = 0;
};
CV_EXPORTS Ptr<gpu::BackgroundSubtractorMOG2>
createBackgroundSubtractorMOG2(int history = 500, double varThreshold = 16,
bool detectShadows = true);
......@@ -140,99 +161,6 @@ private:
std::auto_ptr<Impl> impl_;
};
/*!
The class implements the following algorithm:
"Improved adaptive Gausian mixture model for background subtraction"
Z.Zivkovic
International Conference Pattern Recognition, UK, August, 2004.
http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf
*/
class CV_EXPORTS MOG2_GPU
{
public:
//! the default constructor
MOG2_GPU(int nmixtures = -1);
//! re-initiaization method
void initialize(Size frameSize, int frameType);
//! the update operator
void operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate = -1.0f, Stream& stream = Stream::Null());
//! computes a background image which are the mean of all background gaussians
void getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const;
//! releases all inner buffers
void release();
// parameters
// you should call initialize after parameters changes
int history;
//! here it is the maximum allowed number of mixture components.
//! Actual number is determined dynamically per pixel
float varThreshold;
// threshold on the squared Mahalanobis distance to decide if it is well described
// by the background model or not. Related to Cthr from the paper.
// This does not influence the update of the background. A typical value could be 4 sigma
// and that is varThreshold=4*4=16; Corresponds to Tb in the paper.
/////////////////////////
// less important parameters - things you might change but be carefull
////////////////////////
float backgroundRatio;
// corresponds to fTB=1-cf from the paper
// TB - threshold when the component becomes significant enough to be included into
// the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0.
// For alpha=0.001 it means that the mode should exist for approximately 105 frames before
// it is considered foreground
// float noiseSigma;
float varThresholdGen;
//correspondts to Tg - threshold on the squared Mahalan. dist. to decide
//when a sample is close to the existing components. If it is not close
//to any a new component will be generated. I use 3 sigma => Tg=3*3=9.
//Smaller Tg leads to more generated components and higher Tg might make
//lead to small number of components but they can grow too large
float fVarInit;
float fVarMin;
float fVarMax;
//initial variance for the newly generated components.
//It will will influence the speed of adaptation. A good guess should be made.
//A simple way is to estimate the typical standard deviation from the images.
//I used here 10 as a reasonable value
// min and max can be used to further control the variance
float fCT; //CT - complexity reduction prior
//this is related to the number of samples needed to accept that a component
//actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get
//the standard Stauffer&Grimson algorithm (maybe not exact but very similar)
//shadow detection parameters
bool bShadowDetection; //default 1 - do shadow detection
unsigned char nShadowDetection; //do shadow detection - insert this value as the detection result - 127 default value
float fTau;
// Tau - shadow threshold. The shadow is detected if the pixel is darker
//version of the background. Tau is a threshold on how much darker the shadow can be.
//Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow
//See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003.
private:
int nmixtures_;
Size frameSize_;
int frameType_;
int nframes_;
GpuMat weight_;
GpuMat variance_;
GpuMat mean_;
GpuMat bgmodelUsedModes_; //keep track of number of modes per pixel
};
/**
* Background Subtractor module. Takes a series of images and returns a sequence of mask (8UC1)
* images of the same size, where 255 indicates Foreground and 0 represents Background.
......
......@@ -274,13 +274,13 @@ PERF_TEST_P(Video_Cn, MOG2,
if (PERF_RUN_GPU())
{
cv::gpu::MOG2_GPU d_mog2;
d_mog2.bShadowDetection = false;
cv::Ptr<cv::BackgroundSubtractorMOG2> d_mog2 = cv::gpu::createBackgroundSubtractorMOG2();
d_mog2->setDetectShadows(false);
cv::gpu::GpuMat d_frame(frame);
cv::gpu::GpuMat foreground;
d_mog2(d_frame, foreground);
d_mog2->apply(d_frame, foreground);
for (int i = 0; i < 10; ++i)
{
......@@ -300,7 +300,7 @@ PERF_TEST_P(Video_Cn, MOG2,
d_frame.upload(frame);
startTimer(); next();
d_mog2(d_frame, foreground);
d_mog2->apply(d_frame, foreground);
stopTimer();
}
......@@ -308,8 +308,8 @@ PERF_TEST_P(Video_Cn, MOG2,
}
else
{
cv::Ptr<cv::BackgroundSubtractor> mog2 = cv::createBackgroundSubtractorMOG2();
mog2->set("detectShadows", false);
cv::Ptr<cv::BackgroundSubtractorMOG2> mog2 = cv::createBackgroundSubtractorMOG2();
mog2->setDetectShadows(false);
cv::Mat foreground;
......@@ -360,8 +360,9 @@ PERF_TEST_P(Video_Cn, MOG2GetBackgroundImage,
if (PERF_RUN_GPU())
{
cv::Ptr<cv::BackgroundSubtractor> d_mog2 = cv::gpu::createBackgroundSubtractorMOG2();
cv::gpu::GpuMat d_frame;
cv::gpu::MOG2_GPU d_mog2;
cv::gpu::GpuMat d_foreground;
for (int i = 0; i < 10; ++i)
......@@ -381,12 +382,12 @@ PERF_TEST_P(Video_Cn, MOG2GetBackgroundImage,
d_frame.upload(frame);
d_mog2(d_frame, d_foreground);
d_mog2->apply(d_frame, d_foreground);
}
cv::gpu::GpuMat background;
TEST_CYCLE() d_mog2.getBackgroundImage(background);
TEST_CYCLE() d_mog2->getBackgroundImage(background);
GPU_SANITY_CHECK(background, 1);
}
......
This diff is collapsed.
......@@ -267,8 +267,8 @@ GPU_TEST_P(MOG2, Update)
cap >> frame;
ASSERT_FALSE(frame.empty());
cv::gpu::MOG2_GPU mog2;
mog2.bShadowDetection = detectShadow;
cv::Ptr<cv::BackgroundSubtractorMOG2> mog2 = cv::gpu::createBackgroundSubtractorMOG2();
mog2->setDetectShadows(detectShadow);
cv::gpu::GpuMat foreground = createMat(frame.size(), CV_8UC1, useRoi);
cv::Ptr<cv::BackgroundSubtractorMOG2> mog2_gold = cv::createBackgroundSubtractorMOG2();
......@@ -287,7 +287,7 @@ GPU_TEST_P(MOG2, Update)
cv::swap(temp, frame);
}
mog2(loadMat(frame, useRoi), foreground);
mog2->apply(loadMat(frame, useRoi), foreground);
mog2_gold->apply(frame, foreground_gold);
......@@ -312,8 +312,8 @@ GPU_TEST_P(MOG2, getBackgroundImage)
cv::Mat frame;
cv::gpu::MOG2_GPU mog2;
mog2.bShadowDetection = detectShadow;
cv::Ptr<cv::BackgroundSubtractorMOG2> mog2 = cv::gpu::createBackgroundSubtractorMOG2();
mog2->setDetectShadows(detectShadow);
cv::gpu::GpuMat foreground;
cv::Ptr<cv::BackgroundSubtractorMOG2> mog2_gold = cv::createBackgroundSubtractorMOG2();
......@@ -325,13 +325,13 @@ GPU_TEST_P(MOG2, getBackgroundImage)
cap >> frame;
ASSERT_FALSE(frame.empty());
mog2(loadMat(frame, useRoi), foreground);
mog2->apply(loadMat(frame, useRoi), foreground);
mog2_gold->apply(frame, foreground_gold);
}
cv::gpu::GpuMat background = createMat(frame.size(), frame.type(), useRoi);
mog2.getBackgroundImage(background);
mog2->getBackgroundImage(background);
cv::Mat background_gold;
mog2_gold->getBackgroundImage(background_gold);
......
......@@ -76,8 +76,8 @@ int main(int argc, const char** argv)
GpuMat d_frame(frame);
FGDStatModel fgd_stat;
cv::Ptr<cv::BackgroundSubtractorMOG> mog = cv::gpu::createBackgroundSubtractorMOG();
MOG2_GPU mog2;
cv::Ptr<cv::BackgroundSubtractor> mog = cv::gpu::createBackgroundSubtractorMOG();
cv::Ptr<cv::BackgroundSubtractor> mog2 = cv::gpu::createBackgroundSubtractorMOG2();
GMG_GPU gmg;
gmg.numInitializationFrames = 40;
......@@ -100,7 +100,7 @@ int main(int argc, const char** argv)
break;
case MOG2:
mog2(d_frame, d_fgmask);
mog2->apply(d_frame, d_fgmask);
break;
case GMG:
......@@ -140,8 +140,8 @@ int main(int argc, const char** argv)
break;
case MOG2:
mog2(d_frame, d_fgmask);
mog2.getBackgroundImage(d_bgimg);
mog2->apply(d_frame, d_fgmask);
mog2->getBackgroundImage(d_bgimg);
break;
case GMG:
......
......@@ -1399,13 +1399,13 @@ TEST(MOG2)
cap >> frame;
cv::Ptr<cv::BackgroundSubtractor> d_mog2 = cv::gpu::createBackgroundSubtractorMOG2();
cv::gpu::GpuMat d_frame(frame);
cv::gpu::MOG2_GPU d_mog2;
cv::gpu::GpuMat d_foreground;
cv::gpu::GpuMat d_background;
d_mog2(d_frame, d_foreground);
d_mog2.getBackgroundImage(d_background);
d_mog2->apply(d_frame, d_foreground);
d_mog2->getBackgroundImage(d_background);
while (!TestSystem::instance().stop())
{
......@@ -1414,8 +1414,8 @@ TEST(MOG2)
TestSystem::instance().gpuOn();
d_mog2(d_frame, d_foreground);
d_mog2.getBackgroundImage(d_background);
d_mog2->apply(d_frame, d_foreground);
d_mog2->getBackgroundImage(d_background);
TestSystem::instance().gpuOff();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment