diff --git a/modules/dnn/src/layers/prior_box_layer.cpp b/modules/dnn/src/layers/prior_box_layer.cpp index 1c5dd59ef3..967aa7d1fa 100644 --- a/modules/dnn/src/layers/prior_box_layer.cpp +++ b/modules/dnn/src/layers/prior_box_layer.cpp @@ -192,8 +192,23 @@ public: } } - PriorBoxLayerImpl(const LayerParams ¶ms) + static LayerParams normalizeONNXParams(const LayerParams& params) { + LayerParams p = params; + auto remap = [&](const std::string& from, const std::string& to) { + if (p.has(from) && !p.has(to)) + p.set(to, p.get(from)); + }; + remap("variances", "variance"); + remap("min_sizes", "min_size"); + remap("max_sizes", "max_size"); + remap("aspect_ratios", "aspect_ratio"); + return p; + } + + PriorBoxLayerImpl(const LayerParams ¶ms_) + { + const LayerParams params = normalizeONNXParams(params_); setParamsFrom(params); _flip = getParameter(params, "flip", 0, false, true); _clip = getParameter(params, "clip", 0, false, true); diff --git a/modules/dnn/src/onnx/onnx_importer2.cpp b/modules/dnn/src/onnx/onnx_importer2.cpp index acbd1d4c85..0dde754496 100644 --- a/modules/dnn/src/onnx/onnx_importer2.cpp +++ b/modules/dnn/src/onnx/onnx_importer2.cpp @@ -189,6 +189,7 @@ protected: void parseCumSum (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseDepthSpaceOps (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseDetectionOutput (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); + void parsePriorBox (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseEinsum (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseElementWise (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseElu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); @@ -1913,6 +1914,17 @@ void ONNXImporter2::parseSoftMax(LayerParams& layerParams, const opencv_onnx::No void ONNXImporter2::parseDetectionOutput(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto) { CV_CheckEQ(node_proto.input_size(), 3, ""); + if (layerParams.has("code_type")) + { + int ct = layerParams.get("code_type"); + layerParams.set("code_type", ct == 2 ? "CENTER_SIZE" : "CORNER"); + } + addLayer(layerParams, node_proto); +} + +void ONNXImporter2::parsePriorBox(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto) +{ + layerParams.type = "PriorBox"; addLayer(layerParams, node_proto); } @@ -2759,6 +2771,7 @@ void ONNXImporter2::buildDispatchMap_ONNX_AI() dispatch["NonMaxSuprression"] = &ONNXImporter2::parseNonMaxSuprression; dispatch["SoftMax"] = dispatch["Softmax"] = dispatch["LogSoftmax"] = &ONNXImporter2::parseSoftMax; dispatch["DetectionOutput"] = &ONNXImporter2::parseDetectionOutput; + dispatch["PriorBox"] = &ONNXImporter2::parsePriorBox; dispatch["CumSum"] = &ONNXImporter2::parseCumSum; dispatch["SpaceToDepth"] = dispatch["DepthToSpace"] = &ONNXImporter2::parseDepthSpaceOps; dispatch["ScatterElements"] = dispatch["Scatter"] = dispatch["ScatterND"] = &ONNXImporter2::parseScatter; diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 6f2687842d..29fcc27160 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -1179,6 +1179,11 @@ TEST_P(Test_ONNX_layers, Resize_HumanSeg) testONNXModels("resize_humanseg"); } +TEST_P(Test_ONNX_layers, Resample) +{ + testONNXModels("nearest", npy, 0, 0, false, false); +} + TEST_P(Test_ONNX_layers, Div) { const String model = _tf("models/div.onnx"); @@ -2293,6 +2298,31 @@ TEST_P(Test_ONNX_layers, QLinearSoftmax) testONNXModels("qlinearsoftmax_v13", npy, 0.002, 0.002); } +TEST_P(Test_ONNX_layers, PriorBox_ONNX) +{ + Net net = readNetFromONNX(_tf("models/prior_box.onnx")); + ASSERT_FALSE(net.empty()); + int inp_size[] = {1, 3, 10, 10}; + int shape_size[] = {1, 2, 3, 4}; + Mat inp(4, inp_size, CV_32F, Scalar(0)); + Mat shape(4, shape_size, CV_32F, Scalar(0)); + net.setInput(inp, "input_0"); + net.setInput(shape, "input_1"); + net.setPreferableBackend(backend); + net.setPreferableTarget(target); + Mat out = net.forward(); + Mat ref = blobFromNPY(_tf("data/output_prior_box.npy")); + + double l1 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-5; + double lInf = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1e-3 : 1e-4; + if (target == DNN_TARGET_CUDA_FP16) + { + l1 = 7e-5; + lInf = 0.0005; + } + normAssert(out, ref, "", l1, lInf); +} + INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_ONNX_layers, dnnBackendsAndTargets()); class Test_ONNX_nets : public Test_ONNX_layers