*/
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.
int maxFeatures;
//! Set between 0.0 and 1.0, determines how quickly features are "forgotten" from histograms.
int quantizationLevels;
//! Prior probability that any given pixel is a background pixel. A sensitivity parameter.
double backgroundPrior;
- //! value above which pixel is determined to be FG.
+ //! Value above which pixel is determined to be FG.
double decisionThreshold;
- //! smoothing radius, in pixels, for cleaning up FG image.
+ //! Smoothing radius, in pixels, for cleaning up FG image.
int smoothingRadius;
+ //! Perform background model update
+ bool updateBackgroundModel;
private:
double maxVal_;
backgroundPrior = 0.8;
decisionThreshold = 0.8;
smoothingRadius = 7;
+ updateBackgroundModel = true;
}
cv::BackgroundSubtractorGMG::~BackgroundSubtractorGMG()
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,
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),
maxFeatures_(maxFeatures), learningRate_(learningRate), numInitializationFrames_(numInitializationFrames),
quantizationLevels_(quantizationLevels), backgroundPrior_(backgroundPrior), decisionThreshold_(decisionThreshold),
- maxVal_(maxVal), minVal_(minVal), frameNum_(frameNum)
+ maxVal_(maxVal), minVal_(minVal), frameNum_(frameNum), updateBackgroundModel_(updateBackgroundModel)
{
}
int quantizationLevels_;
double backgroundPrior_;
double decisionThreshold_;
+ bool updateBackgroundModel_;
double maxVal_;
double minVal_;
// update histogram.
- for (int i = 0; i < nfeatures; ++i)
- weights[i] *= 1.0f - learningRate_;
+ if (updateBackgroundModel_)
+ {
+ for (int i = 0; i < nfeatures; ++i)
+ weights[i] *= 1.0f - learningRate_;
- bool inserted = insertFeature(newFeatureColor, learningRate_, colors, weights, nfeatures, maxFeatures_);
+ bool inserted = insertFeature(newFeatureColor, learningRate_, colors, weights, nfeatures, maxFeatures_);
- if (inserted)
- {
- normalizeHistogram(weights, nfeatures);
- nfeatures_row[x] = nfeatures;
+ if (inserted)
+ {
+ normalizeHistogram(weights, nfeatures);
+ nfeatures_row[x] = nfeatures;
+ }
}
}
- else
+ else if (updateBackgroundModel_)
{
// training-mode update
GMG_LoopBody body(frame, fgmask, nfeatures_, colors_, weights_,
maxFeatures, learningRate, numInitializationFrames, quantizationLevels, backgroundPrior, decisionThreshold,
- maxVal_, minVal_, frameNum_);
+ maxVal_, minVal_, frameNum_, updateBackgroundModel);
cv::parallel_for_(cv::Range(0, frame.rows), body);
- cv::medianBlur(fgmask, buf_, smoothingRadius);
- cv::swap(fgmask, buf_);
+ if (smoothingRadius > 0)
+ {
+ cv::medianBlur(fgmask, buf_, smoothingRadius);
+ cv::swap(fgmask, buf_);
+ }
// keep track of how many frames we have processed
++frameNum_;
}
+
+void cv::BackgroundSubtractorGMG::release()
+{
+ frameSize_ = cv::Size();
+
+ nfeatures_.release();
+ colors_.release();
+ weights_.release();
+ buf_.release();
+}
obj.info()->addParam(obj, "smoothingRadius", obj.smoothingRadius,false,0,0,
"Radius of smoothing kernel to filter noise from FG mask image.");
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)
{