From bf128550073cd079b576d6fd82205b297f209b59 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Wed, 28 Mar 2012 09:07:00 +0000 Subject: [PATCH] fixed mask operations with uninitialized output array, added the corresponding test (ticket #1286) --- modules/core/src/arithm.cpp | 15 +++++++ modules/core/test/test_arithm.cpp | 86 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 01e1f4f..97c8659 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1027,6 +1027,7 @@ void binary_op(InputArray _src1, InputArray _src2, OutputArray _dst, int cn = src1.channels(); BinaryFunc copymask = 0; Mat mask; + bool reallocate = false; if( haveMask ) { @@ -1034,6 +1035,8 @@ void binary_op(InputArray _src1, InputArray _src2, OutputArray _dst, CV_Assert( (mask.type() == CV_8UC1 || mask.type() == CV_8SC1) ); CV_Assert( mask.size == src1.size ); copymask = getCopyMaskFunc(esz); + Mat tdst = _dst.getMat(); + reallocate = tdst.size != src1.size || tdst.type() != src1.type(); } AutoBuffer _buf; @@ -1041,6 +1044,11 @@ void binary_op(InputArray _src1, InputArray _src2, OutputArray _dst, _dst.create(src1.dims, src1.size, src1.type()); Mat dst = _dst.getMat(); + + // if this is mask operation and dst has been reallocated, + // we have to + if( haveMask && reallocate ) + dst = Scalar::all(0); if( bitwise ) { @@ -1214,6 +1222,7 @@ void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, int kind1 = _src1.kind(), kind2 = _src2.kind(); Mat src1 = _src1.getMat(), src2 = _src2.getMat(); bool haveMask = !_mask.empty(); + bool reallocate = false; if( kind1 == kind2 && src1.dims <= 2 && src2.dims <= 2 && src1.size() == src2.size() && src1.type() == src2.type() && @@ -1302,6 +1311,8 @@ void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, CV_Assert( (mask.type() == CV_8UC1 || mask.type() == CV_8SC1) ); CV_Assert( mask.size == src1.size ); copymask = getCopyMaskFunc(dsz); + Mat tdst = _dst.getMat(); + reallocate = tdst.size != src1.size || tdst.type() != dtype; } AutoBuffer _buf; @@ -1310,6 +1321,10 @@ void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, _dst.create(src1.dims, src1.size, dtype); Mat dst = _dst.getMat(); + + if( haveMask && reallocate ) + dst = Scalar::all(0); + BinaryFunc func = tab[CV_MAT_DEPTH(wtype)]; if( !haveScalar ) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index d59dc7b..1c6b76c 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1402,4 +1402,90 @@ INSTANTIATE_TEST_CASE_P(Core_MinMaxLoc, ElemWiseTest, ::testing::Values(ElemWise INSTANTIATE_TEST_CASE_P(Core_CartToPolarToCart, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CartToPolarToCartOp))); +class CV_ArithmMaskTest : public cvtest::BaseTest +{ +public: + CV_ArithmMaskTest() {} + ~CV_ArithmMaskTest() {} +protected: + void run(int) + { + try + { + RNG& rng = theRNG(); + const int MAX_DIM=3; + int sizes[MAX_DIM]; + for( int iter = 0; iter < 100; iter++ ) + { + //ts->printf(cvtest::TS::LOG, "."); + + ts->update_context(this, iter, true); + int k, dims = rng.uniform(1, MAX_DIM+1), p = 1; + int depth = rng.uniform(CV_8U, CV_64F+1); + int cn = rng.uniform(1, 6); + int type = CV_MAKETYPE(depth, cn); + int op = rng.uniform(0, 5); + int depth1 = op <= 1 ? CV_64F : depth; + for( k = 0; k < dims; k++ ) + { + sizes[k] = rng.uniform(1, 30); + p *= sizes[k]; + } + Mat a(dims, sizes, type), a1; + Mat b(dims, sizes, type), b1; + Mat mask(dims, sizes, CV_8U); + Mat mask1; + Mat c, d; + + // [-2,2) range means that the each generated random number + // will be one of -2, -1, 0, 1. Saturated to [0,255], it will become + // 0, 0, 0, 1 => the mask will be filled by ~25%. + rng.fill(mask, RNG::UNIFORM, -2, 2); + + a.convertTo(a1, depth1); + b.convertTo(b1, depth1); + // invert the mask + compare(mask, 0, mask1, CMP_EQ); + a1.setTo(0, mask1); + b1.setTo(0, mask1); + + if( op == 0 ) + { + add(a, b, c, mask); + add(a1, b1, d); + } + else if( op == 1 ) + { + subtract(a, b, c, mask); + subtract(a1, b1, d); + } + else if( op == 2 ) + { + bitwise_and(a, b, c, mask); + bitwise_and(a1, b1, d); + } + else if( op == 3 ) + { + bitwise_or(a, b, c, mask); + bitwise_or(a1, b1, d); + } + else if( op == 4 ) + { + bitwise_xor(a, b, c, mask); + bitwise_xor(a1, b1, d); + } + Mat d1; + d.convertTo(d1, depth); + CV_Assert( norm(c, d1, CV_C) == 0 ); + } + } + catch(...) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + } + } +}; + +TEST(Core_ArithmMask, uninitialized) { CV_ArithmMaskTest test; test.safe_run(); } + -- 2.7.4