diff --git a/modules/dnn/src/layers/batch_norm_layer.cpp b/modules/dnn/src/layers/batch_norm_layer.cpp index 0407942efa..7939eaf18b 100644 --- a/modules/dnn/src/layers/batch_norm_layer.cpp +++ b/modules/dnn/src/layers/batch_norm_layer.cpp @@ -163,6 +163,11 @@ public: std::vector &outputs, std::vector &internals) const CV_OVERRIDE { + if (inputs[0].empty()) { // Support for 0D input + outputs.push_back(MatShape()); // Output is also a scalar. + return true; + } + dims = inputs[0].size(); if (!useGlobalStats && inputs[0][0] != 1) CV_Error(Error::StsNotImplemented, "Batch normalization in training mode with batch size > 1"); @@ -272,6 +277,15 @@ public: inputs_arr.getMatVector(inputs); outputs_arr.getMatVector(outputs); + if (inputs[0].dims <= 1) { // Handling for 0D and 1D + Mat &inpBlob = inputs[0]; + Mat &outBlob = outputs[0]; + CV_Assert(inpBlob.total() == weights_.total()); + cv::multiply(inpBlob, weights_, outBlob); + cv::add(outBlob, bias_, outBlob); + return; + } + CV_Assert(blobs.size() >= 2); CV_Assert(inputs.size() == 1); @@ -284,7 +298,6 @@ public: for (size_t ii = 0; ii < outputs.size(); ii++) { Mat &outBlob = outputs[ii]; - for(int num = 0; num < outBlob.size[0]; num++) { for (int n = 0; n < outBlob.size[1]; n++) diff --git a/modules/dnn/test/test_layers_1d.cpp b/modules/dnn/test/test_layers_1d.cpp index 44249ba009..fd3d299170 100644 --- a/modules/dnn/test/test_layers_1d.cpp +++ b/modules/dnn/test/test_layers_1d.cpp @@ -603,6 +603,55 @@ INSTANTIATE_TEST_CASE_P(/*nothting*/, Layer_FullyConnected_Test, std::vector({4}) )); +typedef testing::TestWithParam> Layer_BatchNorm_Test; +TEST_P(Layer_BatchNorm_Test, Accuracy_01D) +{ + std::vector input_shape = GetParam(); + + // Layer parameters + LayerParams lp; + lp.type = "BatchNorm"; + lp.name = "BatchNormLayer"; + lp.set("has_weight", false); + lp.set("has_bias", false); + + RNG& rng = TS::ptr()->get_rng(); + float inp_value = rng.uniform(0.0, 10.0); + + Mat meanMat(input_shape.size(), input_shape.data(), CV_32F, inp_value); + Mat varMat(input_shape.size(), input_shape.data(), CV_32F, inp_value); + vector blobs = {meanMat, varMat}; + lp.blobs = blobs; + + // Create the layer + Ptr layer = BatchNormLayer::create(lp); + + Mat input(input_shape.size(), input_shape.data(), CV_32F, 1.0); + cv::randn(input, 0, 1); + + std::vector inputs{input}; + std::vector outputs; + runLayer(layer, inputs, outputs); + + //create output_ref to compare with outputs + Mat output_ref = input.clone(); + cv::sqrt(varMat + 1e-5, varMat); + output_ref = (output_ref - meanMat) / varMat; + + ASSERT_EQ(outputs.size(), 1); + ASSERT_EQ(shape(output_ref), shape(outputs[0])); + normAssert(output_ref, outputs[0]); + +} +INSTANTIATE_TEST_CASE_P(/*nothting*/, Layer_BatchNorm_Test, + testing::Values( + std::vector({}), + std::vector({4}), + std::vector({1, 4}), + std::vector({4, 1}) +)); + + typedef testing::TestWithParam>> Layer_Const_Test; TEST_P(Layer_Const_Test, Accuracy_01D) {