/modules/cudabgsegm/src/mog2.cpp

https://github.com/batorshih/opencv · C++ · 253 lines · 152 code · 52 blank · 49 comment · 14 complexity · 29b589375b9773361769da3ad0a88251 MD5 · raw file

  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
  14. // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
  15. // Third party copyrights are property of their respective owners.
  16. //
  17. // Redistribution and use in source and binary forms, with or without modification,
  18. // are permitted provided that the following conditions are met:
  19. //
  20. // * Redistribution's of source code must retain the above copyright notice,
  21. // this list of conditions and the following disclaimer.
  22. //
  23. // * Redistribution's in binary form must reproduce the above copyright notice,
  24. // this list of conditions and the following disclaimer in the documentation
  25. // and/or other materials provided with the distribution.
  26. //
  27. // * The name of the copyright holders may not be used to endorse or promote products
  28. // derived from this software without specific prior written permission.
  29. //
  30. // This software is provided by the copyright holders and contributors "as is" and
  31. // any express or implied warranties, including, but not limited to, the implied
  32. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  33. // In no event shall the Intel Corporation or contributors be liable for any direct,
  34. // indirect, incidental, special, exemplary, or consequential damages
  35. // (including, but not limited to, procurement of substitute goods or services;
  36. // loss of use, data, or profits; or business interruption) however caused
  37. // and on any theory of liability, whether in contract, strict liability,
  38. // or tort (including negligence or otherwise) arising in any way out of
  39. // the use of this software, even if advised of the possibility of such damage.
  40. //
  41. //M*/
  42. #include "precomp.hpp"
  43. using namespace cv;
  44. using namespace cv::cuda;
  45. #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
  46. Ptr<cuda::BackgroundSubtractorMOG2> cv::cuda::createBackgroundSubtractorMOG2(int, double, bool) { throw_no_cuda(); return Ptr<cuda::BackgroundSubtractorMOG2>(); }
  47. #else
  48. namespace cv { namespace cuda { namespace device
  49. {
  50. namespace mog2
  51. {
  52. void loadConstants(int nmixtures, float Tb, float TB, float Tg, float varInit, float varMin, float varMax, float tau, unsigned char shadowVal);
  53. void mog2_gpu(PtrStepSzb frame, int cn, PtrStepSzb fgmask, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzf variance, PtrStepSzb mean, float alphaT, float prune, bool detectShadows, cudaStream_t stream);
  54. void getBackgroundImage2_gpu(int cn, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream);
  55. }
  56. }}}
  57. namespace
  58. {
  59. // default parameters of gaussian background detection algorithm
  60. const int defaultHistory = 500; // Learning rate; alpha = 1/defaultHistory2
  61. const float defaultVarThreshold = 4.0f * 4.0f;
  62. const int defaultNMixtures = 5; // maximal number of Gaussians in mixture
  63. const float defaultBackgroundRatio = 0.9f; // threshold sum of weights for background test
  64. const float defaultVarThresholdGen = 3.0f * 3.0f;
  65. const float defaultVarInit = 15.0f; // initial variance for new components
  66. const float defaultVarMax = 5.0f * defaultVarInit;
  67. const float defaultVarMin = 4.0f;
  68. // additional parameters
  69. const float defaultCT = 0.05f; // complexity reduction prior constant 0 - no reduction of number of components
  70. const unsigned char defaultShadowValue = 127; // value to use in the segmentation mask for shadows, set 0 not to do shadow detection
  71. const float defaultShadowThreshold = 0.5f; // Tau - shadow threshold, see the paper for explanation
  72. class MOG2Impl : public cuda::BackgroundSubtractorMOG2
  73. {
  74. public:
  75. MOG2Impl(int history, double varThreshold, bool detectShadows);
  76. void apply(InputArray image, OutputArray fgmask, double learningRate=-1);
  77. void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream);
  78. void getBackgroundImage(OutputArray backgroundImage) const;
  79. void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const;
  80. int getHistory() const { return history_; }
  81. void setHistory(int history) { history_ = history; }
  82. int getNMixtures() const { return nmixtures_; }
  83. void setNMixtures(int nmixtures) { nmixtures_ = nmixtures; }
  84. double getBackgroundRatio() const { return backgroundRatio_; }
  85. void setBackgroundRatio(double ratio) { backgroundRatio_ = (float) ratio; }
  86. double getVarThreshold() const { return varThreshold_; }
  87. void setVarThreshold(double varThreshold) { varThreshold_ = (float) varThreshold; }
  88. double getVarThresholdGen() const { return varThresholdGen_; }
  89. void setVarThresholdGen(double varThresholdGen) { varThresholdGen_ = (float) varThresholdGen; }
  90. double getVarInit() const { return varInit_; }
  91. void setVarInit(double varInit) { varInit_ = (float) varInit; }
  92. double getVarMin() const { return varMin_; }
  93. void setVarMin(double varMin) { varMin_ = (float) varMin; }
  94. double getVarMax() const { return varMax_; }
  95. void setVarMax(double varMax) { varMax_ = (float) varMax; }
  96. double getComplexityReductionThreshold() const { return ct_; }
  97. void setComplexityReductionThreshold(double ct) { ct_ = (float) ct; }
  98. bool getDetectShadows() const { return detectShadows_; }
  99. void setDetectShadows(bool detectShadows) { detectShadows_ = detectShadows; }
  100. int getShadowValue() const { return shadowValue_; }
  101. void setShadowValue(int value) { shadowValue_ = (uchar) value; }
  102. double getShadowThreshold() const { return shadowThreshold_; }
  103. void setShadowThreshold(double threshold) { shadowThreshold_ = (float) threshold; }
  104. private:
  105. void initialize(Size frameSize, int frameType);
  106. int history_;
  107. int nmixtures_;
  108. float backgroundRatio_;
  109. float varThreshold_;
  110. float varThresholdGen_;
  111. float varInit_;
  112. float varMin_;
  113. float varMax_;
  114. float ct_;
  115. bool detectShadows_;
  116. uchar shadowValue_;
  117. float shadowThreshold_;
  118. Size frameSize_;
  119. int frameType_;
  120. int nframes_;
  121. GpuMat weight_;
  122. GpuMat variance_;
  123. GpuMat mean_;
  124. //keep track of number of modes per pixel
  125. GpuMat bgmodelUsedModes_;
  126. };
  127. MOG2Impl::MOG2Impl(int history, double varThreshold, bool detectShadows) :
  128. frameSize_(0, 0), frameType_(0), nframes_(0)
  129. {
  130. history_ = history > 0 ? history : defaultHistory;
  131. varThreshold_ = varThreshold > 0 ? (float) varThreshold : defaultVarThreshold;
  132. detectShadows_ = detectShadows;
  133. nmixtures_ = defaultNMixtures;
  134. backgroundRatio_ = defaultBackgroundRatio;
  135. varInit_ = defaultVarInit;
  136. varMax_ = defaultVarMax;
  137. varMin_ = defaultVarMin;
  138. varThresholdGen_ = defaultVarThresholdGen;
  139. ct_ = defaultCT;
  140. shadowValue_ = defaultShadowValue;
  141. shadowThreshold_ = defaultShadowThreshold;
  142. }
  143. void MOG2Impl::apply(InputArray image, OutputArray fgmask, double learningRate)
  144. {
  145. apply(image, fgmask, learningRate, Stream::Null());
  146. }
  147. void MOG2Impl::apply(InputArray _frame, OutputArray _fgmask, double learningRate, Stream& stream)
  148. {
  149. using namespace cv::cuda::device::mog2;
  150. GpuMat frame = _frame.getGpuMat();
  151. int ch = frame.channels();
  152. int work_ch = ch;
  153. if (nframes_ == 0 || learningRate >= 1.0 || frame.size() != frameSize_ || work_ch != mean_.channels())
  154. initialize(frame.size(), frame.type());
  155. _fgmask.create(frameSize_, CV_8UC1);
  156. GpuMat fgmask = _fgmask.getGpuMat();
  157. fgmask.setTo(Scalar::all(0), stream);
  158. ++nframes_;
  159. learningRate = learningRate >= 0 && nframes_ > 1 ? learningRate : 1.0 / std::min(2 * nframes_, history_);
  160. CV_Assert( learningRate >= 0 );
  161. mog2_gpu(frame, frame.channels(), fgmask, bgmodelUsedModes_, weight_, variance_, mean_,
  162. (float) learningRate, static_cast<float>(-learningRate * ct_), detectShadows_, StreamAccessor::getStream(stream));
  163. }
  164. void MOG2Impl::getBackgroundImage(OutputArray backgroundImage) const
  165. {
  166. getBackgroundImage(backgroundImage, Stream::Null());
  167. }
  168. void MOG2Impl::getBackgroundImage(OutputArray _backgroundImage, Stream& stream) const
  169. {
  170. using namespace cv::cuda::device::mog2;
  171. _backgroundImage.create(frameSize_, frameType_);
  172. GpuMat backgroundImage = _backgroundImage.getGpuMat();
  173. getBackgroundImage2_gpu(backgroundImage.channels(), bgmodelUsedModes_, weight_, mean_, backgroundImage, StreamAccessor::getStream(stream));
  174. }
  175. void MOG2Impl::initialize(cv::Size frameSize, int frameType)
  176. {
  177. using namespace cv::cuda::device::mog2;
  178. CV_Assert( frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_8UC4 );
  179. frameSize_ = frameSize;
  180. frameType_ = frameType;
  181. nframes_ = 0;
  182. int ch = CV_MAT_CN(frameType);
  183. int work_ch = ch;
  184. // for each gaussian mixture of each pixel bg model we store ...
  185. // the mixture weight (w),
  186. // the mean (nchannels values) and
  187. // the covariance
  188. weight_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1);
  189. variance_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1);
  190. mean_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch));
  191. //make the array for keeping track of the used modes per pixel - all zeros at start
  192. bgmodelUsedModes_.create(frameSize_, CV_8UC1);
  193. bgmodelUsedModes_.setTo(Scalar::all(0));
  194. loadConstants(nmixtures_, varThreshold_, backgroundRatio_, varThresholdGen_, varInit_, varMin_, varMax_, shadowThreshold_, shadowValue_);
  195. }
  196. }
  197. Ptr<cuda::BackgroundSubtractorMOG2> cv::cuda::createBackgroundSubtractorMOG2(int history, double varThreshold, bool detectShadows)
  198. {
  199. return makePtr<MOG2Impl>(history, varThreshold, detectShadows);
  200. }
  201. #endif