Skip to content

Commit f3cebb3

Browse files
authored
Merge pull request opencv#18077 from l-bat:reduce_sum
* Supported ReduceSum op * Skip test
1 parent 2b227f0 commit f3cebb3

File tree

4 files changed

+72
-9
lines changed

4 files changed

+72
-9
lines changed

modules/dnn/src/layers/pooling_layer.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ class PoolingLayerImpl CV_FINAL : public PoolingLayer
9898
type = AVE;
9999
else if (pool == "stochastic")
100100
type = STOCHASTIC;
101+
else if (pool == "sum")
102+
type = SUM;
101103
else
102104
CV_Error(Error::StsBadArg, "Unknown pooling type \"" + pool + "\"");
103105

@@ -195,7 +197,7 @@ class PoolingLayerImpl CV_FINAL : public PoolingLayer
195197
return type == MAX || type == AVE;
196198
}
197199
else
198-
return type != STOCHASTIC;
200+
return type != STOCHASTIC && type != SUM;
199201
}
200202
#endif
201203
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
@@ -288,7 +290,7 @@ class PoolingLayerImpl CV_FINAL : public PoolingLayer
288290
maxPooling(inputs[0], outputs[0], mask);
289291
break;
290292
}
291-
case AVE:
293+
case AVE: case SUM:
292294
CV_Assert_N(inputs.size() == 1, outputs.size() == 1);
293295
avePooling(inputs[0], outputs[0]);
294296
break;
@@ -366,7 +368,7 @@ class PoolingLayerImpl CV_FINAL : public PoolingLayer
366368
virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inputs,
367369
const std::vector<Ptr<BackendNode> >& nodes) CV_OVERRIDE
368370
{
369-
CV_Assert_N((inputs.size() == 1 && (type == MAX || type == AVE)) || inputs.size() == 2, nodes.size() == inputs.size());
371+
CV_Assert_N((inputs.size() == 1 && (type == MAX || type == AVE || type == SUM)) || inputs.size() == 2, nodes.size() == inputs.size());
370372
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
371373

372374
ngraph::op::PadType pad_type = ngraph::op::PadType::EXPLICIT;
@@ -381,6 +383,19 @@ virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inp
381383
exclude_pad, rounding_type, pad_type);
382384
return Ptr<BackendNode>(new InfEngineNgraphNode(ave_pool));
383385
}
386+
else if (type == SUM) {
387+
ngraph::Shape inpShape = ieInpNode->get_shape();
388+
CV_Assert(inpShape.size() == 2 + kernel_size.size());
389+
std::vector<int64_t> axes;
390+
for (size_t i = 0; i < kernel_size.size(); i++)
391+
{
392+
if (inpShape[2 + i] == kernel_size[i])
393+
axes.push_back(2 + i);
394+
}
395+
auto reduction_axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{axes.size()}, axes);
396+
auto reduce_sum = std::make_shared<ngraph::op::v1::ReduceSum>(ieInpNode, reduction_axes, true);
397+
return Ptr<BackendNode>(new InfEngineNgraphNode(reduce_sum));
398+
}
384399
else if (type == MAX) {
385400
auto max_pool = std::make_shared<ngraph::op::v1::MaxPool>(ieInpNode, ngraph::Strides(strides),
386401
ngraph::Shape(pads_begin), ngraph::Shape(pads_end), ngraph::Shape(kernel_size),
@@ -739,7 +754,7 @@ virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inp
739754
}
740755
}
741756
}
742-
else if (poolingType == AVE)
757+
else if (poolingType == AVE || poolingType == SUM)
743758
{
744759
for( ; x0 < x1; ++x0)
745760
{
@@ -750,7 +765,7 @@ virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inp
750765
xend = min(xend, inp_width);
751766
float inv_kernel_area = avePoolPaddedArea ? xdelta * ydelta * ddelta :
752767
((dend - dstart) * (yend - ystart) * (xend - xstart));
753-
inv_kernel_area = 1.0 / inv_kernel_area;
768+
inv_kernel_area = poolingType == AVE ? 1.0 / inv_kernel_area : 1.0;
754769
#if CV_SIMD128
755770
if( isPool2D && xstart > 0 && x0 + 7 < x1 && (x0 + 7) * stride_w - pad_l + kernel_w < inp_width )
756771
{
@@ -1095,6 +1110,7 @@ virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inp
10951110
MAX,
10961111
AVE,
10971112
STOCHASTIC,
1113+
SUM,
10981114
ROI, // RoI pooling, https://arxiv.org/pdf/1504.08083.pdf
10991115
PSROI // Position-sensitive RoI pooling, https://arxiv.org/pdf/1605.06409.pdf
11001116
};

modules/dnn/src/tensorflow/tf_importer.cpp

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,7 +2067,7 @@ void TFImporter::populateNet(Net dstNet)
20672067
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
20682068
connect(layer_id, dstNet, parsePin(layer.input(1)), id, 1);
20692069
}
2070-
else if (type == "Mean")
2070+
else if (type == "Mean" || type == "Sum")
20712071
{
20722072
// Computes the mean of elements across dimensions of a tensor.
20732073
// If keepdims is false (default) reduces input_tensor along the dimensions given in axis,
@@ -2116,7 +2116,7 @@ void TFImporter::populateNet(Net dstNet)
21162116
LayerParams avgLp;
21172117
std::string avgName = name + "/avg";
21182118
CV_Assert(layer_id.find(avgName) == layer_id.end());
2119-
avgLp.set("pool", "ave");
2119+
avgLp.set("pool", type == "Mean" ? "ave" : "sum");
21202120
// pooling kernel H x 1
21212121
avgLp.set("global_pooling_h", true);
21222122
avgLp.set("kernel_w", 1);
@@ -2153,11 +2153,44 @@ void TFImporter::populateNet(Net dstNet)
21532153
layer_id[name] = id;
21542154
connect(layer_id, dstNet, Pin(avgName), id, 0);
21552155
connect(layer_id, dstNet, Pin(layerShapeName), id, 1);
2156+
} else if (indices.total() == 1) {
2157+
int axis = toNCHW(indices.at<int>(0));
2158+
if (axis == 2 || axis == 3)
2159+
{
2160+
layerParams.set("pool", type == "Mean" ? "ave" : "sum");
2161+
layerParams.set(axis == 2 ? "kernel_w" : "kernel_h", 1);
2162+
layerParams.set(axis == 2 ? "global_pooling_h" : "global_pooling_w", true);
2163+
int id = dstNet.addLayer(name, "Pooling", layerParams);
2164+
layer_id[name] = id;
2165+
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0);
2166+
2167+
if (!keepDims)
2168+
{
2169+
// To keep correct order after squeeze dims we first need to change layout from NCHW to NHWC
2170+
LayerParams permLP;
2171+
int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC.
2172+
permLP.set("order", DictValue::arrayInt<int*>(order, 4));
2173+
std::string permName = name + "/nchw";
2174+
CV_Assert(layer_id.find(permName) == layer_id.end());
2175+
int permId = dstNet.addLayer(permName, "Permute", permLP);
2176+
layer_id[permName] = permId;
2177+
connect(layer_id, dstNet, Pin(name), permId, 0);
2178+
2179+
LayerParams squeezeLp;
2180+
std::string squeezeName = name + "/squeeze";
2181+
CV_Assert(layer_id.find(squeezeName) == layer_id.end());
2182+
squeezeLp.set("axis", indices.at<int>(0));
2183+
squeezeLp.set("end_axis", indices.at<int>(0) + 1);
2184+
int squeezeId = dstNet.addLayer(squeezeName, "Flatten", squeezeLp);
2185+
layer_id[squeezeName] = squeezeId;
2186+
connect(layer_id, dstNet, Pin(permName), squeezeId, 0);
2187+
}
2188+
}
21562189
} else {
21572190
if (indices.total() != 2 || indices.at<int>(0) != 1 || indices.at<int>(1) != 2)
2158-
CV_Error(Error::StsNotImplemented, "Unsupported mode of reduce_mean operation.");
2191+
CV_Error(Error::StsNotImplemented, "Unsupported mode of reduce_mean or reduce_sum operation.");
21592192

2160-
layerParams.set("pool", "ave");
2193+
layerParams.set("pool", type == "Mean" ? "ave" : "sum");
21612194
layerParams.set("global_pooling", true);
21622195
int id = dstNet.addLayer(name, "Pooling", layerParams);
21632196
layer_id[name] = id;

modules/dnn/test/test_darknet_importer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ TEST_P(Test_Darknet_layers, connected)
755755

756756
TEST_P(Test_Darknet_layers, relu)
757757
{
758+
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
759+
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
758760
testDarknetLayer("relu");
759761
}
760762

modules/dnn/test/test_tf_importer.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ TEST_P(Test_TensorFlow_layers, reduce_mean)
128128
runTensorFlowNet("global_pool_by_axis");
129129
}
130130

131+
TEST_P(Test_TensorFlow_layers, reduce_sum)
132+
{
133+
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
134+
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
135+
runTensorFlowNet("sum_pool_by_axis");
136+
}
137+
131138
TEST_P(Test_TensorFlow_layers, conv_single_conv)
132139
{
133140
runTensorFlowNet("single_conv");
@@ -340,6 +347,11 @@ TEST_P(Test_TensorFlow_layers, pooling_reduce_mean)
340347
runTensorFlowNet("reduce_mean"); // an average pooling over all spatial dimensions.
341348
}
342349

350+
TEST_P(Test_TensorFlow_layers, pooling_reduce_sum)
351+
{
352+
runTensorFlowNet("reduce_sum"); // a SUM pooling over all spatial dimensions.
353+
}
354+
343355
TEST_P(Test_TensorFlow_layers, max_pool_grad)
344356
{
345357
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)

0 commit comments

Comments
 (0)