diff --git a/modules/dnn/src/darknet/darknet_io.cpp b/modules/dnn/src/darknet/darknet_io.cpp index ff322bc188..405209c458 100644 --- a/modules/dnn/src/darknet/darknet_io.cpp +++ b/modules/dnn/src/darknet/darknet_io.cpp @@ -229,6 +229,10 @@ namespace cv { { activation_param.type = "Swish"; } + else if (type == "mish") + { + activation_param.type = "Mish"; + } else if (type == "logistic") { activation_param.type = "Sigmoid"; @@ -436,7 +440,7 @@ namespace cv { fused_layer_names.push_back(last_layer); } - void setYolo(int classes, const std::vector& mask, const std::vector& anchors, float thresh, float nms_threshold) + void setYolo(int classes, const std::vector& mask, const std::vector& anchors, float thresh, float nms_threshold, float scale_x_y) { cv::dnn::LayerParams region_param; region_param.name = "Region-name"; @@ -449,6 +453,7 @@ namespace cv { region_param.set("logistic", true); region_param.set("thresh", thresh); region_param.set("nms_threshold", nms_threshold); + region_param.set("scale_x_y", scale_x_y); std::vector usedAnchors(numAnchors * 2); for (int i = 0; i < numAnchors; ++i) @@ -786,6 +791,7 @@ namespace cv { int num_of_anchors = getParam(layer_params, "num", -1); float thresh = getParam(layer_params, "thresh", 0.2); float nms_threshold = getParam(layer_params, "nms_threshold", 0.4); + float scale_x_y = getParam(layer_params, "scale_x_y", 1.0); std::string anchors_values = getParam(layer_params, "anchors", std::string()); CV_Assert(!anchors_values.empty()); @@ -798,7 +804,7 @@ namespace cv { CV_Assert(classes > 0 && num_of_anchors > 0 && (num_of_anchors * 2) == anchors_vec.size()); setParams.setPermute(false); - setParams.setYolo(classes, mask_vec, anchors_vec, thresh, nms_threshold); + setParams.setYolo(classes, mask_vec, anchors_vec, thresh, nms_threshold, scale_x_y); } else { CV_Error(cv::Error::StsParseError, "Unknown layer type: " + layer_type); @@ -813,6 +819,10 @@ namespace cv { { setParams.setActivation("swish"); } + else if (activation == "mish") + { + setParams.setActivation("mish"); + } else if (activation == "logistic") { setParams.setActivation("logistic"); @@ -935,8 +945,8 @@ namespace cv { } std::string activation = getParam(layer_params, "activation", "linear"); - if(activation == "leaky" || activation == "swish" || activation == "logistic") - ++cv_layers_counter; // For ReLU, Swish, Sigmoid + if(activation == "leaky" || activation == "swish" || activation == "mish" || activation == "logistic") + ++cv_layers_counter; // For ReLU, Swish, Mish, Sigmoid if(!darknet_layers_counter) tensor_shape.resize(1); diff --git a/modules/dnn/src/layers/region_layer.cpp b/modules/dnn/src/layers/region_layer.cpp index e2a0733652..d229369abb 100644 --- a/modules/dnn/src/layers/region_layer.cpp +++ b/modules/dnn/src/layers/region_layer.cpp @@ -63,7 +63,7 @@ class RegionLayerImpl CV_FINAL : public RegionLayer { public: int coords, classes, anchors, classfix; - float thresh, nmsThreshold; + float thresh, nmsThreshold, scale_x_y; bool useSoftmax, useLogistic; #ifdef HAVE_OPENCL UMat blob_umat; @@ -82,6 +82,7 @@ public: useSoftmax = params.get("softmax", false); useLogistic = params.get("logistic", false); nmsThreshold = params.get("nms_threshold", 0.4); + scale_x_y = params.get("scale_x_y", 1.0); // Yolov4 CV_Assert(nmsThreshold >= 0.); CV_Assert(coords == 4); @@ -292,8 +293,10 @@ public: if (classfix == -1 && scale < .5) scale = 0; // if(t0 < 0.5) t0 = 0; int box_index = index_sample_offset + index * cell_size; - dstData[box_index + 0] = (x + logistic_activate(srcData[box_index + 0])) / cols; - dstData[box_index + 1] = (y + logistic_activate(srcData[box_index + 1])) / rows; + float x_tmp = (logistic_activate(srcData[box_index + 0]) - 0.5f) * scale_x_y + 0.5f; + float y_tmp = (logistic_activate(srcData[box_index + 1]) - 0.5f) * scale_x_y + 0.5f; + dstData[box_index + 0] = (x + x_tmp) / cols; + dstData[box_index + 1] = (y + y_tmp) / rows; dstData[box_index + 2] = exp(srcData[box_index + 2]) * biasData[2 * a] / wNorm; dstData[box_index + 3] = exp(srcData[box_index + 3]) * biasData[2 * a + 1] / hNorm; @@ -406,6 +409,8 @@ public: auto shape_3d = std::make_shared(ngraph::element::i64, ngraph::Shape{boxes_shape.size()}, boxes_shape.data()); ngraph::Shape box_broad_shape{1, (size_t)anchors, (size_t)h, (size_t)w}; + auto scale_x_y_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, &scale_x_y); + auto shift_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, std::vector{0.5}); std::shared_ptr box_x; { @@ -413,6 +418,9 @@ public: auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, cols}); box_x = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); box_x = std::make_shared(box_x); + box_x = std::make_shared(box_x, shift_node, ngraph::op::AutoBroadcastType::NUMPY); + box_x = std::make_shared(box_x, scale_x_y_node, ngraph::op::AutoBroadcastType::NUMPY); + box_x = std::make_shared(box_x, shift_node, ngraph::op::AutoBroadcastType::NUMPY); box_x = std::make_shared(box_x, shape_3d, true); std::vector x_indices(w * h * anchors); @@ -439,6 +447,9 @@ public: auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{2, cols}); box_y = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); box_y = std::make_shared(box_y); + box_y = std::make_shared(box_y, shift_node, ngraph::op::AutoBroadcastType::NUMPY); + box_y = std::make_shared(box_y, scale_x_y_node, ngraph::op::AutoBroadcastType::NUMPY); + box_y = std::make_shared(box_y, shift_node, ngraph::op::AutoBroadcastType::NUMPY); box_y = std::make_shared(box_y, shape_3d, true); std::vector y_indices(h * anchors); diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index e76c16e273..de5ff7f0c4 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -523,6 +523,11 @@ TEST_P(Test_Darknet_layers, upsample) testDarknetLayer("upsample"); } +TEST_P(Test_Darknet_layers, mish) +{ + testDarknetLayer("mish", true); +} + TEST_P(Test_Darknet_layers, avgpool_softmax) { testDarknetLayer("avgpool_softmax");