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 
createBackgroundSubtractorMOG(int,int,double,double)50 Ptr<cuda::BackgroundSubtractorMOG> cv::cuda::createBackgroundSubtractorMOG(int, int, double, double)  { throw_no_cuda(); return Ptr<cuda::BackgroundSubtractorMOG>(); }
51 
52 #else
53 
54 namespace cv { namespace cuda { namespace device
55 {
56     namespace mog
57     {
58         void mog_gpu(PtrStepSzb frame, int cn, PtrStepSzb fgmask, PtrStepSzf weight, PtrStepSzf sortKey, PtrStepSzb mean, PtrStepSzb var,
59                      int nmixtures, float varThreshold, float learningRate, float backgroundRatio, float noiseSigma,
60                      cudaStream_t stream);
61         void getBackgroundImage_gpu(int cn, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, int nmixtures, float backgroundRatio, cudaStream_t stream);
62     }
63 }}}
64 
65 namespace
66 {
67     const int defaultNMixtures = 5;
68     const int defaultHistory = 200;
69     const float defaultBackgroundRatio = 0.7f;
70     const float defaultVarThreshold = 2.5f * 2.5f;
71     const float defaultNoiseSigma = 30.0f * 0.5f;
72     const float defaultInitialWeight = 0.05f;
73 
74     class MOGImpl : public cuda::BackgroundSubtractorMOG
75     {
76     public:
77         MOGImpl(int history, int nmixtures, double backgroundRatio, double noiseSigma);
78 
79         void apply(InputArray image, OutputArray fgmask, double learningRate=-1);
80         void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream);
81 
82         void getBackgroundImage(OutputArray backgroundImage) const;
83         void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const;
84 
getHistory() const85         int getHistory() const { return history_; }
setHistory(int nframes)86         void setHistory(int nframes) { history_ = nframes; }
87 
getNMixtures() const88         int getNMixtures() const { return nmixtures_; }
setNMixtures(int nmix)89         void setNMixtures(int nmix) { nmixtures_ = nmix; }
90 
getBackgroundRatio() const91         double getBackgroundRatio() const { return backgroundRatio_; }
setBackgroundRatio(double backgroundRatio)92         void setBackgroundRatio(double backgroundRatio) { backgroundRatio_ = (float) backgroundRatio; }
93 
getNoiseSigma() const94         double getNoiseSigma() const { return noiseSigma_; }
setNoiseSigma(double noiseSigma)95         void setNoiseSigma(double noiseSigma) { noiseSigma_ = (float) noiseSigma; }
96 
97     private:
98         //! re-initiaization method
99         void initialize(Size frameSize, int frameType);
100 
101         int history_;
102         int nmixtures_;
103         float backgroundRatio_;
104         float noiseSigma_;
105 
106         float varThreshold_;
107 
108         Size frameSize_;
109         int frameType_;
110         int nframes_;
111 
112         GpuMat weight_;
113         GpuMat sortKey_;
114         GpuMat mean_;
115         GpuMat var_;
116     };
117 
MOGImpl(int history,int nmixtures,double backgroundRatio,double noiseSigma)118     MOGImpl::MOGImpl(int history, int nmixtures, double backgroundRatio, double noiseSigma) :
119         frameSize_(0, 0), frameType_(0), nframes_(0)
120     {
121         history_ = history > 0 ? history : defaultHistory;
122         nmixtures_ = std::min(nmixtures > 0 ? nmixtures : defaultNMixtures, 8);
123         backgroundRatio_ = backgroundRatio > 0 ? (float) backgroundRatio : defaultBackgroundRatio;
124         noiseSigma_ = noiseSigma > 0 ? (float) noiseSigma : defaultNoiseSigma;
125 
126         varThreshold_ = defaultVarThreshold;
127     }
128 
apply(InputArray image,OutputArray fgmask,double learningRate)129     void MOGImpl::apply(InputArray image, OutputArray fgmask, double learningRate)
130     {
131         apply(image, fgmask, learningRate, Stream::Null());
132     }
133 
apply(InputArray _frame,OutputArray _fgmask,double learningRate,Stream & stream)134     void MOGImpl::apply(InputArray _frame, OutputArray _fgmask, double learningRate, Stream& stream)
135     {
136         using namespace cv::cuda::device::mog;
137 
138         GpuMat frame = _frame.getGpuMat();
139 
140         CV_Assert( frame.depth() == CV_8U );
141 
142         int ch = frame.channels();
143         int work_ch = ch;
144 
145         if (nframes_ == 0 || learningRate >= 1.0 || frame.size() != frameSize_ || work_ch != mean_.channels())
146             initialize(frame.size(), frame.type());
147 
148         _fgmask.create(frameSize_, CV_8UC1);
149         GpuMat fgmask = _fgmask.getGpuMat();
150 
151         ++nframes_;
152         learningRate = learningRate >= 0 && nframes_ > 1 ? learningRate : 1.0 / std::min(nframes_, history_);
153         CV_Assert( learningRate >= 0 );
154 
155         mog_gpu(frame, ch, fgmask, weight_, sortKey_, mean_, var_, nmixtures_,
156                 varThreshold_, (float) learningRate, backgroundRatio_, noiseSigma_,
157                 StreamAccessor::getStream(stream));
158     }
159 
getBackgroundImage(OutputArray backgroundImage) const160     void MOGImpl::getBackgroundImage(OutputArray backgroundImage) const
161     {
162         getBackgroundImage(backgroundImage, Stream::Null());
163     }
164 
getBackgroundImage(OutputArray _backgroundImage,Stream & stream) const165     void MOGImpl::getBackgroundImage(OutputArray _backgroundImage, Stream& stream) const
166     {
167         using namespace cv::cuda::device::mog;
168 
169         _backgroundImage.create(frameSize_, frameType_);
170         GpuMat backgroundImage = _backgroundImage.getGpuMat();
171 
172         getBackgroundImage_gpu(backgroundImage.channels(), weight_, mean_, backgroundImage, nmixtures_, backgroundRatio_, StreamAccessor::getStream(stream));
173     }
174 
initialize(Size frameSize,int frameType)175     void MOGImpl::initialize(Size frameSize, int frameType)
176     {
177         CV_Assert( frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_8UC4 );
178 
179         frameSize_ = frameSize;
180         frameType_ = frameType;
181 
182         int ch = CV_MAT_CN(frameType);
183         int work_ch = ch;
184 
185         // for each gaussian mixture of each pixel bg model we store
186         // the mixture sort key (w/sum_of_variances), the mixture weight (w),
187         // the mean (nchannels values) and
188         // the diagonal covariance matrix (another nchannels values)
189 
190         weight_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1);
191         sortKey_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC1);
192         mean_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch));
193         var_.create(frameSize.height * nmixtures_, frameSize_.width, CV_32FC(work_ch));
194 
195         weight_.setTo(cv::Scalar::all(0));
196         sortKey_.setTo(cv::Scalar::all(0));
197         mean_.setTo(cv::Scalar::all(0));
198         var_.setTo(cv::Scalar::all(0));
199 
200         nframes_ = 0;
201     }
202 }
203 
createBackgroundSubtractorMOG(int history,int nmixtures,double backgroundRatio,double noiseSigma)204 Ptr<cuda::BackgroundSubtractorMOG> cv::cuda::createBackgroundSubtractorMOG(int history, int nmixtures, double backgroundRatio, double noiseSigma)
205 {
206     return makePtr<MOGImpl>(history, nmixtures, backgroundRatio, noiseSigma);
207 }
208 
209 #endif
210