diff --git a/modules/dnn/src/layers/nary_eltwise_layers.cpp b/modules/dnn/src/layers/nary_eltwise_layers.cpp index 975a45f566..d3fdf4e5f8 100644 --- a/modules/dnn/src/layers/nary_eltwise_layers.cpp +++ b/modules/dnn/src/layers/nary_eltwise_layers.cpp @@ -33,6 +33,7 @@ static int _mod(int x, int y) { } return res; } + } class NaryEltwiseHelper CV_FINAL @@ -361,12 +362,33 @@ public: } if (op == OPERATION::POW) { - /* - First input: exponent of Type T; - Second input: power of the exponent of Type T1; - Output: same type T as first input's. - */ - outputs.assign(1, inputs.front()); + CV_Assert(inputs.size() == 2); + auto isIntegerType = [](int t) { + return t == CV_8S || t == CV_8U || t == CV_16S || t == CV_16U || t == CV_32S || t == CV_32U || t == CV_64S || t == CV_64U; + }; + auto isFloatType = [](int t) { + return t == CV_32F || t == CV_64F || t == CV_16F || t == CV_16BF; + }; + + int out_type; + const bool baseIsInt = isIntegerType(inputs[0]); + const bool expIsInt = isIntegerType(inputs[1]); + const bool baseIsFloat = isFloatType(inputs[0]); + const bool expIsFloat = isFloatType(inputs[1]); + + if ((baseIsInt && expIsInt) || (baseIsFloat && expIsFloat)) + { + out_type = (inputs[0] == inputs[1]) ? inputs[0] : CV_32F; + } + else if (baseIsFloat != expIsFloat) + { + out_type = inputs[0]; + } + else + { + out_type = CV_32F; + } + outputs.assign(1, out_type); return; } @@ -766,8 +788,22 @@ public: return; } - int type_for_dispatch = op == OPERATION::WHERE ? outputs.front().type() : inputs.front().type(); - typeDispatch(type_for_dispatch, inputs.size(), inputs, outputs); + std::vector used_inputs = inputs; + if (op == OPERATION::POW) { + CV_Assert(used_inputs.size() == 2); + const int out_type = outputs[0].type(); + if (used_inputs[0].type() != out_type || used_inputs[1].type() != out_type) { + Mat a_conv, b_conv; + used_inputs[0].convertTo(a_conv, out_type); + used_inputs[1].convertTo(b_conv, out_type); + used_inputs = {a_conv, b_conv}; + helper.init(used_inputs, outputs); + CV_CheckTrue(helper.prepare_for_broadcast_op(), "NaryEltwiseLayer: Preparation for broadcasting failed"); + } + } + + int type_for_dispatch = (op == OPERATION::WHERE || op == OPERATION::POW) ? outputs.front().type() : used_inputs.front().type(); + typeDispatch(type_for_dispatch, used_inputs.size(), used_inputs, outputs); } template @@ -801,7 +837,7 @@ public: break; } case OPERATION::POW: { - auto pow = [] (const T& a, const T& b) { return std::pow(a, b); }; + auto pow = [] (const T& a, const T& b) { return saturate_cast(std::pow((double)a, (double)b)); }; binary_forward(pow, std::forward(args)..., 1e5); break; } @@ -944,6 +980,11 @@ public: op != OPERATION::OR && op != OPERATION::XOR); opDispatch(std::forward(args)...); break; + case CV_64F: + CV_Assert(op != OPERATION::BITSHIFT && op != OPERATION::AND && + op != OPERATION::OR && op != OPERATION::XOR); + opDispatch(std::forward(args)...); + break; case CV_16S: opDispatch(std::forward(args)...); break; diff --git a/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp index c220d7321f..9693aaf9f8 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp @@ -411,15 +411,15 @@ CASE(test_concat_3d_axis_negative_2) CASE(test_concat_3d_axis_negative_3) // no filter CASE(test_constant) - // no filter + SKIP; CASE(test_constant_pad) - // no filter + SKIP; CASE(test_constantofshape_float_ones) - // no filter + SKIP; CASE(test_constantofshape_int_shape_zero) // no filter CASE(test_constantofshape_int_zeros) - // no filter + SKIP; CASE(test_conv_with_autopad_same) #if SKIP_SET_1 SKIP_MYRIAD; @@ -547,7 +547,7 @@ CASE(test_dynamicquantizelinear_min_adjusted) CASE(test_dynamicquantizelinear_min_adjusted_expanded) // no filter CASE(test_edge_pad) - // no filter + SKIP; CASE(test_einsum_batch_diagonal) SKIP; CASE(test_hardmax_axis_0) @@ -911,13 +911,13 @@ CASE(test_lrn) CASE(test_lrn_default) // no filter CASE(test_lstm_batchwise) - // no filter + SKIP; CASE(test_lstm_defaults) - // no filter + SKIP; CASE(test_lstm_with_initial_bias) - // no filter + SKIP; CASE(test_lstm_with_peepholes) - // no filter + SKIP; CASE(test_matmul_2d) // no filter CASE(test_matmul_3d) @@ -1266,23 +1266,23 @@ CASE(test_pow_bcast_scalar) CASE(test_pow_example) // no filter CASE(test_pow_types_float) - // no filter + SKIP; CASE(test_pow_types_float32_int32) - // no filter + SKIP; CASE(test_pow_types_float32_int64) - // no filter + SKIP; CASE(test_pow_types_float32_uint32) - // no filter + SKIP; CASE(test_pow_types_float32_uint64) - // no filter + SKIP; CASE(test_pow_types_int) - // no filter + SKIP; CASE(test_pow_types_int32_float32) - // no filter + SKIP; CASE(test_pow_types_int32_int32) - // no filter + SKIP; CASE(test_pow_types_int64_float32) - // no filter + SKIP; CASE(test_pow_types_int64_int64) SKIP; CASE(test_prelu_broadcast) @@ -1560,7 +1560,7 @@ CASE(test_reduce_sum_square_negative_axes_keepdims_random) } #endif CASE(test_reflect_pad) - // no filter + SKIP; CASE(test_relu) // no filter CASE(test_reshape_allowzero_reordered) diff --git a/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp index 263b3169ee..38fb2d7b32 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp @@ -120,3 +120,22 @@ "test_gridsample_reflection_padding", "test_gridsample_zeros_padding", "test_gridsample_nearest", +"test_edge_pad", +"test_lstm_batchwise", +"test_lstm_defaults", +"test_lstm_with_initial_bias", +"test_lstm_with_peepholes", +"test_pow_types_float", +"test_pow_types_float32_int32", +"test_pow_types_float32_int64", +"test_pow_types_float32_uint32", +"test_pow_types_float32_uint64", +"test_pow_types_int", +"test_pow_types_int32_float32", +"test_pow_types_int32_int32", +"test_pow_types_int64_float32", +"test_reflect_pad", +"test_constant", +"test_constant_pad", +"test_constantofshape_float_ones", +"test_constantofshape_int_zeros", 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 d79d5e32cf..ddfb3c8aa3 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 @@ -44,11 +44,7 @@ "test_compress_1", // ---- same as above --- "test_compress_default_axis", // ---- same as above --- "test_compress_negative_axis", // ---- same as above --- -"test_constant", // Issue::Wrong output -"test_constant_pad", // Issue:: Unkonwn error -"test_constantofshape_float_ones", // Issue::Parser::Weights are required as inputs "test_constantofshape_int_shape_zero", // Issue::Parser::Weights are required as inputs -"test_constantofshape_int_zeros", // Issue::Parser::Weights are required as inputs "test_convinteger_with_padding", // Issues::Layer::Can't create layer "onnx_node_output_0!y" of type "ConvInteger" in function 'getLayerInstance' "test_convinteger_without_padding", //Issues::Layer::Can't create layer "onnx_node_output_0!y" of type "ConvInteger" in function 'getLayerInstance' "test_convtranspose", // Issue::Parser::Weights are required as inputs @@ -69,7 +65,6 @@ "test_dynamicquantizelinear_max_adjusted_expanded", // ---- same as above --- "test_dynamicquantizelinear_min_adjusted", // ---- same as above --- "test_dynamicquantizelinear_min_adjusted_expanded", // ---- same as above --- -"test_edge_pad", // Issue::Parser::Weights are required as inputs "test_einsum_inner_prod", // Issue::Output shape does not match with reference "test_elu_default_expanded_ver18", "test_elu_example_expanded_ver18", @@ -93,10 +88,6 @@ "test_loop11", // Issue::'Graph' is not supported in function 'getLayerParams' "test_loop13_seq", // Issue::typeProto.has_tensor_type() in function 'populateNet' "test_loop16_seq_none", // Issue::Failed to allocate 179812654996800 bytes in function 'OutOfMemoryError' -"test_lstm_batchwise", // Issues::Parser:: !name.empty() && constBlobs.count(name) == 1 in function 'parseLSTM' -"test_lstm_defaults", // ---- same as above --- -"test_lstm_with_initial_bias", // ---- same as above --- -"test_lstm_with_peepholes", // ---- same as above --- "test_matmulinteger", // Issues::Layer does not exist. Can't create layer "onnx_node_output_0!Y" of type "MatMulInteger" in function 'getLayerInstance' "test_momentum", // Issues::Layer does not exist. Can't create layer "onnx_node_output_0!X1_new" of type "ai.onnx.preview.training.Momentum" in function 'getLayerInstance' "test_momentum_multiple", // ---- same as above --- @@ -150,15 +141,6 @@ "test_optional_get_element_sequence", // ---- same as above --- "test_optional_has_element", // Issue::typeProto.has_tensor_type() in function 'populateNet' "test_optional_has_element_empty", // ---- same as above --- -"test_pow_types_float", // Issue:: Unsupported data type -"test_pow_types_float32_int32", // ---- same as above --- -"test_pow_types_float32_int64", // ---- same as above --- -"test_pow_types_float32_uint32", // ---- same as above --- -"test_pow_types_float32_uint64", // ---- same as above --- -"test_pow_types_int", // Issue:: Unsupported data type -"test_pow_types_int32_float32", // ---- same as above --- -"test_pow_types_int32_int32", // ---- same as above --- -"test_pow_types_int64_float32", // ---- same as above --- "test_prelu_broadcast", // Issue::Parser:Blob slope not found in const blobs in function 'getBlob' (weights are required as inputs) "test_prelu_example", // ---- same as above --- "test_qlinearconv", // Issue::Parser: Blob x_scale not found in const blobs in function 'getBlob' (weights are required as inputs) @@ -176,7 +158,6 @@ "test_reduce_sum_keepdims_random", // ---- same as above --- "test_reduce_sum_negative_axes_keepdims_example", "test_reduce_sum_negative_axes_keepdims_random", // ---- same as above --- -"test_reflect_pad", // Issue:: Parser: Blob shape not found in const blobs in function 'getBlob' (weights are required as inputs) "test_reshape_allowzero_reordered", // incompatible type of input tensor #0 'data': CV_8UC1 given, CV_32FC1 expected in function 'setGraphInput' "test_resize_downsample_scales_cubic", // Issue:: Parser: layer_id.find(node_proto.input(i)) == layer_id.end() in function 'parseResize' "test_resize_downsample_scales_cubic_A_n0p5_exclude_outside", // ---- same as above ---