diff --git a/modules/dnn/src/layers/tile_layer.cpp b/modules/dnn/src/layers/tile_layer.cpp index 09d4511a8d..7b8d97089a 100644 --- a/modules/dnn/src/layers/tile_layer.cpp +++ b/modules/dnn/src/layers/tile_layer.cpp @@ -42,14 +42,20 @@ public: CV_CheckEQ(inputs.size(), 1ull, "Tile: one input is expected"); // repeats must have the same length as input's dimension number - // FIXIT: it breaks when the input is 1d tensor (represented as 2d mat with size=2 in opencv dnn) - CV_CheckEQ(inputs[0].size(), repeats.size(), "Tile: repeats must be a 1D tensor of the same length as input's dimension number"); - - outputs.assign(1, inputs[0]); - for (int i = 0; i < repeats.size(); i++) - { - outputs[0][i] *= repeats[i]; + if (inputs[0].size() > 1) { + CV_CheckEQ(inputs[0].size(), repeats.size(), "Tile: repeats must be a 1D tensor of the same length as input's dimension number"); + outputs.assign(1, inputs[0]); + for (int i = 0; i < repeats.size(); i++) + { + outputs[0][i] *= repeats[i]; + } + } else { + CV_CheckGE((int)repeats.size(), 1, "Tile: Provide at least one repeat along any dimension"); + outputs.assign(1, repeats); + if (inputs[0].size() == 1) + outputs[0][repeats.size() - 1] *= inputs[0][0]; } + return false; } @@ -79,18 +85,26 @@ public: MatShape out_shape = shape(out); int rep_i, ndims = data.dims; int dims = 1; - for (int i = 0; i < ndims; i++) - { - rep_i = repeats[i]; - if (rep_i != 1) + if (ndims > 1){ + for (int i = 0; i < ndims; i++) { - tmp = tmp.reshape(0, dims); - tmp = cv::repeat(tmp, 1, rep_i); + rep_i = repeats[i]; + if (rep_i != 1) + { + tmp = tmp.reshape(0, dims); + tmp = cv::repeat(tmp, 1, rep_i); + } + dims *= out_shape[i]; } - dims *= out_shape[i]; + tmp = tmp.reshape(0, out_shape); + } else { + for (int i = 0; i < repeats.size(); i++){ + tmp = tmp.reshape(0, dims); + tmp = cv::repeat(tmp, repeats[i], 1); + dims *= out_shape[i]; + } + tmp = tmp.reshape(0, out_shape); } - tmp = tmp.reshape(0, out_shape); - tmp.copyTo(out); } diff --git a/modules/dnn/test/test_layers_1d.cpp b/modules/dnn/test/test_layers_1d.cpp index 308d8f38a4..6e826ba1ce 100644 --- a/modules/dnn/test/test_layers_1d.cpp +++ b/modules/dnn/test/test_layers_1d.cpp @@ -682,6 +682,48 @@ INSTANTIATE_TEST_CASE_P(/*nothing*/, Layer_Const_Test, testing::Values( std::vector({4, 1}) )); +typedef testing::TestWithParam> Layer_Tile_Test; +TEST_P(Layer_Tile_Test, Accuracy_01D){ + + std::vector input_shape = GetParam(); + std::vector repeats = {2, 2}; + + LayerParams lp; + lp.type = "Tile"; + lp.name = "TileLayer"; + lp.set("repeats", DictValue::arrayInt(repeats.data(), repeats.size())); + Ptr layer = TileLayer::create(lp); + + cv::Mat input = cv::Mat(input_shape.size(), input_shape.data(), CV_32F); + cv::randn(input, 0, 1); + + std::vector inputs{input}; + std::vector outputs; + + runLayer(layer, inputs, outputs); + + // Manually create the expected output for verification + cv::Mat output_ref = input.clone(); + for (int i = 0; i < repeats.size(); ++i) { + cv::Mat tmp; + cv::repeat(output_ref, (i == 0 ? repeats[i] : 1), (i == 1 ? repeats[i] : 1), tmp); + output_ref = tmp; + } + + ASSERT_EQ(outputs.size(), 1); + ASSERT_EQ(shape(outputs[0]), shape(output_ref)); + normAssert(output_ref, outputs[0]); + +} +INSTANTIATE_TEST_CASE_P(/*nothing*/, Layer_Tile_Test, +/*input blob shape*/ testing::Values( + std::vector({}), + std::vector({2}), + std::vector({2, 1}), + std::vector({1, 2}), + std::vector({2, 2}) + )); + typedef testing::TestWithParam, std::string>> Layer_Einsum_Test; TEST_P(Layer_Einsum_Test, Accuracy_01D) {