Merge pull request #15012 from andrey-golubev:test_output

G-API: Add output allocation tests for backends (#15012)

* Add output tests for backends

* Fix large size test: output is in fact reallocated

* Use cv::Mat copies for reallocation tracking

* Separate LargeSizeWithCorrectSubmatrix test

* Rename backed output allocation tests

* Address code review feedback

Update test names

Add illustrative "expect (non-)empty" checks

Rename mat "copy" to mat reference

Add more pointer checks

* Add illustrative checks
This commit is contained in:
Andrey Golubev 2019-07-16 19:01:45 +03:00 committed by Alexander Alekhin
parent e629785a97
commit c11423df1e
5 changed files with 269 additions and 0 deletions

View File

@ -165,6 +165,18 @@ GAPI_TEST_FIXTURE(PhaseTest, initMatsRandU, FIXTURE_API(bool), 1, angle_in_degre
GAPI_TEST_FIXTURE(SqrtTest, initMatrixRandU, <>, 0)
GAPI_TEST_FIXTURE(NormalizeTest, initNothing, FIXTURE_API(compare_f,double,double,int,MatType), 5,
cmpF, a, b, norm_type, ddepth)
struct BackendOutputAllocationTest : TestWithParamBase<>
{
BackendOutputAllocationTest()
{
in_mat1 = cv::Mat(sz, type);
in_mat2 = cv::Mat(sz, type);
cv::randu(in_mat1, cv::Scalar::all(1), cv::Scalar::all(15));
cv::randu(in_mat2, cv::Scalar::all(1), cv::Scalar::all(15));
}
};
// FIXME: move all tests from this fixture to the base class once all issues are resolved
struct BackendOutputAllocationLargeSizeWithCorrectSubmatrixTest : BackendOutputAllocationTest {};
} // opencv_test
#endif //OPENCV_GAPI_CORE_TESTS_HPP

View File

@ -1267,6 +1267,217 @@ TEST_P(NormalizeTest, Test)
}
}
TEST_P(BackendOutputAllocationTest, EmptyOutput)
{
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::mul(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
EXPECT_TRUE(out_mat_gapi.empty());
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), getCompileArgs());
EXPECT_FALSE(out_mat_gapi.empty());
// OpenCV code /////////////////////////////////////////////////////////////
cv::multiply(in_mat1, in_mat2, out_mat_ocv);
// Comparison //////////////////////////////////////////////////////////////
// Expected: output is allocated to the needed size
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi.size());
}
TEST_P(BackendOutputAllocationTest, CorrectlyPreallocatedOutput)
{
out_mat_gapi = cv::Mat(sz, type);
auto out_mat_gapi_ref = out_mat_gapi; // shallow copy to ensure previous data is not deleted
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::add(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::add(in_mat1, in_mat2, out_mat_ocv);
// Comparison //////////////////////////////////////////////////////////////
// Expected: output is not reallocated
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi.size());
EXPECT_EQ(out_mat_gapi_ref.data, out_mat_gapi.data);
}
// FIXME: known issue with OCL backend - PR #14985
TEST_P(BackendOutputAllocationTest, DISABLED_IncorrectOutputMeta)
{
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::add(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
const auto run_and_compare = [&c, this] ()
{
auto out_mat_gapi_ref = out_mat_gapi; // shallow copy to ensure previous data is not deleted
// G-API code //////////////////////////////////////////////////////////////
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::add(in_mat1, in_mat2, out_mat_ocv, cv::noArray());
// Comparison //////////////////////////////////////////////////////////////
// Expected: size is changed, type is changed, output is reallocated
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi.size());
EXPECT_EQ(type, out_mat_gapi.type());
EXPECT_NE(out_mat_gapi_ref.data, out_mat_gapi.data);
};
const auto chan = CV_MAT_CN(type);
out_mat_gapi = cv::Mat(sz, CV_MAKE_TYPE(CV_64F, chan));
run_and_compare();
out_mat_gapi = cv::Mat(sz, CV_MAKE_TYPE(CV_MAT_DEPTH(type), chan + 1));
run_and_compare();
}
TEST_P(BackendOutputAllocationTest, SmallerPreallocatedSize)
{
out_mat_gapi = cv::Mat(sz / 2, type);
auto out_mat_gapi_ref = out_mat_gapi; // shallow copy to ensure previous data is not deleted
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::mul(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::multiply(in_mat1, in_mat2, out_mat_ocv);
// Comparison //////////////////////////////////////////////////////////////
// Expected: size is changed, output is reallocated due to original size < curr size
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi.size());
EXPECT_NE(out_mat_gapi_ref.data, out_mat_gapi.data);
}
TEST_P(BackendOutputAllocationTest, SmallerPreallocatedSizeWithSubmatrix)
{
out_mat_gapi = cv::Mat(sz / 2, type);
cv::Mat out_mat_gapi_submat = out_mat_gapi(cv::Rect({10, 0}, sz / 5));
EXPECT_EQ(out_mat_gapi.data, out_mat_gapi_submat.datastart);
auto out_mat_gapi_submat_ref = out_mat_gapi_submat; // shallow copy to ensure previous data is not deleted
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::mul(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi_submat), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::multiply(in_mat1, in_mat2, out_mat_ocv);
// Comparison //////////////////////////////////////////////////////////////
// Expected: submatrix is reallocated and is "detached", original matrix is unchanged
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi_submat != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi_submat.size());
EXPECT_EQ(sz / 2, out_mat_gapi.size());
EXPECT_NE(out_mat_gapi_submat_ref.data, out_mat_gapi_submat.data);
EXPECT_NE(out_mat_gapi.data, out_mat_gapi_submat.datastart);
}
TEST_P(BackendOutputAllocationTest, LargerPreallocatedSize)
{
out_mat_gapi = cv::Mat(sz * 2, type);
auto out_mat_gapi_ref = out_mat_gapi; // shallow copy to ensure previous data is not deleted
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::mul(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::multiply(in_mat1, in_mat2, out_mat_ocv);
// Comparison //////////////////////////////////////////////////////////////
// Expected: size is changed, output is reallocated
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi.size());
EXPECT_NE(out_mat_gapi_ref.data, out_mat_gapi.data);
}
TEST_P(BackendOutputAllocationLargeSizeWithCorrectSubmatrixTest,
LargerPreallocatedSizeWithCorrectSubmatrix)
{
out_mat_gapi = cv::Mat(sz * 2, type);
auto out_mat_gapi_ref = out_mat_gapi; // shallow copy to ensure previous data is not deleted
cv::Mat out_mat_gapi_submat = out_mat_gapi(cv::Rect({5, 8}, sz));
EXPECT_EQ(out_mat_gapi.data, out_mat_gapi_submat.datastart);
auto out_mat_gapi_submat_ref = out_mat_gapi_submat;
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::mul(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi_submat), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::multiply(in_mat1, in_mat2, out_mat_ocv);
// Comparison //////////////////////////////////////////////////////////////
// Expected: submatrix is not reallocated, original matrix is not reallocated
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi_submat != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi_submat.size());
EXPECT_EQ(sz * 2, out_mat_gapi.size());
EXPECT_EQ(out_mat_gapi_ref.data, out_mat_gapi.data);
EXPECT_EQ(out_mat_gapi_submat_ref.data, out_mat_gapi_submat.data);
EXPECT_EQ(out_mat_gapi.data, out_mat_gapi_submat.datastart);
}
TEST_P(BackendOutputAllocationTest, LargerPreallocatedSizeWithSmallSubmatrix)
{
out_mat_gapi = cv::Mat(sz * 2, type);
auto out_mat_gapi_ref = out_mat_gapi; // shallow copy to ensure previous data is not deleted
cv::Mat out_mat_gapi_submat = out_mat_gapi(cv::Rect({5, 8}, sz / 2));
EXPECT_EQ(out_mat_gapi.data, out_mat_gapi_submat.datastart);
auto out_mat_gapi_submat_ref = out_mat_gapi_submat;
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in1, in2, out;
out = cv::gapi::mul(in1, in2);
cv::GComputation c(cv::GIn(in1, in2), cv::GOut(out));
c.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi_submat), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::multiply(in_mat1, in_mat2, out_mat_ocv);
// Comparison //////////////////////////////////////////////////////////////
// Expected: submatrix is reallocated and is "detached", original matrix is unchanged
EXPECT_EQ(0, cv::countNonZero(out_mat_gapi_submat != out_mat_ocv));
EXPECT_EQ(sz, out_mat_gapi_submat.size());
EXPECT_EQ(sz * 2, out_mat_gapi.size());
EXPECT_EQ(out_mat_gapi_ref.data, out_mat_gapi.data);
EXPECT_NE(out_mat_gapi_submat_ref.data, out_mat_gapi_submat.data);
EXPECT_NE(out_mat_gapi.data, out_mat_gapi_submat.datastart);
}
} // opencv_test
#endif //OPENCV_GAPI_CORE_TESTS_INL_HPP

View File

@ -489,4 +489,19 @@ INSTANTIATE_TEST_CASE_P(NormalizeTestCPU, NormalizeTest,
Values(1.0, 120.0, 255.0),
Values(NORM_MINMAX, NORM_INF, NORM_L1, NORM_L2),
Values(-1, CV_8U, CV_16U, CV_16S, CV_32F)));
INSTANTIATE_TEST_CASE_P(BackendOutputAllocationTestCPU, BackendOutputAllocationTest,
Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
Values(cv::Size(50, 50)),
Values(-1),
Values(false),
Values(CORE_CPU)));
INSTANTIATE_TEST_CASE_P(BackendOutputAllocationLargeSizeWithCorrectSubmatrixTestCPU,
BackendOutputAllocationLargeSizeWithCorrectSubmatrixTest,
Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
Values(cv::Size(50, 50)),
Values(-1),
Values(false),
Values(CORE_CPU)));
}

View File

@ -283,6 +283,21 @@ INSTANTIATE_TEST_CASE_P(ResizeTestFluid, ResizeTest,
cv::Size(64, 64),
cv::Size(30, 30))));
INSTANTIATE_TEST_CASE_P(BackendOutputAllocationTestFluid, BackendOutputAllocationTest,
Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
Values(cv::Size(50, 50)),
Values(-1),
Values(false),
Values(CORE_FLUID)));
INSTANTIATE_TEST_CASE_P(BackendOutputAllocationLargeSizeWithCorrectSubmatrixTestFluid,
BackendOutputAllocationLargeSizeWithCorrectSubmatrixTest,
Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
Values(cv::Size(50, 50)),
Values(-1),
Values(false),
Values(CORE_FLUID)));
//----------------------------------------------------------------------
// FIXME: Clean-up test configurations which are enabled already
#if 0

View File

@ -426,6 +426,22 @@ INSTANTIATE_TEST_CASE_P(ConcatVertTestGPU, ConcatVertTest,
Values(false),
Values(CORE_GPU)));
INSTANTIATE_TEST_CASE_P(BackendOutputAllocationTestGPU, BackendOutputAllocationTest,
Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
Values(cv::Size(50, 50)),
Values(-1),
Values(false),
Values(CORE_GPU)));
// FIXME: there's an issue in OCL backend with matrix reallocation that shouldn't happen
INSTANTIATE_TEST_CASE_P(DISABLED_BackendOutputAllocationLargeSizeWithCorrectSubmatrixTestGPU,
BackendOutputAllocationLargeSizeWithCorrectSubmatrixTest,
Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
Values(cv::Size(50, 50)),
Values(-1),
Values(false),
Values(CORE_GPU)));
//TODO: fix this backend to allow ConcatVertVec ConcatHorVec
#if 0
INSTANTIATE_TEST_CASE_P(ConcatVertVecTestGPU, ConcatVertVecTest,