Faster-RCNN models support
[platform/upstream/opencv.git] / modules / dnn / src / layers / pooling_layer.cpp
index 6c51f61..0574458 100644 (file)
@@ -57,13 +57,17 @@ namespace cv
 {
 namespace dnn
 {
+static inline int scaleAndRoundRoi(float f, float scale)
+{
+    return (int)(f * scale + (f >= 0.f ? 0.5f : -0.5f));
+}
 
 class PoolingLayerImpl : public PoolingLayer
 {
 public:
     PoolingLayerImpl(const LayerParams& params)
     {
-        type = PoolingLayer::MAX;
+        type = MAX;
         computeMaxIdx = true;
         globalPooling = false;
 
@@ -71,11 +75,11 @@ public:
         {
             String pool = params.get<String>("pool").toLowerCase();
             if (pool == "max")
-                type = PoolingLayer::MAX;
+                type = MAX;
             else if (pool == "ave")
-                type = PoolingLayer::AVE;
+                type = AVE;
             else if (pool == "stochastic")
-                type = PoolingLayer::STOCHASTIC;
+                type = STOCHASTIC;
             else
                 CV_Error(Error::StsBadArg, "Unknown pooling type \"" + pool + "\"");
             getPoolingKernelParams(params, kernel.height, kernel.width, globalPooling,
@@ -83,7 +87,8 @@ public:
         }
         else if (params.has("pooled_w") || params.has("pooled_h") || params.has("spatial_scale"))
         {
-            type = PoolingLayer::ROI;
+            type = ROI;
+            computeMaxIdx = false;
         }
         setParamsFrom(params);
         ceilMode = params.get<bool>("ceil_mode", true);
@@ -115,8 +120,7 @@ public:
     {
         return backendId == DNN_BACKEND_DEFAULT ||
                backendId == DNN_BACKEND_HALIDE && haveHalide() &&
-               (type == PoolingLayer::MAX ||
-                type == PoolingLayer::AVE && !pad.width && !pad.height);
+               (type == MAX || type == AVE && !pad.width && !pad.height);
     }
 
 #ifdef HAVE_OPENCL
@@ -200,9 +204,9 @@ public:
 
     virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &inputs)
     {
-        if (type == PoolingLayer::MAX)
+        if (type == MAX)
             return initMaxPoolingHalide(inputs);
-        else if (type == PoolingLayer::AVE)
+        else if (type == AVE)
             return initAvePoolingHalide(inputs);
         else
             return Ptr<BackendNode>();
@@ -221,7 +225,7 @@ public:
         float spatialScale;
 
         PoolingInvoker() : src(0), rois(0), dst(0), mask(0), nstripes(0),
-                           computeMaxIdx(0), poolingType(PoolingLayer::MAX), spatialScale(0) {}
+                           computeMaxIdx(0), poolingType(MAX), spatialScale(0) {}
 
         static void run(const Mat& src, const Mat& rois, Mat& dst, Mat& mask, Size kernel,
                         Size stride, Size pad, int poolingType, float spatialScale,
@@ -291,24 +295,17 @@ public:
                 int ystart, yend;
 
                 const float *srcData;
-                int xstartROI = 0;
-                float roiRatio = 0;
                 if (poolingType == ROI)
                 {
                     const float *roisData = rois->ptr<float>(n);
-                    int ystartROI = round(roisData[2] * spatialScale);
-                    int yendROI = round(roisData[4] * spatialScale);
+                    int ystartROI = scaleAndRoundRoi(roisData[2], spatialScale);
+                    int yendROI = scaleAndRoundRoi(roisData[4], spatialScale);
                     int roiHeight = std::max(yendROI - ystartROI + 1, 1);
-                    roiRatio = (float)roiHeight / height;
+                    float roiRatio = (float)roiHeight / height;
 
                     ystart = ystartROI + y0 * roiRatio;
                     yend = ystartROI + std::ceil((y0 + 1) * roiRatio);
 
-                    xstartROI = round(roisData[1] * spatialScale);
-                    int xendROI = round(roisData[3] * spatialScale);
-                    int roiWidth = std::max(xendROI - xstartROI + 1, 1);
-                    roiRatio = (float)roiWidth / width;
-
                     CV_Assert(roisData[0] < src->size[0]);
                     srcData = src->ptr<float>(roisData[0], c);
                 }
@@ -328,22 +325,12 @@ public:
                 ofs0 += delta;
                 int x1 = x0 + delta;
 
-                if( poolingType == MAX || poolingType == ROI)
+                if( poolingType == MAX)
                     for( ; x0 < x1; x0++ )
                     {
-                        int xstart, xend;
-                        if (poolingType == ROI)
-                        {
-                            xstart = xstartROI + x0 * roiRatio;
-                            xend = xstartROI + std::ceil((x0 + 1) * roiRatio);
-                        }
-                        else
-                        {
-                            xstart = x0 * stride_w - pad_w;
-                            xend = xstart + kernel_w;
-                        }
+                        int xstart = x0 * stride_w - pad_w;
+                        int xend = min(xstart + kernel_w, inp_width);
                         xstart = max(xstart, 0);
-                        xend = min(xend, inp_width);
                         if (xstart >= xend || ystart >= yend)
                         {
                             dstData[x0] = 0;
@@ -490,7 +477,7 @@ public:
                             }
                         }
                     }
-                else
+                else if (poolingType == AVE)
                 {
                     for( ; x0 < x1; x0++ )
                     {
@@ -540,6 +527,37 @@ public:
                         }
                     }
                 }
+                else  // ROI
+                {
+                    const float *roisData = rois->ptr<float>(n);
+                    int xstartROI = scaleAndRoundRoi(roisData[1], spatialScale);
+                    int xendROI = scaleAndRoundRoi(roisData[3], spatialScale);
+                    int roiWidth = std::max(xendROI - xstartROI + 1, 1);
+                    float roiRatio = (float)roiWidth / width;
+                    for( ; x0 < x1; x0++ )
+                    {
+                        int xstart = xstartROI + x0 * roiRatio;
+                        int xend = xstartROI + std::ceil((x0 + 1) * roiRatio);
+                        xstart = max(xstart, 0);
+                        xend = min(xend, inp_width);
+                        if (xstart >= xend || ystart >= yend)
+                        {
+                            dstData[x0] = 0;
+                            if (compMaxIdx && dstMaskData)
+                                dstMaskData[x0] = -1;
+                            continue;
+                        }
+                        float max_val = -FLT_MAX;
+                        for (int y = ystart; y < yend; ++y)
+                            for (int x = xstart; x < xend; ++x)
+                            {
+                                const int index = y * inp_width + x;
+                                float val = srcData[index];
+                                max_val = std::max(max_val, val);
+                            }
+                        dstData[x0] = max_val;
+                    }
+                }
             }
         }
     };
@@ -698,7 +716,7 @@ public:
             out.height = 1;
             out.width = 1;
         }
-        else if (type == PoolingLayer::ROI)
+        else if (type == ROI)
         {
             out.height = pooledSize.height;
             out.width = pooledSize.width;
@@ -757,6 +775,14 @@ public:
         }
         return flops;
     }
+private:
+    enum Type
+    {
+        MAX,
+        AVE,
+        STOCHASTIC,
+        ROI
+    };
 };
 
 Ptr<PoolingLayer> PoolingLayer::create(const LayerParams& params)