fixed bug for #1496 and correctness tests for function CheckRange

pull/13383/head
Marina Kolpakova 13 years ago
parent 8fcd0d9222
commit 32b9bc1d00
  1. 108
      modules/core/src/mathfuncs.cpp
  2. 87
      modules/core/test/test_math.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<int cv_mat_type> struct mat_type_assotiations{};
template<> struct mat_type_assotiations<CV_8U>
{
typedef unsigned char type;
static const type min_allowable = 0x0;
static const type max_allowable = 0xFF;
};
template<> struct mat_type_assotiations<CV_8S>
{
typedef signed char type;
static const type min_allowable = SCHAR_MIN;
static const type max_allowable = SCHAR_MAX;
};
template<> struct mat_type_assotiations<CV_16U>
{
typedef unsigned short type;
static const type min_allowable = 0x0;
static const type max_allowable = USHRT_MAX;
};
template<> struct mat_type_assotiations<CV_16S>
{
typedef signed short type;
static const type min_allowable = SHRT_MIN;
static const type max_allowable = SHRT_MAX;
};
template<> struct mat_type_assotiations<CV_32S>
{
typedef int type;
static const type min_allowable = (-INT_MAX - 1);
static const type max_allowable = INT_MAX;
};
template<int depth>
bool chackIntegerRang(cv::Mat src, Point& bad_pt, int minVal, int maxVal, double& bad_value)
{
typedef mat_type_assotiations<depth> 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<typename type_ass::type>(j ,i) <= minVal || as_one_channel.at<typename type_ass::type>(j ,i) >= maxVal)
{
bad_pt.y = j ;
bad_pt.x = i % src.channels();
bad_value = as_one_channel.at<typename type_ass::type>(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<CV_8U>,
&chackIntegerRang<CV_8S>,
&chackIntegerRang<CV_16U>,
&chackIntegerRang<CV_16S>,
&chackIntegerRang<CV_32S>
};
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
{

@ -2347,6 +2347,93 @@ void Core_SolvePolyTest::run( int )
}
}
template <typename T> class Core_CheckRange : public testing::Test {};
template<typename type> struct depth_for_type{};
template<> struct depth_for_type<unsigned char>
{
static const int depth = CV_8U;
};
template<> struct depth_for_type<signed char>
{
static const int depth = CV_8S;
};
template<> struct depth_for_type<unsigned short>
{
static const int depth = CV_16U;
};
template<> struct depth_for_type<signed short>
{
static const int depth = CV_16S;
};
template<> struct depth_for_type<signed int>
{
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<TypeParam>::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<TypeParam>::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<TypeParam>::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<signed char,unsigned char, signed short, unsigned short, signed int> mat_data_types;
INSTANTIATE_TYPED_TEST_CASE_P(Negative_Test, Core_CheckRange, mat_data_types);
/////////////////////////////////////////////////////////////////////////////////////////////////////

Loading…
Cancel
Save