From 32b9bc1d000fb1542b8547fed35aefdcf54a5b4b Mon Sep 17 00:00:00 2001 From: Marina Kolpakova Date: Wed, 28 Mar 2012 20:09:13 +0000 Subject: [PATCH] fixed bug for #1496 and correctness tests for function CheckRange --- modules/core/src/mathfuncs.cpp | 108 +++++++++++++++++++++++++++++++++------- modules/core/test/test_math.cpp | 87 ++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 19 deletions(-) diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 3f8308d..74c8364 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -1996,19 +1996,98 @@ void sqrt(InputArray a, OutputArray b) /************************** CheckArray for NaN's, Inf's *********************************/ -bool checkRange(InputArray _src, bool quiet, Point* pt, - double minVal, double maxVal) +template struct mat_type_assotiations{}; + +template<> struct mat_type_assotiations +{ + typedef unsigned char type; + static const type min_allowable = 0x0; + static const type max_allowable = 0xFF; +}; + +template<> struct mat_type_assotiations +{ + typedef signed char type; + static const type min_allowable = SCHAR_MIN; + static const type max_allowable = SCHAR_MAX; +}; + +template<> struct mat_type_assotiations +{ + typedef unsigned short type; + static const type min_allowable = 0x0; + static const type max_allowable = USHRT_MAX; +}; +template<> struct mat_type_assotiations +{ + typedef signed short type; + static const type min_allowable = SHRT_MIN; + static const type max_allowable = SHRT_MAX; +}; + +template<> struct mat_type_assotiations +{ + typedef int type; + static const type min_allowable = (-INT_MAX - 1); + static const type max_allowable = INT_MAX; +}; + +template +bool chackIntegerRang(cv::Mat src, Point& bad_pt, int minVal, int maxVal, double& bad_value) +{ + typedef mat_type_assotiations type_ass; + + if (minVal < type_ass::min_allowable && maxVal > type_ass::max_allowable) + { + return true; + } + else if (minVal >= type_ass::max_allowable || maxVal <= type_ass::min_allowable || maxVal <= minVal) + { + bad_pt = cv::Point(0,0); + return false; + } + cv::Mat as_one_channel = src.reshape(1,0); + + for (int j = 0; j < as_one_channel.rows; ++j) + for (int i = 0; i < as_one_channel.cols; ++i) + { + if (as_one_channel.at(j ,i) <= minVal || as_one_channel.at(j ,i) >= maxVal) + { + bad_pt.y = j ; + bad_pt.x = i % src.channels(); + bad_value = as_one_channel.at(j ,i); + return false; + } + } + bad_value = 0.0; + + return true; +} + +typedef bool (*check_pange_function)(cv::Mat src, Point& bad_pt, int minVal, int maxVal, double& bad_value); + +check_pange_function check_range_functions[] = +{ + &chackIntegerRang, + &chackIntegerRang, + &chackIntegerRang, + &chackIntegerRang, + &chackIntegerRang +}; + +bool checkRange(InputArray _src, bool quiet, Point* pt, double minVal, double maxVal) { Mat src = _src.getMat(); - if( src.dims > 2 ) + + if ( src.dims > 2 ) { const Mat* arrays[] = {&src, 0}; Mat planes[1]; NAryMatIterator it(arrays, planes); - for( size_t i = 0; i < it.nplanes; i++, ++it ) + for ( size_t i = 0; i < it.nplanes; i++, ++it ) { - if( !checkRange( it.planes[0], quiet, pt, minVal, maxVal )) + if (!checkRange( it.planes[0], quiet, pt, minVal, maxVal )) { // todo: set index properly return false; @@ -2021,21 +2100,12 @@ bool checkRange(InputArray _src, bool quiet, Point* pt, Point badPt(-1, -1); double badValue = 0; - if( depth < CV_32F ) + if (depth < CV_32F) { - double m = 0, M = 0; - Point mp, MP; - minMaxLoc(src.reshape(1,0), &m, &M, &mp, &MP); - if( M >= maxVal ) - { - badPt = MP; - badValue = M; - } - else if( m < minVal ) - { - badPt = mp; - badValue = m; - } + int minVali = cvFloor(minVal); + int maxVali = cvCeil(maxVal); + + (check_range_functions[depth])(src, badPt, minVali, maxVali, badValue); } else { diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index b7e36b1..af9c85d 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2347,6 +2347,93 @@ void Core_SolvePolyTest::run( int ) } } +template class Core_CheckRange : public testing::Test {}; + +template struct depth_for_type{}; + +template<> struct depth_for_type +{ + static const int depth = CV_8U; +}; + +template<> struct depth_for_type +{ + static const int depth = CV_8S; +}; + +template<> struct depth_for_type +{ + static const int depth = CV_16U; +}; + +template<> struct depth_for_type +{ + static const int depth = CV_16S; +}; + +template<> struct depth_for_type +{ + static const int depth = CV_32S; +}; + + +TYPED_TEST_CASE_P(Core_CheckRange); + +TYPED_TEST_P(Core_CheckRange, Negative) +{ + double min_bound = 4.5; + double max_bound = 16.0; + + TypeParam data[] = {5, 10, 15, 4, 10 ,2, 8, 12, 14}; + cv::Mat src = cv::Mat(3,3, depth_for_type::depth, data); + + cv::Point* bad_pt = new cv::Point(0, 0); + + ASSERT_FALSE(checkRange(src, true, bad_pt, min_bound, max_bound)); + ASSERT_EQ(bad_pt->x,0); + ASSERT_EQ(bad_pt->y,1); + + delete bad_pt; +} + +TYPED_TEST_P(Core_CheckRange, Positive) +{ + double min_bound = -1; + double max_bound = 16.0; + + TypeParam data[] = {5, 10, 15, 4, 10 ,2, 8, 12, 14}; + cv::Mat src = cv::Mat(3,3, depth_for_type::depth, data); + + cv::Point* bad_pt = new cv::Point(0, 0); + + ASSERT_TRUE(checkRange(src, true, bad_pt, min_bound, max_bound)); + ASSERT_EQ(bad_pt->x,0); + ASSERT_EQ(bad_pt->y,0); + + delete bad_pt; +} + +TYPED_TEST_P(Core_CheckRange, Bounds) +{ + double min_bound = 24.5; + double max_bound = 1.0; + + TypeParam data[] = {5, 10, 15, 4, 10 ,2, 8, 12, 14}; + cv::Mat src = cv::Mat(3,3, depth_for_type::depth, data); + + cv::Point* bad_pt = new cv::Point(0, 0); + + ASSERT_FALSE(checkRange(src, true, bad_pt, min_bound, max_bound)); + ASSERT_EQ(bad_pt->x,0); + ASSERT_EQ(bad_pt->y,0); + + delete bad_pt; +} + +REGISTER_TYPED_TEST_CASE_P(Core_CheckRange, Negative, Positive, Bounds); + +typedef ::testing::Types mat_data_types; +INSTANTIATE_TYPED_TEST_CASE_P(Negative_Test, Core_CheckRange, mat_data_types); ///////////////////////////////////////////////////////////////////////////////////////////////////// -- 2.7.4