added support of all types to BackgroundSubtractorGMG
authorVladislav Vinogradov <vlad.vinogradov@itseez.com>
Mon, 13 Aug 2012 06:28:42 +0000 (10:28 +0400)
committerVladislav Vinogradov <vlad.vinogradov@itseez.com>
Mon, 13 Aug 2012 06:28:42 +0000 (10:28 +0400)
modules/video/include/opencv2/video/background_segm.hpp
modules/video/src/bgfg_gmg.cpp

index 9c37ffa..2ec21ee 100644 (file)
@@ -251,7 +251,7 @@ private:
     int frameNum_;
 
     cv::Mat_<int> nfeatures_;
-    cv::Mat_<int> colors_;
+    cv::Mat_<uint> colors_;
     cv::Mat_<float> weights_;
 
     cv::Mat buf_;
index acec3ed..881f552 100644 (file)
@@ -91,7 +91,7 @@ void cv::BackgroundSubtractorGMG::initialize(cv::Size frameSize, double min, dou
 
 namespace
 {
-    float findFeature(int color, const int* colors, const float* weights, int nfeatures)
+    float findFeature(uint color, const uint* colors, const float* weights, int nfeatures)
     {
         for (int i = 0; i < nfeatures; ++i)
         {
@@ -116,7 +116,7 @@ namespace
         }
     }
 
-    bool insertFeature(int color, float weight, int* colors, float* weights, int& nfeatures, int maxFeatures)
+    bool insertFeature(uint color, float weight, uint* colors, float* weights, int& nfeatures, int maxFeatures)
     {
         int idx = -1;
         for (int i = 0; i < nfeatures; ++i)
@@ -134,7 +134,7 @@ namespace
         {
             // move feature to beginning of list
 
-            ::memmove(colors + 1, colors, idx * sizeof(int));
+            ::memmove(colors + 1, colors, idx * sizeof(uint));
             ::memmove(weights + 1, weights, idx * sizeof(float));
 
             colors[0] = color;
@@ -144,7 +144,7 @@ namespace
         {
             // discard oldest feature
 
-            ::memmove(colors + 1, colors, (nfeatures - 1) * sizeof(int));
+            ::memmove(colors + 1, colors, (nfeatures - 1) * sizeof(uint));
             ::memmove(weights + 1, weights, (nfeatures - 1) * sizeof(float));
 
             colors[0] = color;
@@ -166,45 +166,31 @@ namespace
 
 namespace
 {
-    template <int cn> struct Quantization_
-    {
-        template <typename T>
-        static inline int apply(T val, double minVal, double maxVal, int quantizationLevels)
-        {
-            int res = 0;
-            res |= static_cast<int>((val[0] - minVal) * quantizationLevels / (maxVal - minVal));
-            res |= static_cast<int>((val[1] - minVal) * quantizationLevels / (maxVal - minVal)) << 8;
-            res |= static_cast<int>((val[2] - minVal) * quantizationLevels / (maxVal - minVal)) << 16;
-            return res;
-        }
-    };
-    template <> struct Quantization_<1>
-    {
-        template <typename T>
-        static inline int apply(T val, double minVal, double maxVal, int quantizationLevels)
-        {
-            return static_cast<int>((val - minVal) * quantizationLevels / (maxVal - minVal));
-        }
-    };
     template <typename T> struct Quantization
     {
-        static int apply(const void* src_, int x, double minVal, double maxVal, int quantizationLevels)
+        static uint apply(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels)
         {
             const T* src = static_cast<const T*>(src_);
-            return Quantization_<cv::DataType<T>::channels>::apply(src[x], minVal, maxVal, quantizationLevels);
+            src += x * cn;
+
+            uint res = 0;
+            for (int i = 0, shift = 0; i < cn; ++i, ++src, shift += 8)
+                res |= static_cast<int>((*src - minVal) * quantizationLevels / (maxVal - minVal)) << shift;
+
+            return res;
         }
     };
 
     class GMG_LoopBody : public cv::ParallelLoopBody
     {
     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,
+        GMG_LoopBody(const cv::Mat& frame, const cv::Mat& fgmask, const cv::Mat_<int>& nfeatures, const cv::Mat_<uint>& colors, const cv::Mat_<float>& weights,
                      int maxFeatures, double learningRate, int numInitializationFrames, int quantizationLevels, double backgroundPrior, double decisionThreshold,
                      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), updateBackgroundModel_(updateBackgroundModel)
+            maxFeatures_(maxFeatures), learningRate_(learningRate), numInitializationFrames_(numInitializationFrames), quantizationLevels_(quantizationLevels),
+            backgroundPrior_(backgroundPrior), decisionThreshold_(decisionThreshold), updateBackgroundModel_(updateBackgroundModel),
+            maxVal_(maxVal), minVal_(minVal), frameNum_(frameNum)
         {
         }
 
@@ -216,7 +202,7 @@ namespace
         mutable cv::Mat_<uchar> fgmask_;
 
         mutable cv::Mat_<int> nfeatures_;
-        mutable cv::Mat_<int> colors_;
+        mutable cv::Mat_<uint> colors_;
         mutable cv::Mat_<float> weights_;
 
         int     maxFeatures_;
@@ -234,20 +220,23 @@ namespace
 
     void GMG_LoopBody::operator() (const cv::Range& range) const
     {
-        typedef int (*func_t)(const void* src_, int x, double minVal, double maxVal, int quantizationLevels);
-        static const func_t funcs[6][4] =
+        typedef uint (*func_t)(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels);
+        static const func_t funcs[] =
         {
-            {Quantization<uchar>::apply, 0, Quantization<cv::Vec3b>::apply, Quantization<cv::Vec4b>::apply},
-            {0,0,0,0},
-            {Quantization<ushort>::apply, 0, Quantization<cv::Vec3w>::apply, Quantization<cv::Vec4w>::apply},
-            {0,0,0,0},
-            {0,0,0,0},
-            {Quantization<float>::apply, 0, Quantization<cv::Vec3f>::apply, Quantization<cv::Vec4f>::apply},
+            Quantization<uchar>::apply,
+            Quantization<schar>::apply,
+            Quantization<ushort>::apply,
+            Quantization<short>::apply,
+            Quantization<int>::apply,
+            Quantization<float>::apply,
+            Quantization<double>::apply
         };
 
-        const func_t func = funcs[frame_.depth()][frame_.channels() - 1];
+        const func_t func = funcs[frame_.depth()];
         CV_Assert(func != 0);
 
+        const int cn = frame_.channels();
+
         for (int y = range.start, featureIdx = y * frame_.cols; y < range.end; ++y)
         {
             const uchar* frame_row = frame_.ptr(y);
@@ -257,10 +246,10 @@ namespace
             for (int x = 0; x < frame_.cols; ++x, ++featureIdx)
             {
                 int nfeatures = nfeatures_row[x];
-                int* colors = colors_[featureIdx];
+                uint* colors = colors_[featureIdx];
                 float* weights = weights_[featureIdx];
 
-                int newFeatureColor = func(frame_row, x, minVal_, maxVal_, quantizationLevels_);
+                uint newFeatureColor = func(frame_row, x, cn, minVal_, maxVal_, quantizationLevels_);
 
                 bool isForeground = false;