From: Zihao Mu Date: Fri, 29 Apr 2022 02:17:02 +0000 (+0800) Subject: parsing depth2space and space2depth of ONNX importer X-Git-Tag: accepted/tizen/unified/20230127.161057~1^2~291^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=64ded50bbf28c0a37a2c0695ae87b0fc08014403;p=platform%2Fupstream%2Fopencv.git parsing depth2space and space2depth of ONNX importer --- diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index 2a440a1..0016061 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -175,6 +175,7 @@ private: void parseSoftMax (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseDetectionOutput (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseCumSum (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); + void parseDepthToSpace (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); void parseSimpleLayers (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto); // Domain: com.microsoft @@ -3183,6 +3184,85 @@ void ONNXImporter::parseCumSum(LayerParams& layerParams, const opencv_onnx::Node addLayer(layerParams, node_proto); } +void ONNXImporter::parseDepthToSpace(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_) +{ + // We parse "DepthToSpace" and "SpaceToDepth" in this function. + opencv_onnx::NodeProto node_proto = node_proto_; + const std::string& layer_type = node_proto.op_type(); + CV_Assert(layer_type == "DepthToSpace" || layer_type == "SpaceToDepth"); + + // Get blocksize + CV_Assert(layerParams.has("blocksize")); + int blocksize = layerParams.get("blocksize"); + CV_Assert(blocksize > 0); + + // Get mode, only for "DepthToSpace" + std::string modeType = layerParams.get("mode", "DCR"); + + MatShape inpShape = outShapes[node_proto.input(0)]; + CV_Assert(inpShape.size() == 4); + int N = inpShape[0], C = inpShape[1], H = inpShape[2], W = inpShape[3]; + + // Implement DepthToSpace and SpaceToDepth by the Reshape and Permute layer. + std::array shape0, perm; + std::array shape1; + + if (layer_type == "DepthToSpace") + { + if (modeType == "DCR") + { + shape0 = {N, blocksize, blocksize, C/(blocksize * blocksize), H, W}; + perm = {0, 3, 4, 1, 5, 2}; + shape1 = {N, C/(blocksize * blocksize), H * blocksize, W * blocksize}; + } + else if (modeType == "CRD") + { + shape0 = {N, C/(blocksize * blocksize), blocksize, blocksize, H, W}; + perm = {0, 1, 4, 2, 5, 3}; + shape1 = {N, C/(blocksize * blocksize), H * blocksize, W * blocksize}; + } + else + CV_Error(Error::StsNotImplemented, "The mode of " + modeType + " in " + layer_type + " Layer is not supported"); + } + else // SpaceToDepth + { + shape0 = {N, C, H/blocksize, blocksize, W/blocksize, blocksize}; + perm = {0, 3, 5, 1, 2, 4}; + shape1 = {N, C * blocksize * blocksize, H/blocksize, W/blocksize}; + } + + // Step1: Reshape + LayerParams reshapeLp; + reshapeLp.name = layerParams.name + "/reshape"; + reshapeLp.type = "Reshape"; + CV_Assert(layer_id.find(reshapeLp.name) == layer_id.end()); + reshapeLp.set("dim", DictValue::arrayInt(shape0.data(), shape0.size())); + + opencv_onnx::NodeProto protoReshape; + protoReshape.add_input(node_proto.input(0)); + protoReshape.add_output(reshapeLp.name); + addLayer(reshapeLp, protoReshape); + + // Step2: Transpose + LayerParams permuteLp; + permuteLp.name = layerParams.name + "/permute"; + permuteLp.type = "Permute"; + CV_Assert(layer_id.find(permuteLp.name) == layer_id.end()); + permuteLp.set("order", DictValue::arrayInt(perm.data(), perm.size())); + + opencv_onnx::NodeProto protoPermute; + protoPermute.add_input(reshapeLp.name); + protoPermute.add_output(permuteLp.name); + addLayer(permuteLp, protoPermute); + + // Step3: Reshape + layerParams.type = "Reshape"; + layerParams.set("dim", DictValue::arrayInt(shape1.data(), shape1.size())); + + node_proto.set_input(0, permuteLp.name); + addLayer(layerParams, node_proto); +} + void ONNXImporter::parseSimpleLayers(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto) { for (int j = 0; j < node_proto.input_size(); j++) { @@ -3672,6 +3752,7 @@ void ONNXImporter::buildDispatchMap_ONNX_AI(int opset_version) dispatch["SoftMax"] = dispatch["LogSoftmax"] = &ONNXImporter::parseSoftMax; dispatch["DetectionOutput"] = &ONNXImporter::parseDetectionOutput; dispatch["CumSum"] = &ONNXImporter::parseCumSum; + dispatch["SpaceToDepth"] = dispatch["DepthToSpace"] = &ONNXImporter::parseDepthToSpace; std::vector simpleLayers{"Acos", "Acosh", "Asin", "Asinh", "Atan", "Atanh", "Ceil", "Celu", "Cos", "Cosh", "Dropout", "Erf", "Exp", "Floor", "HardSigmoid", "HardSwish", diff --git a/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp index 49db810..1437e54 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp @@ -96,10 +96,6 @@ "test_cumsum_2d_axis_0", "test_cumsum_2d_axis_1", "test_cumsum_2d_negative_axis", -"test_depthtospace_crd_mode", -"test_depthtospace_crd_mode_example", -"test_depthtospace_dcr_mode", -"test_depthtospace_example", "test_dequantizelinear", "test_dequantizelinear_axis", "test_det_2d", @@ -490,8 +486,6 @@ "test_slice_neg_steps", "test_slice_negative_axes", "test_slice_start_out_of_bounds", -"test_spacetodepth", -"test_spacetodepth_example", "test_split_variable_parts_1d", "test_split_variable_parts_2d", "test_split_variable_parts_default_axis",