1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge pull request #25779 from fengyuentau:dnn/fix_onnx_depthtospace

dnn: add DepthToSpace and SpaceToDepth #25779

We are working on updating WeChat QRCode module. One of the new models is a fully convolutional model and hence it should be able to run with different input shapes. However,  it has an operator `DepthToSpace`, which is parsed as a subgraph of `Reshape -> Permute -> Reshape` with a fixed shape getting during parsing. The subgraph itself is not a problem, but the true problem is the subgraph with a fixed input and output shape regardless input changes. This does not allow the model to run with different input shapes.

Solution is to add a dedicated layer for DepthtoSpace and SpaceToDepth.

Backend support:

- [x] CPU
- [x] CUDA
- [x] OpenCL
- [x] OpenVINO
- [x] CANN
- [x] TIMVX
-  ~Vulkan~ (missing fundamental tools, like permutation and reshape)

### Pull Request Readiness Checklist

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:
Yuantao Feng
2024-06-22 00:28:22 +08:00
committed by GitHub
parent acd16e384f
commit 3f13ce797b
8 changed files with 663 additions and 95 deletions
+55
View File
@@ -509,6 +509,61 @@ TEST_P(Test_Int8_layers, Eltwise)
testLayer("split_max", "ONNX", 0.004, 0.012);
}
TEST_P(Test_Int8_layers, DepthSpaceOps) {
auto test_layer_with_onnx_conformance_models = [&](const std::string &model_name, double l1, double lInf) {
std::string model_path = _tf("onnx/conformance/node/test_" + model_name + "/model.onnx");
auto net = readNet(model_path);
// load reference inputs and outputs
std::string data_base_path = _tf("onnx/conformance/node/test_" + model_name + "/test_data_set_0");
Mat input = readTensorFromONNX(data_base_path + "/input_0.pb");
Mat ref_output = readTensorFromONNX(data_base_path + "/output_0.pb");
std::vector<float> input_scales, output_scales;
std::vector<int> input_zeropoints, output_zeropoints;
auto qnet = net.quantize(std::vector<Mat>{input}, CV_8S, CV_8S, false);
qnet.getInputDetails(input_scales, input_zeropoints);
qnet.getOutputDetails(output_scales, output_zeropoints);
qnet.setPreferableBackend(backend);
qnet.setPreferableTarget(target);
Mat quantized_input, quantized_output;
input.convertTo(quantized_input, CV_8S, 1.f / input_scales.front(), input_zeropoints.front());
qnet.setInput(quantized_input);
quantized_output = qnet.forward();
Mat output;
quantized_output.convertTo(output, CV_32F, output_scales.front(), -(output_scales.front() * output_zeropoints.front()));
normAssert(ref_output, output, model_name.c_str(), l1, lInf);
};
double l1 = default_l1, lInf = default_lInf;
{
l1 = 0.001; lInf = 0.002;
if (backend == DNN_BACKEND_TIMVX) { l1 = 0.001; lInf = 0.002; }
test_layer_with_onnx_conformance_models("spacetodepth", l1, lInf);
}
{
l1 = 0.022; lInf = 0.044;
if (backend == DNN_BACKEND_TIMVX) { l1 = 0.022; lInf = 0.044; }
test_layer_with_onnx_conformance_models("spacetodepth_example", l1, lInf);
}
{
l1 = 0.001; lInf = 0.002;
if (backend == DNN_BACKEND_TIMVX) { l1 = 0.24; lInf = 0.99; }
test_layer_with_onnx_conformance_models("depthtospace_crd_mode", l1, lInf);
}
test_layer_with_onnx_conformance_models("depthtospace_dcr_mode", 0.001, 0.002);
test_layer_with_onnx_conformance_models("depthtospace_example", 0.07, 0.14);
{
l1 = 0.07; lInf = 0.14;
if (backend == DNN_BACKEND_TIMVX) // diff too huge, l1 = 13.6; lInf = 27.2
applyTestTag(CV_TEST_TAG_DNN_SKIP_TIMVX);
test_layer_with_onnx_conformance_models("depthtospace_crd_mode_example", l1, lInf);
}
}
INSTANTIATE_TEST_CASE_P(/**/, Test_Int8_layers, dnnBackendsAndTargetsInt8());
class Test_Int8_nets : public DNNTestLayer