From 5f269d08b462b96bde2b8d13afaa2b7b97a48a49 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 8 Jul 2016 17:46:08 +0300 Subject: [PATCH] bigdata: add test, resolve split/merge issue --- cmake/OpenCVModule.cmake | 4 ++++ cmake/OpenCVUtils.cmake | 10 ++++++++++ modules/core/src/convert.cpp | 29 +++++++++++++++++------------ modules/core/test/test_mat.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index ee14c79..197aead 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -1110,6 +1110,10 @@ function(ocv_add_accuracy_tests) set_target_properties(${the_target} PROPERTIES FOLDER "tests accuracy") endif() + if(OPENCV_TEST_BIGDATA) + ocv_append_target_property(${the_target} COMPILE_DEFINITIONS "OPENCV_TEST_BIGDATA=1") + endif() + if(NOT BUILD_opencv_world) _ocv_add_precompiled_headers(${the_target}) endif() diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index 309aad9..b1a099e 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -128,6 +128,16 @@ function(ocv_include_directories) include_directories(BEFORE ${__add_before}) endfunction() +function(ocv_append_target_property target prop) + get_target_property(val ${target} ${prop}) + if(val) + set(val "${val} ${ARGN}") + set_target_properties(${target} PROPERTIES ${prop} "${val}") + else() + set_target_properties(${target} PROPERTIES ${prop} "${ARGN}") + endif() +endfunction() + # adds include directories in such way that directories from the OpenCV source tree go first function(ocv_target_include_directories target) _ocv_fix_target(target) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index f41bfa1..1db170a 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -50,6 +50,7 @@ #define CV_NEON 0 #endif +#define CV_SPLIT_MERGE_MAX_BLOCK_SIZE(cn) ((INT_MAX/4)/cn) // HAL implementation accepts 'int' len, so INT_MAX doesn't work here /****************************************************************************************\ * split & merge * @@ -93,8 +94,8 @@ void cv::split(const Mat& src, Mat* mv) SplitFunc func = getSplitFunc(depth); CV_Assert( func != 0 ); - int esz = (int)src.elemSize(), esz1 = (int)src.elemSize1(); - int blocksize0 = (BLOCK_SIZE + esz-1)/esz; + size_t esz = src.elemSize(), esz1 = src.elemSize1(); + size_t blocksize0 = (BLOCK_SIZE + esz-1)/esz; AutoBuffer _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16); const Mat** arrays = (const Mat**)(uchar*)_buf; uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16); @@ -107,14 +108,15 @@ void cv::split(const Mat& src, Mat* mv) } NAryMatIterator it(arrays, ptrs, cn+1); - int total = (int)it.size, blocksize = cn <= 4 ? total : std::min(total, blocksize0); + size_t total = it.size; + size_t blocksize = std::min((size_t)CV_SPLIT_MERGE_MAX_BLOCK_SIZE(cn), cn <= 4 ? total : std::min(total, blocksize0)); for( size_t i = 0; i < it.nplanes; i++, ++it ) { - for( int j = 0; j < total; j += blocksize ) + for( size_t j = 0; j < total; j += blocksize ) { - int bsz = std::min(total - j, blocksize); - func( ptrs[0], &ptrs[1], bsz, cn ); + size_t bsz = std::min(total - j, blocksize); + func( ptrs[0], &ptrs[1], (int)bsz, cn ); if( j + blocksize < total ) { @@ -241,8 +243,11 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst) return; } + MergeFunc func = getMergeFunc(depth); + CV_Assert( func != 0 ); + size_t esz = dst.elemSize(), esz1 = dst.elemSize1(); - int blocksize0 = (int)((BLOCK_SIZE + esz-1)/esz); + size_t blocksize0 = (int)((BLOCK_SIZE + esz-1)/esz); AutoBuffer _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16); const Mat** arrays = (const Mat**)(uchar*)_buf; uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16); @@ -252,15 +257,15 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst) arrays[k+1] = &mv[k]; NAryMatIterator it(arrays, ptrs, cn+1); - int total = (int)it.size, blocksize = cn <= 4 ? total : std::min(total, blocksize0); - MergeFunc func = getMergeFunc(depth); + size_t total = (int)it.size; + size_t blocksize = std::min((size_t)CV_SPLIT_MERGE_MAX_BLOCK_SIZE(cn), cn <= 4 ? total : std::min(total, blocksize0)); for( i = 0; i < it.nplanes; i++, ++it ) { - for( int j = 0; j < total; j += blocksize ) + for( size_t j = 0; j < total; j += blocksize ) { - int bsz = std::min(total - j, blocksize); - func( (const uchar**)&ptrs[1], ptrs[0], bsz, cn ); + size_t bsz = std::min(total - j, blocksize); + func( (const uchar**)&ptrs[1], ptrs[0], (int)bsz, cn ); if( j + blocksize < total ) { diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index e2de324..1e64cdf 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -1483,3 +1483,29 @@ TEST(Mat, regression_5991) EXPECT_EQ(sz[2], mat.size[2]); EXPECT_EQ(0, cvtest::norm(mat, Mat(3, sz, CV_8U, Scalar(1)), NORM_INF)); } + +#ifdef OPENCV_TEST_BIGDATA +TEST(Mat, regression_6696_BigData_8Gb) +{ + int width = 60000; + int height = 10000; + + Mat destImageBGR = Mat(height, width, CV_8UC3, Scalar(1, 2, 3, 0)); + Mat destImageA = Mat(height, width, CV_8UC1, Scalar::all(4)); + + vector planes; + split(destImageBGR, planes); + planes.push_back(destImageA); + merge(planes, destImageBGR); + + EXPECT_EQ(1, destImageBGR.at(0)[0]); + EXPECT_EQ(2, destImageBGR.at(0)[1]); + EXPECT_EQ(3, destImageBGR.at(0)[2]); + EXPECT_EQ(4, destImageBGR.at(0)[3]); + + EXPECT_EQ(1, destImageBGR.at(height-1, width-1)[0]); + EXPECT_EQ(2, destImageBGR.at(height-1, width-1)[1]); + EXPECT_EQ(3, destImageBGR.at(height-1, width-1)[2]); + EXPECT_EQ(4, destImageBGR.at(height-1, width-1)[3]); +} +#endif -- 2.7.4