diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index 1a01ac87d6..8cbe1c4b23 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -2142,6 +2142,7 @@ void TFImporter::parseMean(tensorflow::GraphDef& net, const tensorflow::NodeDef& const std::string& type = layer.op(); const int num_inputs = layer.input_size(); std::string pool_type = cv::toLowerCase(type); + DataLayout layout = getDataLayout(name, data_layouts); if (pool_type == "mean") { @@ -2205,6 +2206,16 @@ void TFImporter::parseMean(tensorflow::GraphDef& net, const tensorflow::NodeDef& if (!keepDims) { + if (layout == DATA_LAYOUT_NHWC) + { + LayerParams permLP; + int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC. + std::string permName = name + "/nhwc"; + Pin inpId = Pin(layerShapeName); + addPermuteLayer(order, permName, inpId); + layerShapeName = permName; + } + LayerParams squeezeLp; std::string squeezeName = name + "/squeeze"; CV_Assert(layer_id.find(squeezeName) == layer_id.end()); @@ -2227,22 +2238,30 @@ void TFImporter::parseMean(tensorflow::GraphDef& net, const tensorflow::NodeDef& layerParams.set("pool", pool_type); layerParams.set(axis == 2 ? "kernel_w" : "kernel_h", 1); layerParams.set(axis == 2 ? "global_pooling_h" : "global_pooling_w", true); - int id = dstNet.addLayer(name, "Pooling", layerParams); - layer_id[name] = id; - connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); - if (!keepDims) + if (keepDims) + { + int id = dstNet.addLayer(name, "Pooling", layerParams); + layer_id[name] = id; + connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); + } + else { // To keep correct order after squeeze dims we first need to change layout from NCHW to NHWC + std::string poolingName = name + "/Pooling"; + CV_Assert(layer_id.find(poolingName) == layer_id.end()); + int id = dstNet.addLayer(poolingName, "Pooling", layerParams); + layer_id[poolingName] = id; + connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); + LayerParams permLP; int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC. - std::string permName = name + "/nchw"; - Pin inpId = Pin(name); + std::string permName = name + "/nhwc"; + Pin inpId = Pin(poolingName); addPermuteLayer(order, permName, inpId); LayerParams squeezeLp; - std::string squeezeName = name + "/squeeze"; - CV_Assert(layer_id.find(squeezeName) == layer_id.end()); + const std::string& squeezeName = name; squeezeLp.set("axis", indices.at(0)); squeezeLp.set("end_axis", indices.at(0) + 1); int squeezeId = dstNet.addLayer(squeezeName, "Flatten", squeezeLp); @@ -2254,32 +2273,34 @@ void TFImporter::parseMean(tensorflow::GraphDef& net, const tensorflow::NodeDef& { int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC. Pin inpId = parsePin(layer.input(0)); - addPermuteLayer(order, name + "/nhwc", inpId); + std::string permName = name + "/nhwc"; + addPermuteLayer(order, permName, inpId); layerParams.set("pool", pool_type); layerParams.set("kernel_h", 1); layerParams.set("global_pooling_w", true); - int id = dstNet.addLayer(name, "Pooling", layerParams); - layer_id[name] = id; - connect(layer_id, dstNet, inpId, id, 0); + std::string poolingName = name + "/Pooling"; + CV_Assert(layer_id.find(poolingName) == layer_id.end()); + int id = dstNet.addLayer(poolingName, "Pooling", layerParams); + layer_id[poolingName] = id; + connect(layer_id, dstNet, Pin(permName), id, 0); if (!keepDims) { LayerParams squeezeLp; - std::string squeezeName = name + "/squeeze"; - CV_Assert(layer_id.find(squeezeName) == layer_id.end()); + const std::string& squeezeName = name; int channel_id = 3; // TF NHWC layout squeezeLp.set("axis", channel_id - 1); squeezeLp.set("end_axis", channel_id); int squeezeId = dstNet.addLayer(squeezeName, "Flatten", squeezeLp); layer_id[squeezeName] = squeezeId; - connect(layer_id, dstNet, Pin(name), squeezeId, 0); + connect(layer_id, dstNet, Pin(poolingName), squeezeId, 0); } else { int order[] = {0, 3, 1, 2}; // From NHWC to OpenCV's NCHW. - Pin inpId = parsePin(name); - addPermuteLayer(order, name + "/nchw", inpId); + Pin inpId = parsePin(poolingName); + addPermuteLayer(order, name, inpId); } } } else { @@ -2288,18 +2309,26 @@ void TFImporter::parseMean(tensorflow::GraphDef& net, const tensorflow::NodeDef& layerParams.set("pool", pool_type); layerParams.set("global_pooling", true); - int id = dstNet.addLayer(name, "Pooling", layerParams); - layer_id[name] = id; - connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); - if (!keepDims) + if (keepDims) { + int id = dstNet.addLayer(name, "Pooling", layerParams); + layer_id[name] = id; + connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); + } + else + { + std::string poolingName = name + "/Pooling"; + CV_Assert(layer_id.find(poolingName) == layer_id.end()); + int id = dstNet.addLayer(poolingName, "Pooling", layerParams); + layer_id[poolingName] = id; + connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); LayerParams flattenLp; - std::string flattenName = name + "/flatten"; - CV_Assert(layer_id.find(flattenName) == layer_id.end()); + const std::string& flattenName = name; int flattenId = dstNet.addLayer(flattenName, "Flatten", flattenLp); layer_id[flattenName] = flattenId; - connect(layer_id, dstNet, Pin(name), flattenId, 0); + connect(layer_id, dstNet, Pin(poolingName), flattenId, 0); + data_layouts[name] = DATA_LAYOUT_PLANAR; } } } diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index cdf3794bf1..b688c31383 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -413,6 +413,19 @@ TEST_P(Test_TensorFlow_layers, pooling_reduce_sum) runTensorFlowNet("reduce_sum"); // a SUM pooling over all spatial dimensions. } +TEST_P(Test_TensorFlow_layers, pooling_reduce_sum2) +{ + int axises[] = {0, 1, 2, 3}; + for (int keepdims = 0; keepdims <= 1; ++keepdims) + { + for (int i = 0; i < sizeof(axises)/sizeof(axises[0]); ++i) + { + runTensorFlowNet(cv::format("reduce_sum_%d_%s", axises[i], (keepdims ? "True" : "False"))); + } + runTensorFlowNet(cv::format("reduce_sum_1_2_%s", keepdims ? "True" : "False")); + } +} + TEST_P(Test_TensorFlow_layers, max_pool_grad) { if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)