2011-02-10 04:55:11 +08:00
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
# include "test_precomp.hpp"
2017-11-05 21:48:40 +08:00
namespace opencv_test { namespace {
2011-02-10 04:55:11 +08:00
class CV_ThreshTest : public cvtest : : ArrayTest
{
public :
CV_ThreshTest ( ) ;
protected :
void get_test_array_types_and_sizes ( int test_case_idx , vector < vector < Size > > & sizes , vector < vector < int > > & types ) ;
double get_success_error_level ( int test_case_idx , int i , int j ) ;
void run_func ( ) ;
void prepare_to_validation ( int ) ;
int thresh_type ;
2016-05-17 21:57:05 +08:00
double thresh_val ;
double max_val ;
2011-02-10 04:55:11 +08:00
} ;
CV_ThreshTest : : CV_ThreshTest ( )
{
test_array [ INPUT ] . push_back ( NULL ) ;
test_array [ OUTPUT ] . push_back ( NULL ) ;
test_array [ REF_OUTPUT ] . push_back ( NULL ) ;
optional_mask = false ;
element_wise_relative_error = true ;
}
void CV_ThreshTest : : get_test_array_types_and_sizes ( int test_case_idx ,
vector < vector < Size > > & sizes , vector < vector < int > > & types )
{
RNG & rng = ts - > get_rng ( ) ;
2017-09-18 20:42:44 +08:00
int depth = cvtest : : randInt ( rng ) % 5 , cn = cvtest : : randInt ( rng ) % 4 + 1 ;
2011-02-10 04:55:11 +08:00
cvtest : : ArrayTest : : get_test_array_types_and_sizes ( test_case_idx , sizes , types ) ;
2017-09-18 20:42:44 +08:00
depth = depth = = 0 ? CV_8U : depth = = 1 ? CV_16S : depth = = 2 ? CV_16U : depth = = 3 ? CV_32F : CV_64F ;
2011-02-10 04:55:11 +08:00
types [ INPUT ] [ 0 ] = types [ OUTPUT ] [ 0 ] = types [ REF_OUTPUT ] [ 0 ] = CV_MAKETYPE ( depth , cn ) ;
thresh_type = cvtest : : randInt ( rng ) % 5 ;
if ( depth = = CV_8U )
{
2016-05-26 07:38:29 +08:00
thresh_val = ( cvtest : : randReal ( rng ) * 350. - 50. ) ;
max_val = ( cvtest : : randReal ( rng ) * 350. - 50. ) ;
2011-02-10 04:55:11 +08:00
if ( cvtest : : randInt ( rng ) % 4 = = 0 )
2011-11-22 23:16:45 +08:00
max_val = 255.f ;
}
else if ( depth = = CV_16S )
{
2016-05-26 07:38:29 +08:00
double min_val = SHRT_MIN - 100.f ;
2012-06-15 21:04:17 +08:00
max_val = SHRT_MAX + 100.f ;
2016-05-26 07:38:29 +08:00
thresh_val = ( cvtest : : randReal ( rng ) * ( max_val - min_val ) + min_val ) ;
max_val = ( cvtest : : randReal ( rng ) * ( max_val - min_val ) + min_val ) ;
2011-11-22 23:16:45 +08:00
if ( cvtest : : randInt ( rng ) % 4 = = 0 )
2016-05-26 07:38:29 +08:00
max_val = ( double ) SHRT_MAX ;
2011-02-10 04:55:11 +08:00
}
2017-09-18 20:42:44 +08:00
else if ( depth = = CV_16U )
{
double min_val = - 100.f ;
max_val = USHRT_MAX + 100.f ;
thresh_val = ( cvtest : : randReal ( rng ) * ( max_val - min_val ) + min_val ) ;
max_val = ( cvtest : : randReal ( rng ) * ( max_val - min_val ) + min_val ) ;
if ( cvtest : : randInt ( rng ) % 4 = = 0 )
max_val = ( double ) USHRT_MAX ;
}
2011-02-10 04:55:11 +08:00
else
{
2016-05-26 07:38:29 +08:00
thresh_val = ( cvtest : : randReal ( rng ) * 1000. - 500. ) ;
max_val = ( cvtest : : randReal ( rng ) * 1000. - 500. ) ;
2011-02-10 04:55:11 +08:00
}
}
double CV_ThreshTest : : get_success_error_level ( int /*test_case_idx*/ , int /*i*/ , int /*j*/ )
{
return FLT_EPSILON * 10 ;
}
void CV_ThreshTest : : run_func ( )
{
cvThreshold ( test_array [ INPUT ] [ 0 ] , test_array [ OUTPUT ] [ 0 ] ,
thresh_val , max_val , thresh_type ) ;
}
static void test_threshold ( const Mat & _src , Mat & _dst ,
2016-05-17 21:57:05 +08:00
double thresh , double maxval , int thresh_type )
2011-02-10 04:55:11 +08:00
{
int i , j ;
int depth = _src . depth ( ) , cn = _src . channels ( ) ;
int width_n = _src . cols * cn , height = _src . rows ;
2012-03-02 16:34:54 +08:00
int ithresh = cvFloor ( thresh ) ;
int imaxval , ithresh2 ;
2012-10-17 07:18:30 +08:00
2011-11-22 23:16:45 +08:00
if ( depth = = CV_8U )
{
ithresh2 = saturate_cast < uchar > ( ithresh ) ;
2012-03-02 16:34:54 +08:00
imaxval = saturate_cast < uchar > ( maxval ) ;
2011-11-22 23:16:45 +08:00
}
else if ( depth = = CV_16S )
{
ithresh2 = saturate_cast < short > ( ithresh ) ;
2012-03-02 16:34:54 +08:00
imaxval = saturate_cast < short > ( maxval ) ;
}
2017-09-18 20:42:44 +08:00
else if ( depth = = CV_16U )
{
ithresh2 = saturate_cast < ushort > ( ithresh ) ;
imaxval = saturate_cast < ushort > ( maxval ) ;
}
2012-03-02 16:34:54 +08:00
else
{
ithresh2 = cvRound ( ithresh ) ;
imaxval = cvRound ( maxval ) ;
2011-11-22 23:16:45 +08:00
}
2011-02-10 04:55:11 +08:00
2017-09-18 20:42:44 +08:00
assert ( depth = = CV_8U | | depth = = CV_16S | | depth = = CV_16U | | depth = = CV_32F | | depth = = CV_64F ) ;
2012-10-17 07:18:30 +08:00
2011-02-10 04:55:11 +08:00
switch ( thresh_type )
{
case CV_THRESH_BINARY :
2011-11-22 23:16:45 +08:00
for ( i = 0 ; i < height ; i + + )
2011-02-10 04:55:11 +08:00
{
if ( depth = = CV_8U )
2011-11-22 23:16:45 +08:00
{
const uchar * src = _src . ptr < uchar > ( i ) ;
uchar * dst = _dst . ptr < uchar > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = ( uchar ) ( src [ j ] > ithresh ? imaxval : 0 ) ;
2011-11-22 23:16:45 +08:00
}
else if ( depth = = CV_16S )
{
const short * src = _src . ptr < short > ( i ) ;
short * dst = _dst . ptr < short > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = ( short ) ( src [ j ] > ithresh ? imaxval : 0 ) ;
}
2017-09-18 20:42:44 +08:00
else if ( depth = = CV_16U )
{
const ushort * src = _src . ptr < ushort > ( i ) ;
ushort * dst = _dst . ptr < ushort > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = ( ushort ) ( src [ j ] > ithresh ? imaxval : 0 ) ;
}
2016-05-17 21:57:05 +08:00
else if ( depth = = CV_32F )
2011-11-22 23:16:45 +08:00
{
const float * src = _src . ptr < float > ( i ) ;
float * dst = _dst . ptr < float > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
2016-05-17 23:34:51 +08:00
dst [ j ] = ( float ) ( src [ j ] > thresh ? maxval : 0.f ) ;
2011-11-22 23:16:45 +08:00
}
2016-05-17 21:57:05 +08:00
else
{
const double * src = _src . ptr < double > ( i ) ;
double * dst = _dst . ptr < double > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = src [ j ] > thresh ? maxval : 0.0 ;
}
2011-02-10 04:55:11 +08:00
}
break ;
case CV_THRESH_BINARY_INV :
2011-11-22 23:16:45 +08:00
for ( i = 0 ; i < height ; i + + )
2011-02-10 04:55:11 +08:00
{
if ( depth = = CV_8U )
2011-11-22 23:16:45 +08:00
{
const uchar * src = _src . ptr < uchar > ( i ) ;
uchar * dst = _dst . ptr < uchar > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = ( uchar ) ( src [ j ] > ithresh ? 0 : imaxval ) ;
2011-11-22 23:16:45 +08:00
}
else if ( depth = = CV_16S )
{
const short * src = _src . ptr < short > ( i ) ;
short * dst = _dst . ptr < short > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = ( short ) ( src [ j ] > ithresh ? 0 : imaxval ) ;
}
2017-09-18 20:42:44 +08:00
else if ( depth = = CV_16U )
{
const ushort * src = _src . ptr < ushort > ( i ) ;
ushort * dst = _dst . ptr < ushort > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = ( ushort ) ( src [ j ] > ithresh ? 0 : imaxval ) ;
}
2016-05-17 21:57:05 +08:00
else if ( depth = = CV_32F )
2011-11-22 23:16:45 +08:00
{
const float * src = _src . ptr < float > ( i ) ;
float * dst = _dst . ptr < float > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
2016-05-17 23:34:51 +08:00
dst [ j ] = ( float ) ( src [ j ] > thresh ? 0.f : maxval ) ;
2011-11-22 23:16:45 +08:00
}
2016-05-17 21:57:05 +08:00
else
{
const double * src = _src . ptr < double > ( i ) ;
double * dst = _dst . ptr < double > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
dst [ j ] = src [ j ] > thresh ? 0.0 : maxval ;
}
2011-02-10 04:55:11 +08:00
}
break ;
case CV_THRESH_TRUNC :
2011-11-22 23:16:45 +08:00
for ( i = 0 ; i < height ; i + + )
2011-02-10 04:55:11 +08:00
{
if ( depth = = CV_8U )
2011-11-22 23:16:45 +08:00
{
const uchar * src = _src . ptr < uchar > ( i ) ;
uchar * dst = _dst . ptr < uchar > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( uchar ) ( s > ithresh ? ithresh2 : s ) ;
}
2011-11-22 23:16:45 +08:00
}
else if ( depth = = CV_16S )
{
const short * src = _src . ptr < short > ( i ) ;
short * dst = _dst . ptr < short > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( short ) ( s > ithresh ? ithresh2 : s ) ;
}
}
2017-09-18 20:42:44 +08:00
else if ( depth = = CV_16U )
{
const ushort * src = _src . ptr < ushort > ( i ) ;
ushort * dst = _dst . ptr < ushort > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( ushort ) ( s > ithresh ? ithresh2 : s ) ;
}
}
2016-05-17 21:57:05 +08:00
else if ( depth = = CV_32F )
2011-11-22 23:16:45 +08:00
{
const float * src = _src . ptr < float > ( i ) ;
float * dst = _dst . ptr < float > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
{
2011-11-22 23:16:45 +08:00
float s = src [ j ] ;
2016-05-17 23:34:51 +08:00
dst [ j ] = ( float ) ( s > thresh ? thresh : s ) ;
2011-02-10 04:55:11 +08:00
}
2011-11-22 23:16:45 +08:00
}
2016-05-17 21:57:05 +08:00
else
{
const double * src = _src . ptr < double > ( i ) ;
double * dst = _dst . ptr < double > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
double s = src [ j ] ;
dst [ j ] = s > thresh ? thresh : s ;
}
}
2011-02-10 04:55:11 +08:00
}
break ;
case CV_THRESH_TOZERO :
2011-11-22 23:16:45 +08:00
for ( i = 0 ; i < height ; i + + )
2011-02-10 04:55:11 +08:00
{
if ( depth = = CV_8U )
2011-11-22 23:16:45 +08:00
{
const uchar * src = _src . ptr < uchar > ( i ) ;
uchar * dst = _dst . ptr < uchar > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( uchar ) ( s > ithresh ? s : 0 ) ;
}
2011-11-22 23:16:45 +08:00
}
else if ( depth = = CV_16S )
{
const short * src = _src . ptr < short > ( i ) ;
short * dst = _dst . ptr < short > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( short ) ( s > ithresh ? s : 0 ) ;
}
}
2017-09-18 20:42:44 +08:00
else if ( depth = = CV_16U )
{
const ushort * src = _src . ptr < ushort > ( i ) ;
ushort * dst = _dst . ptr < ushort > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( ushort ) ( s > ithresh ? s : 0 ) ;
}
}
2016-05-17 21:57:05 +08:00
else if ( depth = = CV_32F )
2011-11-22 23:16:45 +08:00
{
const float * src = _src . ptr < float > ( i ) ;
float * dst = _dst . ptr < float > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
{
2011-11-22 23:16:45 +08:00
float s = src [ j ] ;
dst [ j ] = s > thresh ? s : 0.f ;
2011-02-10 04:55:11 +08:00
}
2011-11-22 23:16:45 +08:00
}
2016-05-17 21:57:05 +08:00
else
{
const double * src = _src . ptr < double > ( i ) ;
double * dst = _dst . ptr < double > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
double s = src [ j ] ;
dst [ j ] = s > thresh ? s : 0.0 ;
}
}
2011-02-10 04:55:11 +08:00
}
break ;
case CV_THRESH_TOZERO_INV :
2011-11-22 23:16:45 +08:00
for ( i = 0 ; i < height ; i + + )
2011-02-10 04:55:11 +08:00
{
if ( depth = = CV_8U )
2011-11-22 23:16:45 +08:00
{
const uchar * src = _src . ptr < uchar > ( i ) ;
uchar * dst = _dst . ptr < uchar > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( uchar ) ( s > ithresh ? 0 : s ) ;
}
2011-11-22 23:16:45 +08:00
}
else if ( depth = = CV_16S )
{
const short * src = _src . ptr < short > ( i ) ;
short * dst = _dst . ptr < short > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( short ) ( s > ithresh ? 0 : s ) ;
}
2017-09-18 20:42:44 +08:00
}
else if ( depth = = CV_16U )
{
const ushort * src = _src . ptr < ushort > ( i ) ;
ushort * dst = _dst . ptr < ushort > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
int s = src [ j ] ;
dst [ j ] = ( ushort ) ( s > ithresh ? 0 : s ) ;
}
2011-11-22 23:16:45 +08:00
}
2016-05-17 21:57:05 +08:00
else if ( depth = = CV_32F )
2011-11-22 23:16:45 +08:00
{
const float * src = _src . ptr < float > ( i ) ;
float * dst = _dst . ptr < float > ( i ) ;
2011-02-10 04:55:11 +08:00
for ( j = 0 ; j < width_n ; j + + )
{
2011-11-22 23:16:45 +08:00
float s = src [ j ] ;
dst [ j ] = s > thresh ? 0.f : s ;
2011-02-10 04:55:11 +08:00
}
2011-11-22 23:16:45 +08:00
}
2016-05-17 21:57:05 +08:00
else
{
const double * src = _src . ptr < double > ( i ) ;
double * dst = _dst . ptr < double > ( i ) ;
for ( j = 0 ; j < width_n ; j + + )
{
double s = src [ j ] ;
dst [ j ] = s > thresh ? 0.0 : s ;
}
}
2011-02-10 04:55:11 +08:00
}
break ;
default :
assert ( 0 ) ;
}
}
void CV_ThreshTest : : prepare_to_validation ( int /*test_case_idx*/ )
{
test_threshold ( test_mat [ INPUT ] [ 0 ] , test_mat [ REF_OUTPUT ] [ 0 ] ,
thresh_val , max_val , thresh_type ) ;
}
TEST ( Imgproc_Threshold , accuracy ) { CV_ThreshTest test ; test . safe_run ( ) ; }
2017-11-05 21:48:40 +08:00
2018-05-14 20:29:14 +08:00
# if defined(_M_X64) || defined(__x86_64__)
TEST ( Imgproc_Threshold , huge ) /* since the test needs a lot of memory, enable it only on 64-bit Intel/AMD platforms, otherwise it may take a lot of time because of heavy swapping */
# else
TEST ( DISABLED_Imgproc_Threshold , huge )
# endif
{
Mat m ;
try
{
m . create ( 65000 , 40000 , CV_8U ) ;
}
catch ( . . . )
{
}
if ( ! m . empty ( ) )
{
ASSERT_FALSE ( m . isContinuous ( ) ) ;
uint64 i , n = ( uint64 ) m . rows * m . cols ;
for ( i = 0 ; i < n ; i + + )
m . data [ i ] = ( uchar ) ( i & 255 ) ;
cv : : threshold ( m , m , 127 , 255 , cv : : THRESH_BINARY ) ;
int nz = cv : : countNonZero ( m ) ;
ASSERT_EQ ( nz , ( int ) ( n / 2 ) ) ;
}
// just skip the test if there is no enough memory
}
2017-11-05 21:48:40 +08:00
} } // namespace