added updateBackgroundModel parameter and release method

This commit is contained in:
Vladislav Vinogradov 2012-08-09 14:37:08 +04:00
parent 55f8310cac
commit bfd9e6102a
3 changed files with 44 additions and 17 deletions

View File

@ -221,6 +221,11 @@ public:
*/ */
virtual void operator()(InputArray image, OutputArray fgmask, double learningRate=-1.0); virtual void operator()(InputArray image, OutputArray fgmask, double learningRate=-1.0);
/**
* Releases all inner buffers.
*/
void release();
//! Total number of distinct colors to maintain in histogram. //! Total number of distinct colors to maintain in histogram.
int maxFeatures; int maxFeatures;
//! Set between 0.0 and 1.0, determines how quickly features are "forgotten" from histograms. //! Set between 0.0 and 1.0, determines how quickly features are "forgotten" from histograms.
@ -231,10 +236,12 @@ public:
int quantizationLevels; int quantizationLevels;
//! Prior probability that any given pixel is a background pixel. A sensitivity parameter. //! Prior probability that any given pixel is a background pixel. A sensitivity parameter.
double backgroundPrior; double backgroundPrior;
//! value above which pixel is determined to be FG. //! Value above which pixel is determined to be FG.
double decisionThreshold; double decisionThreshold;
//! smoothing radius, in pixels, for cleaning up FG image. //! Smoothing radius, in pixels, for cleaning up FG image.
int smoothingRadius; int smoothingRadius;
//! Perform background model update
bool updateBackgroundModel;
private: private:
double maxVal_; double maxVal_;

View File

@ -60,6 +60,7 @@ cv::BackgroundSubtractorGMG::BackgroundSubtractorGMG()
backgroundPrior = 0.8; backgroundPrior = 0.8;
decisionThreshold = 0.8; decisionThreshold = 0.8;
smoothingRadius = 7; smoothingRadius = 7;
updateBackgroundModel = true;
} }
cv::BackgroundSubtractorGMG::~BackgroundSubtractorGMG() cv::BackgroundSubtractorGMG::~BackgroundSubtractorGMG()
@ -199,11 +200,11 @@ namespace
public: public:
GMG_LoopBody(const cv::Mat& frame, const cv::Mat& fgmask, const cv::Mat_<int>& nfeatures, const cv::Mat_<int>& colors, const cv::Mat_<float>& weights, GMG_LoopBody(const cv::Mat& frame, const cv::Mat& fgmask, const cv::Mat_<int>& nfeatures, const cv::Mat_<int>& colors, const cv::Mat_<float>& weights,
int maxFeatures, double learningRate, int numInitializationFrames, int quantizationLevels, double backgroundPrior, double decisionThreshold, int maxFeatures, double learningRate, int numInitializationFrames, int quantizationLevels, double backgroundPrior, double decisionThreshold,
double maxVal, double minVal, int frameNum) : double maxVal, double minVal, int frameNum, bool updateBackgroundModel) :
frame_(frame), fgmask_(fgmask), nfeatures_(nfeatures), colors_(colors), weights_(weights), frame_(frame), fgmask_(fgmask), nfeatures_(nfeatures), colors_(colors), weights_(weights),
maxFeatures_(maxFeatures), learningRate_(learningRate), numInitializationFrames_(numInitializationFrames), maxFeatures_(maxFeatures), learningRate_(learningRate), numInitializationFrames_(numInitializationFrames),
quantizationLevels_(quantizationLevels), backgroundPrior_(backgroundPrior), decisionThreshold_(decisionThreshold), quantizationLevels_(quantizationLevels), backgroundPrior_(backgroundPrior), decisionThreshold_(decisionThreshold),
maxVal_(maxVal), minVal_(minVal), frameNum_(frameNum) maxVal_(maxVal), minVal_(minVal), frameNum_(frameNum), updateBackgroundModel_(updateBackgroundModel)
{ {
} }
@ -224,6 +225,7 @@ namespace
int quantizationLevels_; int quantizationLevels_;
double backgroundPrior_; double backgroundPrior_;
double decisionThreshold_; double decisionThreshold_;
bool updateBackgroundModel_;
double maxVal_; double maxVal_;
double minVal_; double minVal_;
@ -275,18 +277,21 @@ namespace
// update histogram. // update histogram.
for (int i = 0; i < nfeatures; ++i) if (updateBackgroundModel_)
weights[i] *= 1.0f - learningRate_;
bool inserted = insertFeature(newFeatureColor, learningRate_, colors, weights, nfeatures, maxFeatures_);
if (inserted)
{ {
normalizeHistogram(weights, nfeatures); for (int i = 0; i < nfeatures; ++i)
nfeatures_row[x] = nfeatures; weights[i] *= 1.0f - learningRate_;
bool inserted = insertFeature(newFeatureColor, learningRate_, colors, weights, nfeatures, maxFeatures_);
if (inserted)
{
normalizeHistogram(weights, nfeatures);
nfeatures_row[x] = nfeatures;
}
} }
} }
else else if (updateBackgroundModel_)
{ {
// training-mode update // training-mode update
@ -323,12 +328,25 @@ void cv::BackgroundSubtractorGMG::operator ()(InputArray _frame, OutputArray _fg
GMG_LoopBody body(frame, fgmask, nfeatures_, colors_, weights_, GMG_LoopBody body(frame, fgmask, nfeatures_, colors_, weights_,
maxFeatures, learningRate, numInitializationFrames, quantizationLevels, backgroundPrior, decisionThreshold, maxFeatures, learningRate, numInitializationFrames, quantizationLevels, backgroundPrior, decisionThreshold,
maxVal_, minVal_, frameNum_); maxVal_, minVal_, frameNum_, updateBackgroundModel);
cv::parallel_for_(cv::Range(0, frame.rows), body); cv::parallel_for_(cv::Range(0, frame.rows), body);
cv::medianBlur(fgmask, buf_, smoothingRadius); if (smoothingRadius > 0)
cv::swap(fgmask, buf_); {
cv::medianBlur(fgmask, buf_, smoothingRadius);
cv::swap(fgmask, buf_);
}
// keep track of how many frames we have processed // keep track of how many frames we have processed
++frameNum_; ++frameNum_;
} }
void cv::BackgroundSubtractorGMG::release()
{
frameSize_ = cv::Size();
nfeatures_.release();
colors_.release();
weights_.release();
buf_.release();
}

View File

@ -78,7 +78,9 @@ CV_INIT_ALGORITHM(BackgroundSubtractorGMG, "BackgroundSubtractor.GMG",
obj.info()->addParam(obj, "smoothingRadius", obj.smoothingRadius,false,0,0, obj.info()->addParam(obj, "smoothingRadius", obj.smoothingRadius,false,0,0,
"Radius of smoothing kernel to filter noise from FG mask image."); "Radius of smoothing kernel to filter noise from FG mask image.");
obj.info()->addParam(obj, "decisionThreshold", obj.decisionThreshold,false,0,0, obj.info()->addParam(obj, "decisionThreshold", obj.decisionThreshold,false,0,0,
"Threshold for FG decision rule. Pixel is FG if posterior probability exceeds threshold.")); "Threshold for FG decision rule. Pixel is FG if posterior probability exceeds threshold.");
obj.info()->addParam(obj, "updateBackgroundModel", obj.updateBackgroundModel,false,0,0,
"Perform background model update."));
bool initModule_video(void) bool initModule_video(void)
{ {