Home | History | Annotate | Download | only in src
      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