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 43 #include "precomp.hpp" 44 45 using namespace cv; 46 using namespace cv::cuda; 47 48 #if !defined HAVE_CUDA || defined(CUDA_DISABLER) 49 50 Ptr<cuda::BackgroundSubtractorMOG2> cv::cuda::createBackgroundSubtractorMOG2(int, double, bool) { throw_no_cuda(); return Ptr<cuda::BackgroundSubtractorMOG2>(); } 51 52 #else 53 54 namespace cv { namespace cuda { namespace device 55 { 56 namespace mog2 57 { 58 void loadConstants(int nmixtures, float Tb, float TB, float Tg, float varInit, float varMin, float varMax, float tau, unsigned char shadowVal); 59 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); 60 void getBackgroundImage2_gpu(int cn, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream); 61 } 62 }}} 63 64 namespace 65 { 66 // default parameters of gaussian background detection algorithm 67 const int defaultHistory = 500; // Learning rate; alpha = 1/defaultHistory2 68 const float defaultVarThreshold = 4.0f * 4.0f; 69 const int defaultNMixtures = 5; // maximal number of Gaussians in mixture 70 const float defaultBackgroundRatio = 0.9f; // threshold sum of weights for background test 71 const float defaultVarThresholdGen = 3.0f * 3.0f; 72 const float defaultVarInit = 15.0f; // initial variance for new components 73 const float defaultVarMax = 5.0f * defaultVarInit; 74 const float defaultVarMin = 4.0f; 75 76 // additional parameters 77 const float defaultCT = 0.05f; // complexity reduction prior constant 0 - no reduction of number of components 78 const unsigned char defaultShadowValue = 127; // value to use in the segmentation mask for shadows, set 0 not to do shadow detection 79 const float defaultShadowThreshold = 0.5f; // Tau - shadow threshold, see the paper for explanation 80 81 class MOG2Impl : public cuda::BackgroundSubtractorMOG2 82 { 83 public: 84 MOG2Impl(int history, double varThreshold, bool detectShadows); 85 86 void apply(InputArray image, OutputArray fgmask, double learningRate=-1); 87 void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream); 88 89 void getBackgroundImage(OutputArray backgroundImage) const; 90 void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const; 91 92 int getHistory() const { return history_; } 93 void setHistory(int history) { history_ = history; } 94 95 int getNMixtures() const { return nmixtures_; } 96 void setNMixtures(int nmixtures) { nmixtures_ = nmixtures; } 97 98 double getBackgroundRatio() const { return backgroundRatio_; } 99 void setBackgroundRatio(double ratio) { backgroundRatio_ = (float) ratio; } 100 101 double getVarThreshold() const { return varThreshold_; } 102 void setVarThreshold(double varThreshold) { varThreshold_ = (float) varThreshold; } 103 104 double getVarThresholdGen() const { return varThresholdGen_; } 105 void setVarThresholdGen(double varThresholdGen) { varThresholdGen_ = (float) varThresholdGen; } 106 107 double getVarInit() const { return varInit_; } 108 void setVarInit(double varInit) { varInit_ = (float) varInit; } 109 110 double getVarMin() const { return varMin_; } 111 void setVarMin(double varMin) { varMin_ = (float) varMin; } 112 113 double getVarMax() const { return varMax_; } 114 void setVarMax(double varMax) { varMax_ = (float) varMax; } 115 116 double getComplexityReductionThreshold() const { return ct_; } 117 void setComplexityReductionThreshold(double ct) { ct_ = (float) ct; } 118 119 bool getDetectShadows() const { return detectShadows_; } 120 void setDetectShadows(bool detectShadows) { detectShadows_ = detectShadows; } 121 122 int getShadowValue() const { return shadowValue_; } 123 void setShadowValue(int value) { shadowValue_ = (uchar) value; } 124 125 double getShadowThreshold() const { return shadowThreshold_; } 126 void setShadowThreshold(double threshold) { shadowThreshold_ = (float) threshold; } 127 128 private: 129 void initialize(Size frameSize, int frameType); 130 131 int history_; 132 int nmixtures_; 133 float backgroundRatio_; 134 float varThreshold_; 135 float varThresholdGen_; 136 float varInit_; 137 float varMin_; 138 float varMax_; 139 float ct_; 140 bool detectShadows_; 141 uchar shadowValue_; 142 float shadowThreshold_; 143 144 Size frameSize_; 145 int frameType_; 146 int nframes_; 147 148 GpuMat weight_; 149 GpuMat variance_; 150 GpuMat mean_; 151 152 //keep track of number of modes per pixel 153 GpuMat bgmodelUsedModes_; 154 }; 155 156 MOG2Impl::MOG2Impl(int history, double varThreshold, bool detectShadows) : 157 frameSize_(0, 0), frameType_(0), nframes_(0) 158 { 159 history_ = history > 0 ? history : defaultHistory; 160 varThreshold_ = varThreshold > 0 ? (float) varThreshold : defaultVarThreshold; 161 detectShadows_ = detectShadows; 162 163 nmixtures_ = defaultNMixtures; 164 backgroundRatio_ = defaultBackgroundRatio; 165 varInit_ = defaultVarInit; 166 varMax_ = defaultVarMax; 167 varMin_ = defaultVarMin; 168 varThresholdGen_ = defaultVarThresholdGen; 169 ct_ = defaultCT; 170 shadowValue_ = defaultShadowValue; 171 shadowThreshold_ = defaultShadowThreshold; 172 } 173 174 void MOG2Impl::apply(InputArray image, OutputArray fgmask, double learningRate) 175 { 176 apply(image, fgmask, learningRate, Stream::Null()); 177 } 178 179 void MOG2Impl::apply(InputArray _frame, OutputArray _fgmask, double learningRate, Stream& stream) 180 { 181 using namespace cv::cuda::device::mog2; 182 183 GpuMat frame = _frame.getGpuMat(); 184 185 int ch = frame.channels(); 186 int work_ch = ch; 187 188 if (nframes_ == 0 || learningRate >= 1.0 || frame.size() != frameSize_ || work_ch != mean_.channels()) 189 initialize(frame.size(), frame.type()); 190 191 _fgmask.create(frameSize_, CV_8UC1); 192 GpuMat fgmask = _fgmask.getGpuMat(); 193 194 fgmask.setTo(Scalar::all(0), stream); 195 196 ++nframes_; 197 learningRate = learningRate >= 0 && nframes_ > 1 ? learningRate : 1.0 / std::min(2 * nframes_, history_); 198 CV_Assert( learningRate >= 0 ); 199 200 mog2_gpu(frame, frame.channels(), fgmask, bgmodelUsedModes_, weight_, variance_, mean_, 201 (float) learningRate, static_cast<float>(-learningRate * ct_), detectShadows_, StreamAccessor::getStream(stream)); 202 } 203 204 void MOG2Impl::getBackgroundImage(OutputArray backgroundImage) const 205 { 206 getBackgroundImage(backgroundImage, Stream::Null()); 207 } 208 209 void MOG2Impl::getBackgroundImage(OutputArray _backgroundImage, Stream& stream) const 210 { 211 using namespace cv::cuda::device::mog2; 212 213 _backgroundImage.create(frameSize_, frameType_); 214 GpuMat backgroundImage = _backgroundImage.getGpuMat(); 215 216 getBackgroundImage2_gpu(backgroundImage.channels(), bgmodelUsedModes_, weight_, mean_, backgroundImage, StreamAccessor::getStream(stream)); 217 } 218 219 void MOG2Impl::initialize(cv::Size frameSize, int frameType) 220 { 221 using namespace cv::cuda::device::mog2; 222 223 CV_Assert( frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_8UC4 ); 224 225 frameSize_ = frameSize; 226 frameType_ = frameType; 227 nframes_ = 0; 228 229 int ch = CV_MAT_CN(frameType); 230 int work_ch = ch; 231 232 // for each gaussian mixture of each pixel bg model we store ... 233 // the mixture weight (w), 234 // the mean (nchannels values) and 235 // the covariance 236 weight_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); 237 variance_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1); 238 mean_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch)); 239 240 //make the array for keeping track of the used modes per pixel - all zeros at start 241 bgmodelUsedModes_.create(frameSize_, CV_8UC1); 242 bgmodelUsedModes_.setTo(Scalar::all(0)); 243 244 loadConstants(nmixtures_, varThreshold_, backgroundRatio_, varThresholdGen_, varInit_, varMin_, varMax_, shadowThreshold_, shadowValue_); 245 } 246 } 247 248 Ptr<cuda::BackgroundSubtractorMOG2> cv::cuda::createBackgroundSubtractorMOG2(int history, double varThreshold, bool detectShadows) 249 { 250 return makePtr<MOG2Impl>(history, varThreshold, detectShadows); 251 } 252 253 #endif 254