From a5696da9ecf5c90c230c1ad74e1b276eddb20c02 Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Thu, 30 Apr 2020 16:53:44 +0300 Subject: [PATCH] Merge pull request #17185 from l-bat:yolo_v4 * Support Yolov4 * Skip Mish on OpenVINO 2020.2 * Revert Mish * Refactoring --- modules/dnn/src/darknet/darknet_io.cpp | 18 ++++++++++++++---- modules/dnn/src/layers/region_layer.cpp | 17 ++++++++++++++--- modules/dnn/test/test_darknet_importer.cpp | 5 +++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/modules/dnn/src/darknet/darknet_io.cpp b/modules/dnn/src/darknet/darknet_io.cpp index ff322bc18878..405209c45886 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 e2a07336522f..d229369abbcf 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 @@ class RegionLayerImpl CV_FINAL : public RegionLayer 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 @@ class RegionLayerImpl CV_FINAL : public RegionLayer 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 @@ class RegionLayerImpl CV_FINAL : public RegionLayer 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 @@ class RegionLayerImpl CV_FINAL : public RegionLayer 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 @@ class RegionLayerImpl CV_FINAL : public RegionLayer 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 e76c16e27358..de5ff7f0c4f8 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");