diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index b3c3e014bd..9e232c440f 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -2170,7 +2170,10 @@ struct Net::Impl if (isAsync) CV_Error(Error::StsNotImplemented, "Default implementation fallbacks in asynchronous mode"); - CV_Assert(layer->supportBackend(DNN_BACKEND_OPENCV)); + if (!layer->supportBackend(DNN_BACKEND_OPENCV)) + CV_Error(Error::StsNotImplemented, format("Layer \"%s\" of type \"%s\" unsupported on OpenCV backend", + ld.name.c_str(), ld.type.c_str())); + if (preferableBackend == DNN_BACKEND_OPENCV && IS_DNN_OPENCL_TARGET(preferableTarget)) { std::vector umat_inputBlobs = OpenCLBackendWrapper::getUMatVector(ld.inputBlobsWrappers); diff --git a/modules/dnn/src/layers/layers_common.cpp b/modules/dnn/src/layers/layers_common.cpp index 2f5f486155..f119c12ac0 100644 --- a/modules/dnn/src/layers/layers_common.cpp +++ b/modules/dnn/src/layers/layers_common.cpp @@ -148,13 +148,12 @@ void getPoolingKernelParams(const LayerParams ¶ms, std::vector& kern std::vector& pads_begin, std::vector& pads_end, std::vector& strides, cv::String &padMode) { - util::getStrideAndPadding(params, pads_begin, pads_end, strides, padMode); - globalPooling = params.has("global_pooling") && params.get("global_pooling"); if (globalPooling) { + util::getStrideAndPadding(params, pads_begin, pads_end, strides, padMode); if(params.has("kernel_h") || params.has("kernel_w") || params.has("kernel_size")) { CV_Error(cv::Error::StsBadArg, "In global_pooling mode, kernel_size (or kernel_h and kernel_w) cannot be specified"); @@ -171,6 +170,7 @@ void getPoolingKernelParams(const LayerParams ¶ms, std::vector& kern else { util::getKernelSize(params, kernel); + util::getStrideAndPadding(params, pads_begin, pads_end, strides, padMode, kernel.size()); } } diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index c5745c9b8b..ddea2edda0 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -397,11 +397,33 @@ void ONNXImporter::populateNet(Net dstNet) layerParams.set("ceil_mode", layerParams.has("pad_mode")); layerParams.set("ave_pool_padded_area", framework_name == "pytorch"); } - else if (layer_type == "GlobalAveragePool" || layer_type == "GlobalMaxPool") + else if (layer_type == "GlobalAveragePool" || layer_type == "GlobalMaxPool" || layer_type == "ReduceMean") { + CV_Assert(node_proto.input_size() == 1); layerParams.type = "Pooling"; - layerParams.set("pool", layer_type == "GlobalAveragePool" ? "AVE" : "MAX"); - layerParams.set("global_pooling", true); + layerParams.set("pool", layer_type == "GlobalMaxPool"? "MAX" : "AVE"); + layerParams.set("global_pooling", layer_type == "GlobalAveragePool" || layer_type == "GlobalMaxPool"); + + if (layer_type == "ReduceMean") + { + if (layerParams.get("keepdims") == 0 || !layerParams.has("axes")) + CV_Error(Error::StsNotImplemented, "Unsupported mode of ReduceMean operation."); + + MatShape inpShape = outShapes[node_proto.input(0)]; + if (inpShape.size() != 4 && inpShape.size() != 5) + CV_Error(Error::StsNotImplemented, "Unsupported input shape of reduce_mean operation."); + + DictValue axes = layerParams.get("axes"); + CV_Assert(axes.size() <= inpShape.size() - 2); + std::vector kernel_size(inpShape.size() - 2, 1); + for (int i = 0; i < axes.size(); i++) { + int axis = axes.get(i); + CV_Assert_N(axis >= 2 + i, axis < inpShape.size()); + kernel_size[axis - 2] = inpShape[axis]; + } + + layerParams.set("kernel_size", DictValue::arrayInt(&kernel_size[0], kernel_size.size())); + } } else if (layer_type == "Slice") { @@ -747,11 +769,13 @@ void ONNXImporter::populateNet(Net dstNet) if (axes.size() != 1) CV_Error(Error::StsNotImplemented, "Multidimensional unsqueeze"); - int dims[] = {1, -1}; + MatShape inpShape = outShapes[node_proto.input(0)]; + int axis = axes.getIntValue(0); + CV_Assert(0 <= axis && axis <= inpShape.size()); + std::vector outShape = inpShape; + outShape.insert(outShape.begin() + axis, 1); layerParams.type = "Reshape"; - layerParams.set("axis", axes.getIntValue(0)); - layerParams.set("num_axes", 1); - layerParams.set("dim", DictValue::arrayInt(&dims[0], 2)); + layerParams.set("dim", DictValue::arrayInt(&outShape[0], outShape.size())); } else if (layer_type == "Reshape") { diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index ce77e867a2..aeceb9ac69 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -162,6 +162,18 @@ TEST_P(Test_ONNX_layers, Clip) testONNXModels("clip", npy); } +TEST_P(Test_ONNX_layers, ReduceMean) +{ + testONNXModels("reduce_mean"); +} + +TEST_P(Test_ONNX_layers, ReduceMean3D) +{ + if (target != DNN_TARGET_CPU) + throw SkipTestException("Only CPU is supported"); + testONNXModels("reduce_mean3d"); +} + TEST_P(Test_ONNX_layers, MaxPooling_Sigmoid) { testONNXModels("maxpooling_sigmoid"); diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 0357b8ecc5..8fcf81245a 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -350,11 +350,6 @@ TEST_P(Test_TensorFlow_layers, l2_normalize_3d) runTensorFlowNet("l2_normalize_3d"); } -TEST_P(Test_TensorFlow_layers, Split) -{ - runTensorFlowNet("split"); -} - class Test_TensorFlow_nets : public DNNTestLayer {}; TEST_P(Test_TensorFlow_nets, MobileNet_SSD) @@ -682,6 +677,9 @@ TEST_P(Test_TensorFlow_layers, lstm) TEST_P(Test_TensorFlow_layers, split) { + if (backend == DNN_BACKEND_INFERENCE_ENGINE) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_2); + runTensorFlowNet("split"); if (backend == DNN_BACKEND_INFERENCE_ENGINE) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE); runTensorFlowNet("split_equals");