mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #28855 from omrope79:wechat-fix-layers
Add Prior Box Layer to support the WeChat QR model #28855 OpenCV extra: https://github.com/opencv/opencv_extra/pull/1349 ### Pull Request Readiness Checklist This PR is part 1 of the split from the original PR: WeChatQR-fix conversion Caffe to ONNX #28746. It focuses on adding the PriorBox layer and its related unit tests. The WeChatQR specific changes will be submitted in a separate PR. See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -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<bool>(params, "flip", 0, false, true);
|
||||
_clip = getParameter<bool>(params, "clip", 0, false, true);
|
||||
|
||||
@@ -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<int>("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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user