|
|
@ -46,7 +46,7 @@ namespace opencv_test { namespace { |
|
|
|
class CV_ThreshTest : public cvtest::ArrayTest |
|
|
|
class CV_ThreshTest : public cvtest::ArrayTest |
|
|
|
{ |
|
|
|
{ |
|
|
|
public: |
|
|
|
public: |
|
|
|
CV_ThreshTest(); |
|
|
|
CV_ThreshTest(int test_type = 0); |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
protected: |
|
|
|
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); |
|
|
|
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); |
|
|
@ -57,16 +57,22 @@ protected: |
|
|
|
int thresh_type; |
|
|
|
int thresh_type; |
|
|
|
double thresh_val; |
|
|
|
double thresh_val; |
|
|
|
double max_val; |
|
|
|
double max_val; |
|
|
|
|
|
|
|
int extra_type; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CV_ThreshTest::CV_ThreshTest() |
|
|
|
CV_ThreshTest::CV_ThreshTest(int test_type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
CV_Assert( (test_type & CV_THRESH_MASK) == 0 ); |
|
|
|
test_array[INPUT].push_back(NULL); |
|
|
|
test_array[INPUT].push_back(NULL); |
|
|
|
test_array[OUTPUT].push_back(NULL); |
|
|
|
test_array[OUTPUT].push_back(NULL); |
|
|
|
test_array[REF_OUTPUT].push_back(NULL); |
|
|
|
test_array[REF_OUTPUT].push_back(NULL); |
|
|
|
optional_mask = false; |
|
|
|
optional_mask = false; |
|
|
|
element_wise_relative_error = true; |
|
|
|
element_wise_relative_error = true; |
|
|
|
|
|
|
|
extra_type = test_type; |
|
|
|
|
|
|
|
// Reduce number of test with automated thresholding
|
|
|
|
|
|
|
|
if (extra_type != 0) |
|
|
|
|
|
|
|
test_case_count = 250; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -78,6 +84,12 @@ void CV_ThreshTest::get_test_array_types_and_sizes( int test_case_idx, |
|
|
|
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); |
|
|
|
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); |
|
|
|
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16S : depth == 2 ? CV_16U : depth == 3 ? CV_32F : CV_64F; |
|
|
|
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16S : depth == 2 ? CV_16U : depth == 3 ? CV_32F : CV_64F; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( extra_type == CV_THRESH_OTSU ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
depth = cvtest::randInt(rng) % 2 == 0 ? CV_8U : CV_16U; |
|
|
|
|
|
|
|
cn = 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn); |
|
|
|
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn); |
|
|
|
thresh_type = cvtest::randInt(rng) % 5; |
|
|
|
thresh_type = cvtest::randInt(rng) % 5; |
|
|
|
|
|
|
|
|
|
|
@ -123,18 +135,73 @@ double CV_ThreshTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, |
|
|
|
void CV_ThreshTest::run_func() |
|
|
|
void CV_ThreshTest::run_func() |
|
|
|
{ |
|
|
|
{ |
|
|
|
cvThreshold( test_array[INPUT][0], test_array[OUTPUT][0], |
|
|
|
cvThreshold( test_array[INPUT][0], test_array[OUTPUT][0], |
|
|
|
thresh_val, max_val, thresh_type ); |
|
|
|
thresh_val, max_val, thresh_type | extra_type); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static double compute_otsu_thresh(const Mat& _src) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int depth = _src.depth(); |
|
|
|
|
|
|
|
int width = _src.cols, height = _src.rows; |
|
|
|
|
|
|
|
const int N = 65536; |
|
|
|
|
|
|
|
std::vector<int> h(N, 0); |
|
|
|
|
|
|
|
int i, j; |
|
|
|
|
|
|
|
double mu = 0, scale = 1./(width*height); |
|
|
|
|
|
|
|
for(i = 0; i < height; ++i) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for(j = 0; j < width; ++j) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const int val = depth == CV_16UC1 ? (int)_src.at<ushort>(i, j) : (int)_src.at<uchar>(i,j); |
|
|
|
|
|
|
|
h[val]++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for( i = 0; i < N; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
mu += i*(double)h[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mu *= scale; |
|
|
|
|
|
|
|
double mu1 = 0, q1 = 0; |
|
|
|
|
|
|
|
double max_sigma = 0, max_val = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < N; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double p_i, q2, mu2, sigma; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p_i = h[i]*scale; |
|
|
|
|
|
|
|
mu1 *= q1; |
|
|
|
|
|
|
|
q1 += p_i; |
|
|
|
|
|
|
|
q2 = 1. - q1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( std::min(q1,q2) < FLT_EPSILON || std::max(q1,q2) > 1. - FLT_EPSILON ) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mu1 = (mu1 + i*p_i)/q1; |
|
|
|
|
|
|
|
mu2 = (mu - q1*mu1)/q2; |
|
|
|
|
|
|
|
sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2); |
|
|
|
|
|
|
|
if( sigma > max_sigma ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
max_sigma = sigma; |
|
|
|
|
|
|
|
max_val = i; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return max_val; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void test_threshold( const Mat& _src, Mat& _dst, |
|
|
|
static void test_threshold( const Mat& _src, Mat& _dst, |
|
|
|
double thresh, double maxval, int thresh_type ) |
|
|
|
double thresh, double maxval, int thresh_type, int extra_type ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i, j; |
|
|
|
int i, j; |
|
|
|
int depth = _src.depth(), cn = _src.channels(); |
|
|
|
int depth = _src.depth(), cn = _src.channels(); |
|
|
|
int width_n = _src.cols*cn, height = _src.rows; |
|
|
|
int width_n = _src.cols*cn, height = _src.rows; |
|
|
|
int ithresh = cvFloor(thresh); |
|
|
|
int ithresh = cvFloor(thresh); |
|
|
|
int imaxval, ithresh2; |
|
|
|
int imaxval, ithresh2; |
|
|
|
|
|
|
|
if (extra_type == CV_THRESH_OTSU) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
thresh = compute_otsu_thresh(_src); |
|
|
|
|
|
|
|
ithresh = cvFloor(thresh); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( depth == CV_8U ) |
|
|
|
if( depth == CV_8U ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -157,7 +224,7 @@ static void test_threshold( const Mat& _src, Mat& _dst, |
|
|
|
imaxval = cvRound(maxval); |
|
|
|
imaxval = cvRound(maxval); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
assert( depth == CV_8U || depth == CV_16S || depth == CV_16U || depth == CV_32F || depth == CV_64F ); |
|
|
|
CV_Assert( depth == CV_8U || depth == CV_16S || depth == CV_16U || depth == CV_32F || depth == CV_64F ); |
|
|
|
|
|
|
|
|
|
|
|
switch( thresh_type ) |
|
|
|
switch( thresh_type ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -415,10 +482,11 @@ static void test_threshold( const Mat& _src, Mat& _dst, |
|
|
|
void CV_ThreshTest::prepare_to_validation( int /*test_case_idx*/ ) |
|
|
|
void CV_ThreshTest::prepare_to_validation( int /*test_case_idx*/ ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
test_threshold( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], |
|
|
|
test_threshold( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], |
|
|
|
thresh_val, max_val, thresh_type ); |
|
|
|
thresh_val, max_val, thresh_type, extra_type ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TEST(Imgproc_Threshold, accuracy) { CV_ThreshTest test; test.safe_run(); } |
|
|
|
TEST(Imgproc_Threshold, accuracy) { CV_ThreshTest test; test.safe_run(); } |
|
|
|
|
|
|
|
TEST(Imgproc_Threshold, accuracyOtsu) { CV_ThreshTest test(CV_THRESH_OTSU); test.safe_run(); } |
|
|
|
|
|
|
|
|
|
|
|
BIGDATA_TEST(Imgproc_Threshold, huge) |
|
|
|
BIGDATA_TEST(Imgproc_Threshold, huge) |
|
|
|
{ |
|
|
|
{ |
|
|
|