// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // // Copyright (C) 2017, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. #include "test_precomp.hpp" #include namespace opencv_test { namespace { int64_t getValueAt(const Mat &m, const int *indices) { if (m.type() == CV_Bool) return m.at(indices); else if (m.type() == CV_8U) return m.at(indices); else if (m.type() == CV_8S) return m.at(indices); else if (m.type() == CV_32S) return m.at(indices); else if (m.type() == CV_64S) return m.at(indices); else CV_Error(Error::BadDepth, "Unsupported type"); return -1; } int64_t getValueAt(const Mat &m, int index) { if (m.type() == CV_Bool) return m.ptr()[index]; else if (m.type() == CV_8U) return m.ptr()[index]; else if (m.type() == CV_8S) return m.ptr()[index]; else if (m.type() == CV_32S) return m.ptr()[index]; else if (m.type() == CV_64S) return m.ptr()[index]; else CV_Error(Error::BadDepth, "Unsupported type"); return -1; } void fillRandom(Mat& m, int matType, Backend backend) { if (matType == CV_64S && backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) cv::randu(m, 1000000000, 1000000100); // Looks like OpenVINO uses int32 internal values for int64 operations else if (matType == CV_64S) cv::randu(m, 1000000000000000ll, 1000000000000100ll); else if (matType == CV_32S) cv::randu(m, 1000000000, 1000000100); else if (matType == CV_8S) cv::randu(m, -50, 50); else if (matType == CV_8U) cv::randu(m, 0, 100); else if (matType == CV_Bool) cv::randu(m, 0, 2); else CV_Error(Error::BadDepth, "Unsupported type"); } typedef testing::TestWithParam > > Test_NaryEltwise_Int; TEST_P(Test_NaryEltwise_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input1(inShape, matType); Mat input2(inShape, matType); fillRandom(input1, matType, backend); fillRandom(input2, matType, backend); Net net; LayerParams lp; lp.type = "NaryEltwise"; lp.name = "testLayer"; if (matType == CV_Bool) lp.set("operation", "or"); else lp.set("operation", "add"); int id = net.addLayerToPrev(lp.name, lp.type, lp); net.connect(0, 1, id, 1); vector inpNames(2); inpNames[0] = "input1"; inpNames[1] = "input2"; net.setInputsNames(inpNames); net.setInput(input1, inpNames[0]); net.setInput(input2, inpNames[1]); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], input1.size[0]); EXPECT_EQ(re.size[1], input1.size[1]); EXPECT_EQ(re.size[2], input1.size[2]); EXPECT_EQ(re.size[3], input1.size[3]); std::vector reIndices(4); for (int i0 = 0; i0 < re.size[0]; ++i0) { reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { reIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { reIndices[2] = i2; for (int i3 = 0; i3 < re.size[3]; ++i3) { reIndices[3] = i3; if (matType == CV_Bool) EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input1, reIndices.data()) | getValueAt(input2, reIndices.data())); else EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input1, reIndices.data()) + getValueAt(input2, reIndices.data())); } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_NaryEltwise_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Const_Int; TEST_P(Test_Const_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input1(inShape, matType); Mat inputConst(inShape, matType); fillRandom(input1, matType, backend); fillRandom(inputConst, matType, backend); Net net; LayerParams lpConst; lpConst.type = "Const"; lpConst.name = "constLayer"; lpConst.blobs.push_back(inputConst); int idConst = net.addLayer(lpConst.name, lpConst.type, lpConst); LayerParams lp; lp.type = "NaryEltwise"; lp.name = "testLayer"; if (matType == CV_Bool) lp.set("operation", "or"); else lp.set("operation", "add"); int idSum = net.addLayer(lp.name, lp.type, lp); net.connect(0, 0, idSum, 0); net.connect(idConst, 0, idSum, 1); net.setInput(input1); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], input1.size[0]); EXPECT_EQ(re.size[1], input1.size[1]); EXPECT_EQ(re.size[2], input1.size[2]); EXPECT_EQ(re.size[3], input1.size[3]); std::vector reIndices(4); for (int i0 = 0; i0 < re.size[0]; ++i0) { reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { reIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { reIndices[2] = i2; for (int i3 = 0; i3 < re.size[3]; ++i3) { reIndices[3] = i3; if (matType == CV_Bool) EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input1, reIndices.data()) | getValueAt(inputConst, reIndices.data())); else EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input1, reIndices.data()) + getValueAt(inputConst, reIndices.data())); } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Const_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_ScatterND_Int; TEST_P(Test_ScatterND_Int, random) { int matType = get<0>(GetParam()); int indicesType = get<1>(GetParam()); tuple backend_target= get<2>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); std::vector indicesValues{0, 1, 2, 3, 1, 2, 3, 4}; std::vector updatesValues{25, 35}; if (matType == CV_Bool) { updatesValues[0] = 1; updatesValues[1] = 0; } Mat indices(2, 4, indicesType); std::vector updatesShape{2}; Mat updates(updatesShape, matType); for (int i = 0; i < indicesValues.size(); ++i) { if (indicesType == CV_32S) indices.ptr()[i] = indicesValues[i]; else indices.ptr()[i] = indicesValues[i]; } for (int i = 0; i < updatesValues.size(); ++i) { if (matType == CV_32S) updates.ptr()[i] = updatesValues[i]; else if (matType == CV_64S) updates.ptr()[i] = updatesValues[i]; else if (matType == CV_8S) updates.ptr()[i] = updatesValues[i]; else if (matType == CV_8U) updates.ptr()[i] = updatesValues[i]; else if (matType == CV_Bool) updates.ptr()[i] = updatesValues[i]; } Net net; LayerParams lp; lp.type = "ScatterND"; lp.name = "testLayer"; int id = net.addLayerToPrev(lp.name, lp.type, lp); net.connect(0, 1, id, 1); net.connect(0, 2, id, 2); std::vector inpNames(3); inpNames[0] = "scattedND_input"; inpNames[1] = "scatterND_indices"; inpNames[2] = "scatterND_updates"; net.setInputsNames(inpNames); net.setInput(input, inpNames[0]); net.setInput(indices, inpNames[1]); net.setInput(updates, inpNames[2]); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); ASSERT_EQ(shape(input), shape(re)); std::vector reIndices(4); for (int i0 = 0; i0 < input.size[0]; ++i0) { reIndices[0] = i0; for (int i1 = 0; i1 < input.size[1]; ++i1) { reIndices[1] = i1; for (int i2 = 0; i2 < input.size[2]; ++i2) { reIndices[2] = i2; for (int i3 = 0; i3 < input.size[3]; ++i3) { reIndices[3] = i3; if (reIndices[0] == indicesValues[0] && reIndices[1] == indicesValues[1] && reIndices[2] == indicesValues[2] && reIndices[3] == indicesValues[3]) { EXPECT_EQ(getValueAt(re, reIndices.data()), updatesValues[0]); } else if (reIndices[0] == indicesValues[4] && reIndices[1] == indicesValues[5] && reIndices[2] == indicesValues[6] && reIndices[3] == indicesValues[7]) { EXPECT_EQ(getValueAt(re, reIndices.data()), updatesValues[1]); } else { EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input, reIndices.data())); } } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_ScatterND_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), testing::Values(CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Concat_Int; TEST_P(Test_Concat_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape1{2, 3, 4, 5}; Mat input1(inShape1, matType); fillRandom(input1, matType, backend); std::vector inShape2{2, 2, 4, 5}; Mat input2(inShape2, matType); fillRandom(input2, matType, backend); Net net; LayerParams lp; lp.type = "Concat"; lp.name = "testLayer"; lp.set("axis", 1); int id = net.addLayerToPrev(lp.name, lp.type, lp); net.connect(0, 1, id, 1); vector inpNames(2); inpNames[0] = "input1"; inpNames[1] = "input2"; net.setInputsNames(inpNames); net.setInput(input1, inpNames[0]); net.setInput(input2, inpNames[1]); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], input1.size[0]); EXPECT_EQ(re.size[1], input1.size[1] + input2.size[1]); EXPECT_EQ(re.size[2], input1.size[2]); EXPECT_EQ(re.size[3], input1.size[3]); std::vector inIndices(4); std::vector reIndices(4); for (int i0 = 0; i0 < re.size[0]; ++i0) { reIndices[0] = i0; inIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { reIndices[1] = i1; if (i1 < input1.size[1]) inIndices[1] = i1; else inIndices[1] = i1 - input1.size[1]; for (int i2 = 0; i2 < re.size[2]; ++i2) { reIndices[2] = i2; inIndices[2] = i2; for (int i3 = 0; i3 < re.size[3]; ++i3) { reIndices[3] = i3; inIndices[3] = i3; if (i1 < input1.size[1]) { EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input1, inIndices.data())); } else { EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input2, inIndices.data())); } } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Concat_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_ArgMax_Int; TEST_P(Test_ArgMax_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // There is a problem with OpenVINO and custom int64 layers. After model compilation the output tensor type changes from int64 to int32 std::vector inShape{5, 4, 3, 2}; Mat input(inShape, matType); fillRandom(input, matType, backend); Net net; LayerParams lp; lp.type = "Arg"; lp.name = "testLayer"; lp.set("op", "max"); lp.set("keepdims", 0); lp.set("axis", 1); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), CV_64S); EXPECT_EQ(re.size.dims(), 3); EXPECT_EQ(re.size[0], inShape[0]); EXPECT_EQ(re.size[1], inShape[2]); EXPECT_EQ(re.size[2], inShape[3]); std::vector inIndices(4); std::vector reIndices(3); for (int i0 = 0; i0 < re.size[0]; ++i0) { inIndices[0] = i0; reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { inIndices[2] = i1; reIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { inIndices[3] = i2; reIndices[2] = i2; int64_t max_value = -1000000000000000000l; int64_t index = 0; for (int j = 0; j < input.size[1]; ++j) { inIndices[1] = j; int64_t cur_value = getValueAt(input, inIndices.data()); if (cur_value > max_value) { max_value = cur_value; index = j; } } EXPECT_EQ(getValueAt(re, reIndices.data()), index); } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_ArgMax_Int, Combine( testing::Values(CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Blank_Int; TEST_P(Test_Blank_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); Net net; LayerParams lp; lp.type = "Identity"; lp.name = "testLayer"; net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], 2); EXPECT_EQ(re.size[1], 3); EXPECT_EQ(re.size[2], 4); EXPECT_EQ(re.size[3], 5); std::vector reIndices(4); for (int i0 = 0; i0 < re.size[0]; ++i0) { reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { reIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { reIndices[2] = i2; for (int i3 = 0; i3 < re.size[3]; ++i3) { reIndices[3] = i3; EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input, reIndices.data())); } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Blank_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Expand_Int; TEST_P(Test_Expand_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 1, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); std::vector outShape{2, 1, 4, 5}; Net net; LayerParams lp; lp.type = "Expand"; lp.name = "testLayer"; lp.set("shape", DictValue::arrayInt(&outShape[0], outShape.size())); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], 2); EXPECT_EQ(re.size[1], 3); EXPECT_EQ(re.size[2], 4); EXPECT_EQ(re.size[3], 5); std::vector inIndices(4); std::vector reIndices(4); for (int i0 = 0; i0 < re.size[0]; ++i0) { inIndices[0] = i0 % inShape[0]; reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { inIndices[1] = i1 % inShape[1]; reIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { inIndices[2] = i2 % inShape[2]; reIndices[2] = i2; for (int i3 = 0; i3 < re.size[3]; ++i3) { inIndices[3] = i3 % inShape[3]; reIndices[3] = i3; EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input, inIndices.data())); } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Expand_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Permute_Int; TEST_P(Test_Permute_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); std::vector order{0, 2, 3, 1}; Net net; LayerParams lp; lp.type = "Permute"; lp.name = "testLayer"; lp.set("order", DictValue::arrayInt(&order[0], order.size())); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], 2); EXPECT_EQ(re.size[1], 4); EXPECT_EQ(re.size[2], 5); EXPECT_EQ(re.size[3], 3); std::vector inIndices(4); std::vector reIndices(4); for (int i0 = 0; i0 < input.size[0]; ++i0) { inIndices[0] = i0; reIndices[0] = i0; for (int i1 = 0; i1 < input.size[1]; ++i1) { inIndices[1] = i1; reIndices[3] = i1; for (int i2 = 0; i2 < input.size[2]; ++i2) { inIndices[2] = i2; reIndices[1] = i2; for (int i3 = 0; i3 < input.size[3]; ++i3) { inIndices[3] = i3; reIndices[2] = i3; EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input, inIndices.data())); } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Permute_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_GatherElements_Int; TEST_P(Test_GatherElements_Int, random) { int matType = get<0>(GetParam()); int indicesType = get<1>(GetParam()); tuple backend_target= get<2>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); std::vector indicesShape{2, 3, 10, 5}; Mat indicesMat(indicesShape, indicesType); cv::randu(indicesMat, 0, 4); Net net; LayerParams lp; lp.type = "GatherElements"; lp.name = "testLayer"; lp.set("axis", 2); int id = net.addLayerToPrev(lp.name, lp.type, lp); net.connect(0, 1, id, 1); std::vector inpNames(2); inpNames[0] = "gather_input"; inpNames[1] = "gather_indices"; net.setInputsNames(inpNames); net.setInput(input, inpNames[0]); net.setInput(indicesMat, inpNames[1]); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); ASSERT_EQ(shape(indicesMat), shape(re)); std::vector inIndices(4); std::vector reIndices(4); for (int i0 = 0; i0 < input.size[0]; ++i0) { inIndices[0] = i0; reIndices[0] = i0; for (int i1 = 0; i1 < input.size[1]; ++i1) { inIndices[1] = i1; reIndices[1] = i1; for (int i2 = 0; i2 < indicesMat.size[2]; ++i2) { reIndices[2] = i2; for (int i3 = 0; i3 < input.size[3]; ++i3) { inIndices[3] = i3; reIndices[3] = i3; inIndices[2] = getValueAt(indicesMat, reIndices.data()); EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input, inIndices.data())); } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_GatherElements_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), testing::Values(CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Gather_Int; TEST_P(Test_Gather_Int, random) { int matType = get<0>(GetParam()); int indicesType = get<1>(GetParam()); tuple backend_target= get<2>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{5, 1}; Mat input(inShape, matType); fillRandom(input, matType, backend); std::vector indices_shape = {1, 1}; Mat indicesMat = cv::Mat(indices_shape, indicesType, 0.0); std::vector output_shape = {5, 1}; cv::Mat outputRef = cv::Mat(output_shape, matType, input(cv::Range::all(), cv::Range(0, 1)).data); Net net; LayerParams lp; lp.type = "Gather"; lp.name = "testLayer"; lp.set("axis", 1); lp.set("real_ndims", 1); int id = net.addLayerToPrev(lp.name, lp.type, lp); net.connect(0, 1, id, 1); std::vector inpNames(2); inpNames[0] = "gather_input"; inpNames[1] = "gather_indices"; net.setInputsNames(inpNames); net.setInput(input, inpNames[0]); net.setInput(indicesMat, inpNames[1]); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); ASSERT_EQ(shape(outputRef), shape(re)); normAssert(outputRef, re); } INSTANTIATE_TEST_CASE_P(/**/, Test_Gather_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), testing::Values(CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Cast_Int; TEST_P(Test_Cast_Int, random) { int inMatType = get<0>(GetParam()); int outMatType = get<1>(GetParam()); tuple backend_target= get<2>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, inMatType); if (inMatType == CV_Bool || outMatType == CV_Bool) cv::randu(input, 0, 1.1); else cv::randu(input, 0, 100); Mat outputRef; input.convertTo(outputRef, outMatType); Net net; LayerParams lp; lp.type = "Cast"; lp.name = "testLayer"; lp.set("outputType", outMatType); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), outMatType); EXPECT_EQ(re.size.dims(), 4); ASSERT_EQ(shape(input), shape(re)); normAssert(outputRef, re); } INSTANTIATE_TEST_CASE_P(/**/, Test_Cast_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Pad_Int; TEST_P(Test_Pad_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); std::vector paddings{0, 0, 0, 0, 1, 0, 0, 1}; int64_t padValue = matType == CV_Bool ? 1 : 25; Net net; LayerParams lp; lp.type = "Padding"; lp.name = "testLayer"; lp.set("paddings", DictValue::arrayInt(&paddings[0], paddings.size())); lp.set("value", padValue); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], 2); EXPECT_EQ(re.size[1], 3); EXPECT_EQ(re.size[2], 5); EXPECT_EQ(re.size[3], 6); std::vector reIndices(4); std::vector inIndices(4); for (int i0 = 0; i0 < re.size[0]; ++i0) { reIndices[0] = i0; inIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { reIndices[1] = i1; inIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { reIndices[2] = i2; inIndices[2] = i2 - 1; for (int i3 = 0; i3 < re.size[3]; ++i3) { reIndices[3] = i3; inIndices[3] = i3; if (i2 < 1 || i3 >= input.size[3]) { EXPECT_EQ(getValueAt(re, reIndices.data()), padValue); } else { EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input, inIndices.data())); } } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Pad_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Slice_Int; TEST_P(Test_Slice_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inputShape{1, 16, 6, 8}; std::vector begin{0, 4, 0, 0}; std::vector end{1, 8, 6, 8}; Mat input(inputShape, matType); fillRandom(input, matType, backend); std::vector range(4); for (int i = 0; i < 4; ++i) range[i] = Range(begin[i], end[i]); Net net; LayerParams lp; lp.type = "Slice"; lp.name = "testLayer"; lp.set("begin", DictValue::arrayInt(&(begin[0]), 4)); lp.set("end", DictValue::arrayInt(&(end[0]), 4)); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat out = net.forward(); Mat gt = input(range); EXPECT_EQ(out.size.dims(), 4); EXPECT_EQ(out.size[0], gt.size[0]); EXPECT_EQ(out.size[1], gt.size[1]); EXPECT_EQ(out.size[2], gt.size[2]); EXPECT_EQ(out.size[3], gt.size[3]); for (int i = 0; i < out.total(); ++i) EXPECT_EQ(getValueAt(out, i), getValueAt(gt, i)); } INSTANTIATE_TEST_CASE_P(/**/, Test_Slice_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Reshape_Int; TEST_P(Test_Reshape_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; std::vector outShape{2, 3, 2, 10}; Mat input(inShape, matType); fillRandom(input, matType, backend); Net net; LayerParams lp; lp.type = "Reshape"; lp.name = "testLayer"; lp.set("dim", DictValue::arrayInt(&outShape[0], outShape.size())); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], outShape[0]); EXPECT_EQ(re.size[1], outShape[1]); EXPECT_EQ(re.size[2], outShape[2]); EXPECT_EQ(re.size[3], outShape[3]); for (int i = 0; i < input.total(); ++i) EXPECT_EQ(getValueAt(re, i), getValueAt(input, i)); } INSTANTIATE_TEST_CASE_P(/**/, Test_Reshape_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Flatten_Int; TEST_P(Test_Flatten_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); Net net; LayerParams lp; lp.type = "Flatten"; lp.name = "testLayer"; lp.set("axis", 1); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 2); EXPECT_EQ(re.size[0], inShape[0]); EXPECT_EQ(re.size[1], inShape[1] * inShape[2] * inShape[3]); for (int i = 0; i < input.total(); ++i) EXPECT_EQ(getValueAt(re, i), getValueAt(input, i)); } INSTANTIATE_TEST_CASE_P(/**/, Test_Flatten_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Tile_Int; TEST_P(Test_Tile_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); std::vector inShape{2, 3, 4, 5}; Mat input(inShape, matType); fillRandom(input, matType, backend); std::vector repeats{1, 1, 2, 3}; Net net; LayerParams lp; lp.type = "Tile"; lp.name = "testLayer"; lp.set("repeats", DictValue::arrayInt(repeats.data(), repeats.size())); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 4); EXPECT_EQ(re.size[0], inShape[0] * repeats[0]); EXPECT_EQ(re.size[1], inShape[1] * repeats[1]); EXPECT_EQ(re.size[2], inShape[2] * repeats[2]); EXPECT_EQ(re.size[3], inShape[3] * repeats[3]); std::vector inIndices(4); std::vector reIndices(4); for (int i0 = 0; i0 < re.size[0]; ++i0) { inIndices[0] = i0 % inShape[0]; reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { inIndices[1] = i1 % inShape[1]; reIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { inIndices[2] = i2 % inShape[2]; reIndices[2] = i2; for (int i3 = 0; i3 < re.size[3]; ++i3) { inIndices[3] = i3 % inShape[3]; reIndices[3] = i3; EXPECT_EQ(getValueAt(re, reIndices.data()), getValueAt(input, inIndices.data())); } } } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Tile_Int, Combine( testing::Values(CV_Bool, CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); typedef testing::TestWithParam > > Test_Reduce_Int; TEST_P(Test_Reduce_Int, random) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && matType == CV_64S) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // There is a problem with OpenVINO and custom int64 layers. After model compilation the output tensor type changes from int64 to int32 std::vector inShape{5, 4, 3, 2}; Mat input(inShape, matType); if (matType == CV_64S && backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) cv::randu(input, 100000000, 100000100); // Looks like OpenVINO uses int32 internal values for int64 operations else if (matType == CV_64S) cv::randu(input, 1000000000000000ll, 1000000000000100ll); else if (matType == CV_32S) cv::randu(input, 100000000, 100000100); else if (matType == CV_8S) cv::randu(input, -25, 25); else if (matType == CV_8U) cv::randu(input, 0, 50); else CV_Error(Error::BadDepth, "Unsupported type"); std::vector axes{1}; Net net; LayerParams lp; lp.type = "Reduce"; lp.name = "testLayer"; lp.set("reduce", "SUM"); lp.set("keepdims", false); lp.set("axes", DictValue::arrayInt(axes.data(), axes.size())); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 3); EXPECT_EQ(re.size[0], inShape[0]); EXPECT_EQ(re.size[1], inShape[2]); EXPECT_EQ(re.size[2], inShape[3]); std::vector inIndices(4); std::vector reIndices(3); for (int i0 = 0; i0 < re.size[0]; ++i0) { inIndices[0] = i0; reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { inIndices[2] = i1; reIndices[1] = i1; for (int i2 = 0; i2 < re.size[2]; ++i2) { inIndices[3] = i2; reIndices[2] = i2; int64_t value = 0; for (int j = 0; j < input.size[1]; ++j) { inIndices[1] = j; value += getValueAt(input, inIndices.data()); } EXPECT_EQ(getValueAt(re, reIndices.data()), value); } } } } typedef testing::TestWithParam > > Test_Reduce_Int; TEST_P(Test_Reduce_Int, two_axes) { int matType = get<0>(GetParam()); tuple backend_target= get<1>(GetParam()); Backend backend = get<0>(backend_target); Target target = get<1>(backend_target); if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && matType == CV_64S) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // There is a problem with OpenVINO and custom int64 layers. After model compilation the output tensor type changes from int64 to int32 std::vector inShape{5, 4, 3, 2}; Mat input(inShape, matType); if (matType == CV_64S && backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) cv::randu(input, 100000000, 100000100); // Looks like OpenVINO uses int32 internal values for int64 operations else if (matType == CV_64S) cv::randu(input, 1000000000000000ll, 1000000000000100ll); else if (matType == CV_32S) cv::randu(input, 100000000, 100000100); else if (matType == CV_8S) cv::randu(input, -15, 15); else if (matType == CV_8U) cv::randu(input, 0, 30); else CV_Error(Error::BadDepth, "Unsupported type"); std::vector axes{1, 3}; Net net; LayerParams lp; lp.type = "Reduce"; lp.name = "testLayer"; lp.set("reduce", "SUM"); lp.set("keepdims", false); lp.set("axes", DictValue::arrayInt(axes.data(), axes.size())); net.addLayerToPrev(lp.name, lp.type, lp); net.setInput(input); net.setPreferableBackend(backend); net.setPreferableTarget(target); Mat re; re = net.forward(); EXPECT_EQ(re.depth(), matType); EXPECT_EQ(re.size.dims(), 2); EXPECT_EQ(re.size[0], inShape[0]); EXPECT_EQ(re.size[1], inShape[2]); std::vector inIndices(4); std::vector reIndices(2); for (int i0 = 0; i0 < re.size[0]; ++i0) { inIndices[0] = i0; reIndices[0] = i0; for (int i1 = 0; i1 < re.size[1]; ++i1) { inIndices[2] = i1; reIndices[1] = i1; int64_t value = 0; for (int i2 = 0; i2 < input.size[3]; ++i2) { inIndices[3] = i2; for (int j = 0; j < input.size[1]; ++j) { inIndices[1] = j; value += getValueAt(input, inIndices.data()); } } EXPECT_EQ(getValueAt(re, reIndices.data()), value); } } } INSTANTIATE_TEST_CASE_P(/**/, Test_Reduce_Int, Combine( testing::Values(CV_8U, CV_8S, CV_32S, CV_64S), dnnBackendsAndTargets() )); }} // namespace