From b36eba7fab0182333333d5881abeb18321aed05d Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Sat, 4 Apr 2020 16:02:17 +0300 Subject: [PATCH] Support FusedResizeAndPadConv2D from TensorFlow --- modules/dnn/src/tensorflow/tf_importer.cpp | 46 ++++++++++++++++++++++++++++-- modules/dnn/test/test_tf_importer.cpp | 5 ++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index fe7e47f..0dd2177 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -1402,9 +1402,17 @@ void TFImporter::populateNet(Net dstNet) netInputsNames.push_back(name); layer_id[name] = 0; } + tensorflow::TensorShapeProto shape; if (hasLayerAttr(layer, "shape")) + shape = getLayerAttr(layer, "shape").shape(); + else if (hasLayerAttr(layer, "_output_shapes")) + { + tensorflow::AttrValue_ListValue list = getLayerAttr(layer, "_output_shapes").list(); + if (list.shape_size()) + shape = list.shape()[0]; + } + if (shape.dim_size()) { - const tensorflow::TensorShapeProto& shape = getLayerAttr(layer, "shape").shape(); MatShape dims(shape.dim_size()); for (int i = 0; i < dims.size(); ++i) dims[i] = shape.dim(i).size(); @@ -1868,8 +1876,31 @@ void TFImporter::populateNet(Net dstNet) connect(layer_id, dstNet, parsePin(layer.input(1)), id, 0); data_layouts[name] = DATA_LAYOUT_UNKNOWN; } - else if (type == "ResizeNearestNeighbor" || type == "ResizeBilinear") + else if (type == "ResizeNearestNeighbor" || type == "ResizeBilinear" || type == "FusedResizeAndPadConv2D") { + std::string convWeights = ""; + if (type == "FusedResizeAndPadConv2D") + { + // input: "mul_1" + // input: "decoder/ResizeBilinear/size" + // input: "decoder/decoder_conv0/Conv2D_dummy_paddings" + // input: "decoder/decoder_conv0/weights" + CV_CheckEQ(layer.input_size(), 4, "Number of input for FusedResizeAndPadConv2D"); + + Mat paddings = getTensorContent(getConstBlob(layer, value_id, 2)); + CV_CheckEQ(countNonZero(paddings), 0, "Unsupported mode"); + + convWeights = layer.input(3); + layer.mutable_input()->DeleteSubrange(2, 2); + name = name + "/resize"; + + if (hasLayerAttr(layer, "resize_align_corners")) + { + layer.mutable_attr()->insert( + ::google::protobuf::MapPair("align_corners", + getLayerAttr(layer, "resize_align_corners"))); + } + } if (layer.input_size() == 2) { Mat outSize = getTensorContent(getConstBlob(layer, value_id, 1)); @@ -1901,6 +1932,17 @@ void TFImporter::populateNet(Net dstNet) layer_id[name] = id; connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); + + // Step back to add convolution + if (type == "FusedResizeAndPadConv2D") + { + tensorflow::NodeDef* conv = net.mutable_node(li); + conv->clear_input(); + conv->add_input(name); + conv->add_input(convWeights); + conv->set_op("Conv2D"); + li -= 1; + } } else if (type == "L2Normalize") { diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 8cacae8..4c32311 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -811,6 +811,11 @@ TEST_P(Test_TensorFlow_layers, resize_nearest_neighbor) runTensorFlowNet("keras_upsampling2d"); } +TEST_P(Test_TensorFlow_layers, fused_resize_conv) +{ + runTensorFlowNet("fused_resize_conv"); +} + TEST_P(Test_TensorFlow_layers, slice) { if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && -- 2.7.4