Fix Proposal deep learning layer
authorDmitry Kurtaev <dmitry.kurtaev+github@gmail.com>
Wed, 4 Apr 2018 11:48:29 +0000 (14:48 +0300)
committerDmitry Kurtaev <dmitry.kurtaev+github@gmail.com>
Wed, 4 Apr 2018 11:48:29 +0000 (14:48 +0300)
modules/dnn/src/layers/proposal_layer.cpp
modules/dnn/test/test_layers.cpp

index a4c0ecf..7784e70 100644 (file)
@@ -31,6 +31,7 @@ public:
             lp.set("flip", false);
             lp.set("clip", false);
             lp.set("normalized_bbox", false);
+            lp.set("offset", 0.5 * baseSize / featStride);
 
             // Unused values.
             float variance[] = {0.1f, 0.1f, 0.2f, 0.2f};
@@ -123,7 +124,9 @@ public:
         CV_Assert(layerInternals.empty());
         internals.push_back(layerOutputs[0]);
 
-        outputs.resize(1, shape(keepTopAfterNMS, 5));
+        outputs.resize(2);
+        outputs[0] = shape(keepTopAfterNMS, 5);
+        outputs[1] = shape(keepTopAfterNMS, 1);
         return false;
     }
 
@@ -210,13 +213,20 @@ public:
         CV_Assert(numDets <= keepTopAfterNMS);
 
         MatShape s = shape(numDets, 7);
-        UMat src = layerOutputs[0].reshape(1, s.size(), &s[0]).colRange(3, 7);
+        layerOutputs[0] = layerOutputs[0].reshape(1, s.size(), &s[0]);
+
+        // The boxes.
         UMat dst = outputs[0].rowRange(0, numDets);
-        src.copyTo(dst.colRange(1, 5));
+        layerOutputs[0].colRange(3, 7).copyTo(dst.colRange(1, 5));
         dst.col(0).setTo(0);  // First column are batch ids. Keep it zeros too.
 
+        // The scores.
+        dst = outputs[1].rowRange(0, numDets);
+        layerOutputs[0].col(2).copyTo(dst);
+
         if (numDets < keepTopAfterNMS)
-            outputs[0].rowRange(numDets, keepTopAfterNMS).setTo(0);
+            for (int i = 0; i < 2; ++i)
+                outputs[i].rowRange(numDets, keepTopAfterNMS).setTo(0);
 
         return true;
     }
@@ -284,13 +294,19 @@ public:
         const int numDets = layerOutputs[0].total() / 7;
         CV_Assert(numDets <= keepTopAfterNMS);
 
-        Mat src = layerOutputs[0].reshape(1, numDets).colRange(3, 7);
+        // The boxes.
+        layerOutputs[0] = layerOutputs[0].reshape(1, numDets);
         Mat dst = outputs[0].rowRange(0, numDets);
-        src.copyTo(dst.colRange(1, 5));
+        layerOutputs[0].colRange(3, 7).copyTo(dst.colRange(1, 5));
         dst.col(0).setTo(0);  // First column are batch ids. Keep it zeros too.
 
+        // The scores.
+        dst = outputs[1].rowRange(0, numDets);
+        layerOutputs[0].col(2).copyTo(dst);
+
         if (numDets < keepTopAfterNMS)
-            outputs[0].rowRange(numDets, keepTopAfterNMS).setTo(0);
+            for (int i = 0; i < 2; ++i)
+                outputs[i].rowRange(numDets, keepTopAfterNMS).setTo(0);
     }
 
 private:
index 3cdf88a..dd5a06b 100644 (file)
@@ -602,54 +602,36 @@ TEST(Layer_Test_ROIPooling, Accuracy)
     normAssert(out, ref);
 }
 
-TEST(Layer_Test_FasterRCNN_Proposal, Accuracy)
+typedef testing::TestWithParam<DNNTarget> Test_Caffe_layers;
+TEST_P(Test_Caffe_layers, FasterRCNN_Proposal)
 {
     Net net = readNetFromCaffe(_tf("net_faster_rcnn_proposal.prototxt"));
+    net.setPreferableTarget(GetParam());
 
     Mat scores = blobFromNPY(_tf("net_faster_rcnn_proposal.scores.npy"));
     Mat deltas = blobFromNPY(_tf("net_faster_rcnn_proposal.deltas.npy"));
     Mat imInfo = (Mat_<float>(1, 3) << 600, 800, 1.6f);
-    Mat ref = blobFromNPY(_tf("net_faster_rcnn_proposal.npy"));
 
     net.setInput(scores, "rpn_cls_prob_reshape");
     net.setInput(deltas, "rpn_bbox_pred");
     net.setInput(imInfo, "im_info");
 
-    Mat out = net.forward();
-
-    const int numDets = ref.size[0];
-    EXPECT_LE(numDets, out.size[0]);
-    normAssert(out.rowRange(0, numDets), ref);
-
-    if (numDets < out.size[0])
-        EXPECT_EQ(countNonZero(out.rowRange(numDets, out.size[0])), 0);
-}
-
-OCL_TEST(Layer_Test_FasterRCNN_Proposal, Accuracy)
-{
-    Net net = readNetFromCaffe(_tf("net_faster_rcnn_proposal.prototxt"));
-
-    net.setPreferableBackend(DNN_BACKEND_DEFAULT);
-    net.setPreferableTarget(DNN_TARGET_OPENCL);
-
-    Mat scores = blobFromNPY(_tf("net_faster_rcnn_proposal.scores.npy"));
-    Mat deltas = blobFromNPY(_tf("net_faster_rcnn_proposal.deltas.npy"));
-    Mat imInfo = (Mat_<float>(1, 3) << 600, 800, 1.6f);
-    Mat ref = blobFromNPY(_tf("net_faster_rcnn_proposal.npy"));
-
-    net.setInput(scores, "rpn_cls_prob_reshape");
-    net.setInput(deltas, "rpn_bbox_pred");
-    net.setInput(imInfo, "im_info");
+    std::vector<Mat> outs;
+    net.forward(outs, "output");
 
-    Mat out = net.forward();
-
-    const int numDets = ref.size[0];
-    EXPECT_LE(numDets, out.size[0]);
-    normAssert(out.rowRange(0, numDets), ref);
-
-    if (numDets < out.size[0])
-        EXPECT_EQ(countNonZero(out.rowRange(numDets, out.size[0])), 0);
+    for (int i = 0; i < 2; ++i)
+    {
+        Mat ref = blobFromNPY(_tf(i == 0 ? "net_faster_rcnn_proposal.out_rois.npy" :
+                                           "net_faster_rcnn_proposal.out_scores.npy"));
+        const int numDets = ref.size[0];
+        EXPECT_LE(numDets, outs[i].size[0]);
+        normAssert(outs[i].rowRange(0, numDets), ref);
+
+        if (numDets < outs[i].size[0])
+            EXPECT_EQ(countNonZero(outs[i].rowRange(numDets, outs[i].size[0])), 0);
+    }
 }
+INSTANTIATE_TEST_CASE_P(/**/, Test_Caffe_layers, availableDnnTargets());
 
 typedef testing::TestWithParam<tuple<Vec4i, Vec2i, bool> > Scale_untrainable;
 TEST_P(Scale_untrainable, Accuracy)