diff --git a/modules/dnn/src/darknet/darknet_io.cpp b/modules/dnn/src/darknet/darknet_io.cpp index 664a1d617b..f6504b96c7 100644 --- a/modules/dnn/src/darknet/darknet_io.cpp +++ b/modules/dnn/src/darknet/darknet_io.cpp @@ -363,6 +363,28 @@ namespace cv { fused_layer_names.push_back(last_layer); } + void setSlice(int input_index, int split_size, int group_id) + { + int begin[] = {0, split_size * group_id, 0, 0}; + cv::dnn::DictValue paramBegin = cv::dnn::DictValue::arrayInt(begin, 4); + + int end[] = {-1, begin[1] + split_size, -1, -1}; + cv::dnn::DictValue paramEnd = cv::dnn::DictValue::arrayInt(end, 4); + + darknet::LayerParameter lp; + lp.layer_name = cv::format("slice_%d", layer_id); + lp.layer_type = "Slice"; + lp.layerParams.set("begin", paramBegin); + lp.layerParams.set("end", paramEnd); + + lp.bottom_indexes.push_back(fused_layer_names.at(input_index)); + net->layers.push_back(lp); + + layer_id++; + last_layer = lp.layer_name; + fused_layer_names.push_back(last_layer); + } + void setReorg(int stride) { cv::dnn::LayerParams reorg_params; @@ -717,6 +739,7 @@ namespace cv { { std::string bottom_layers = getParam(layer_params, "layers", ""); CV_Assert(!bottom_layers.empty()); + int groups = getParam(layer_params, "groups", 1); std::vector layers_vec = getNumbers(bottom_layers); tensor_shape[0] = 0; @@ -725,10 +748,31 @@ namespace cv { tensor_shape[0] += net->out_channels_vec[layers_vec[k]]; } - if (layers_vec.size() == 1) - setParams.setIdentity(layers_vec.at(0)); + if (groups > 1) + { + int group_id = getParam(layer_params, "group_id", 0); + tensor_shape[0] /= groups; + int split_size = tensor_shape[0] / layers_vec.size(); + for (size_t k = 0; k < layers_vec.size(); ++k) + setParams.setSlice(layers_vec[k], split_size, group_id); + + if (layers_vec.size() > 1) + { + // layer ids in layers_vec - inputs of Slice layers + // after adding offset to layers_vec: layer ids - ouputs of Slice layers + for (size_t k = 0; k < layers_vec.size(); ++k) + layers_vec[k] += layers_vec.size(); + + setParams.setConcat(layers_vec.size(), layers_vec.data()); + } + } else - setParams.setConcat(layers_vec.size(), layers_vec.data()); + { + if (layers_vec.size() == 1) + setParams.setIdentity(layers_vec.at(0)); + else + setParams.setConcat(layers_vec.size(), layers_vec.data()); + } } else if (layer_type == "dropout" || layer_type == "cost") { diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 607761ed2f..fcc9088b00 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -627,6 +627,12 @@ TEST_P(Test_Darknet_layers, reorg) testDarknetLayer("reorg"); } +TEST_P(Test_Darknet_layers, route) +{ + testDarknetLayer("route"); + testDarknetLayer("route_multi"); +} + TEST_P(Test_Darknet_layers, maxpool) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2020020000)