2011-02-10 04:55:11 +08:00
# include "test_precomp.hpp"
2013-04-03 00:59:43 +08:00
# include <map>
2011-02-10 04:55:11 +08:00
using namespace cv ;
using namespace std ;
class Core_ReduceTest : public cvtest : : BaseTest
{
public :
2014-01-18 05:30:29 +08:00
Core_ReduceTest ( ) { }
2011-02-10 04:55:11 +08:00
protected :
void run ( int ) ;
2012-04-14 05:50:59 +08:00
int checkOp ( const Mat & src , int dstType , int opType , const Mat & opRes , int dim ) ;
2011-02-10 04:55:11 +08:00
int checkCase ( int srcType , int dstType , int dim , Size sz ) ;
int checkDim ( int dim , Size sz ) ;
int checkSize ( Size sz ) ;
} ;
template < class Type >
void testReduce ( const Mat & src , Mat & sum , Mat & avg , Mat & max , Mat & min , int dim )
{
assert ( src . channels ( ) = = 1 ) ;
if ( dim = = 0 ) // row
{
2012-06-09 23:00:04 +08:00
sum . create ( 1 , src . cols , CV_64FC1 ) ;
2011-02-10 04:55:11 +08:00
max . create ( 1 , src . cols , CV_64FC1 ) ;
min . create ( 1 , src . cols , CV_64FC1 ) ;
}
else
{
2012-06-09 23:00:04 +08:00
sum . create ( src . rows , 1 , CV_64FC1 ) ;
2011-02-10 04:55:11 +08:00
max . create ( src . rows , 1 , CV_64FC1 ) ;
min . create ( src . rows , 1 , CV_64FC1 ) ;
}
sum . setTo ( Scalar ( 0 ) ) ;
max . setTo ( Scalar ( - DBL_MAX ) ) ;
min . setTo ( Scalar ( DBL_MAX ) ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
const Mat_ < Type > & src_ = src ;
Mat_ < double > & sum_ = ( Mat_ < double > & ) sum ;
Mat_ < double > & min_ = ( Mat_ < double > & ) min ;
Mat_ < double > & max_ = ( Mat_ < double > & ) max ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
if ( dim = = 0 )
{
for ( int ri = 0 ; ri < src . rows ; ri + + )
{
for ( int ci = 0 ; ci < src . cols ; ci + + )
{
sum_ ( 0 , ci ) + = src_ ( ri , ci ) ;
max_ ( 0 , ci ) = std : : max ( max_ ( 0 , ci ) , ( double ) src_ ( ri , ci ) ) ;
min_ ( 0 , ci ) = std : : min ( min_ ( 0 , ci ) , ( double ) src_ ( ri , ci ) ) ;
}
}
}
else
{
for ( int ci = 0 ; ci < src . cols ; ci + + )
{
for ( int ri = 0 ; ri < src . rows ; ri + + )
{
sum_ ( ri , 0 ) + = src_ ( ri , ci ) ;
max_ ( ri , 0 ) = std : : max ( max_ ( ri , 0 ) , ( double ) src_ ( ri , ci ) ) ;
min_ ( ri , 0 ) = std : : min ( min_ ( ri , 0 ) , ( double ) src_ ( ri , ci ) ) ;
}
}
}
sum . convertTo ( avg , CV_64FC1 ) ;
avg = avg * ( 1.0 / ( dim = = 0 ? ( double ) src . rows : ( double ) src . cols ) ) ;
}
void getMatTypeStr ( int type , string & str )
{
str = type = = CV_8UC1 ? " CV_8UC1 " :
type = = CV_8SC1 ? " CV_8SC1 " :
type = = CV_16UC1 ? " CV_16UC1 " :
type = = CV_16SC1 ? " CV_16SC1 " :
type = = CV_32SC1 ? " CV_32SC1 " :
type = = CV_32FC1 ? " CV_32FC1 " :
type = = CV_64FC1 ? " CV_64FC1 " : " unsupported matrix type " ;
}
2012-04-14 05:50:59 +08:00
int Core_ReduceTest : : checkOp ( const Mat & src , int dstType , int opType , const Mat & opRes , int dim )
2011-02-10 04:55:11 +08:00
{
int srcType = src . type ( ) ;
bool support = false ;
if ( opType = = CV_REDUCE_SUM | | opType = = CV_REDUCE_AVG )
{
if ( srcType = = CV_8U & & ( dstType = = CV_32S | | dstType = = CV_32F | | dstType = = CV_64F ) )
support = true ;
if ( srcType = = CV_16U & & ( dstType = = CV_32F | | dstType = = CV_64F ) )
support = true ;
if ( srcType = = CV_16S & & ( dstType = = CV_32F | | dstType = = CV_64F ) )
support = true ;
if ( srcType = = CV_32F & & ( dstType = = CV_32F | | dstType = = CV_64F ) )
support = true ;
if ( srcType = = CV_64F & & dstType = = CV_64F )
support = true ;
}
else if ( opType = = CV_REDUCE_MAX )
{
if ( srcType = = CV_8U & & dstType = = CV_8U )
support = true ;
if ( srcType = = CV_32F & & dstType = = CV_32F )
support = true ;
if ( srcType = = CV_64F & & dstType = = CV_64F )
support = true ;
}
else if ( opType = = CV_REDUCE_MIN )
{
if ( srcType = = CV_8U & & dstType = = CV_8U )
support = true ;
if ( srcType = = CV_32F & & dstType = = CV_32F )
support = true ;
if ( srcType = = CV_64F & & dstType = = CV_64F )
support = true ;
}
if ( ! support )
return cvtest : : TS : : OK ;
2012-04-14 05:50:59 +08:00
double eps = 0.0 ;
if ( opType = = CV_REDUCE_SUM | | opType = = CV_REDUCE_AVG )
{
if ( dstType = = CV_32F )
eps = 1.e-5 ;
else if ( dstType = = CV_64F )
eps = 1.e-8 ;
else if ( dstType = = CV_32S )
eps = 0.6 ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
assert ( opRes . type ( ) = = CV_64FC1 ) ;
2012-04-14 05:50:59 +08:00
Mat _dst , dst , diff ;
2017-10-11 15:50:22 +08:00
cv : : reduce ( src , _dst , dim , opType , dstType ) ;
2011-02-10 04:55:11 +08:00
_dst . convertTo ( dst , CV_64FC1 ) ;
2012-04-14 05:50:59 +08:00
absdiff ( opRes , dst , diff ) ;
bool check = false ;
if ( dstType = = CV_32F | | dstType = = CV_64F )
check = countNonZero ( diff > eps * dst ) > 0 ;
else
check = countNonZero ( diff > eps ) > 0 ;
if ( check )
2011-02-10 04:55:11 +08:00
{
char msg [ 100 ] ;
const char * opTypeStr = opType = = CV_REDUCE_SUM ? " CV_REDUCE_SUM " :
opType = = CV_REDUCE_AVG ? " CV_REDUCE_AVG " :
opType = = CV_REDUCE_MAX ? " CV_REDUCE_MAX " :
opType = = CV_REDUCE_MIN ? " CV_REDUCE_MIN " : " unknown operation type " ;
string srcTypeStr , dstTypeStr ;
getMatTypeStr ( src . type ( ) , srcTypeStr ) ;
getMatTypeStr ( dstType , dstTypeStr ) ;
const char * dimStr = dim = = 0 ? " ROWS " : " COLS " ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
sprintf ( msg , " bad accuracy with srcType = %s, dstType = %s, opType = %s, dim = %s " ,
srcTypeStr . c_str ( ) , dstTypeStr . c_str ( ) , opTypeStr , dimStr ) ;
ts - > printf ( cvtest : : TS : : LOG , msg ) ;
return cvtest : : TS : : FAIL_BAD_ACCURACY ;
}
return cvtest : : TS : : OK ;
}
int Core_ReduceTest : : checkCase ( int srcType , int dstType , int dim , Size sz )
{
int code = cvtest : : TS : : OK , tempCode ;
Mat src , sum , avg , max , min ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
src . create ( sz , srcType ) ;
randu ( src , Scalar ( 0 ) , Scalar ( 100 ) ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
if ( srcType = = CV_8UC1 )
testReduce < uchar > ( src , sum , avg , max , min , dim ) ;
else if ( srcType = = CV_8SC1 )
testReduce < char > ( src , sum , avg , max , min , dim ) ;
else if ( srcType = = CV_16UC1 )
testReduce < unsigned short int > ( src , sum , avg , max , min , dim ) ;
else if ( srcType = = CV_16SC1 )
testReduce < short int > ( src , sum , avg , max , min , dim ) ;
else if ( srcType = = CV_32SC1 )
testReduce < int > ( src , sum , avg , max , min , dim ) ;
else if ( srcType = = CV_32FC1 )
testReduce < float > ( src , sum , avg , max , min , dim ) ;
else if ( srcType = = CV_64FC1 )
testReduce < double > ( src , sum , avg , max , min , dim ) ;
2012-06-09 23:00:04 +08:00
else
2011-02-10 04:55:11 +08:00
assert ( 0 ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// 1. sum
2012-04-14 05:50:59 +08:00
tempCode = checkOp ( src , dstType , CV_REDUCE_SUM , sum , dim ) ;
2011-02-10 04:55:11 +08:00
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// 2. avg
2012-04-14 05:50:59 +08:00
tempCode = checkOp ( src , dstType , CV_REDUCE_AVG , avg , dim ) ;
2011-02-10 04:55:11 +08:00
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// 3. max
2012-04-14 05:50:59 +08:00
tempCode = checkOp ( src , dstType , CV_REDUCE_MAX , max , dim ) ;
2011-02-10 04:55:11 +08:00
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// 4. min
2012-04-14 05:50:59 +08:00
tempCode = checkOp ( src , dstType , CV_REDUCE_MIN , min , dim ) ;
2011-02-10 04:55:11 +08:00
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
return code ;
}
int Core_ReduceTest : : checkDim ( int dim , Size sz )
{
int code = cvtest : : TS : : OK , tempCode ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// CV_8UC1
tempCode = checkCase ( CV_8UC1 , CV_8UC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkCase ( CV_8UC1 , CV_32SC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkCase ( CV_8UC1 , CV_32FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkCase ( CV_8UC1 , CV_64FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// CV_16UC1
tempCode = checkCase ( CV_16UC1 , CV_32FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkCase ( CV_16UC1 , CV_64FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// CV_16SC1
tempCode = checkCase ( CV_16SC1 , CV_32FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkCase ( CV_16SC1 , CV_64FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// CV_32FC1
tempCode = checkCase ( CV_32FC1 , CV_32FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkCase ( CV_32FC1 , CV_64FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// CV_64FC1
tempCode = checkCase ( CV_64FC1 , CV_64FC1 , dim , sz ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
return code ;
}
int Core_ReduceTest : : checkSize ( Size sz )
{
int code = cvtest : : TS : : OK , tempCode ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkDim ( 0 , sz ) ; // rows
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
tempCode = checkDim ( 1 , sz ) ; // cols
2011-02-10 04:55:11 +08:00
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
return code ;
}
void Core_ReduceTest : : run ( int )
{
int code = cvtest : : TS : : OK , tempCode ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkSize ( Size ( 1 , 1 ) ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkSize ( Size ( 1 , 100 ) ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkSize ( Size ( 100 , 1 ) ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
tempCode = checkSize ( Size ( 1000 , 500 ) ) ;
code = tempCode ! = cvtest : : TS : : OK ? tempCode : code ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
ts - > set_failed_test_info ( code ) ;
}
# define CHECK_C
class Core_PCATest : public cvtest : : BaseTest
{
public :
Core_PCATest ( ) { }
protected :
void run ( int )
{
2012-06-09 23:00:04 +08:00
const Size sz ( 200 , 500 ) ;
2011-02-10 04:55:11 +08:00
double diffPrjEps , diffBackPrjEps ,
prjEps , backPrjEps ,
evalEps , evecEps ;
int maxComponents = 100 ;
2012-08-23 11:21:49 +08:00
double retainedVariance = 0.95 ;
2011-02-10 04:55:11 +08:00
Mat rPoints ( sz , CV_32FC1 ) , rTestPoints ( sz , CV_32FC1 ) ;
2012-06-09 23:00:04 +08:00
RNG & rng = ts - > get_rng ( ) ;
2011-02-10 04:55:11 +08:00
rng . fill ( rPoints , RNG : : UNIFORM , Scalar : : all ( 0.0 ) , Scalar : : all ( 1.0 ) ) ;
rng . fill ( rTestPoints , RNG : : UNIFORM , Scalar : : all ( 0.0 ) , Scalar : : all ( 1.0 ) ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
PCA rPCA ( rPoints , Mat ( ) , CV_PCA_DATA_AS_ROW , maxComponents ) , cPCA ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// 1. check C++ PCA & ROW
Mat rPrjTestPoints = rPCA . project ( rTestPoints ) ;
Mat rBackPrjTestPoints = rPCA . backProject ( rPrjTestPoints ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
Mat avg ( 1 , sz . width , CV_32FC1 ) ;
2017-10-11 15:50:22 +08:00
cv : : reduce ( rPoints , avg , 0 , CV_REDUCE_AVG ) ;
2011-02-10 04:55:11 +08:00
Mat Q = rPoints - repeat ( avg , rPoints . rows , 1 ) , Qt = Q . t ( ) , eval , evec ;
Q = Qt * Q ;
Q = Q / ( float ) rPoints . rows ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
eigen ( Q , eval , evec ) ;
/*SVD svd(Q);
evec = svd . vt ;
eval = svd . w ; */
2012-06-09 23:00:04 +08:00
2014-08-13 19:08:27 +08:00
Mat subEval ( maxComponents , 1 , eval . type ( ) , eval . ptr ( ) ) ,
subEvec ( maxComponents , evec . cols , evec . type ( ) , evec . ptr ( ) ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
# ifdef CHECK_C
Mat prjTestPoints , backPrjTestPoints , cPoints = rPoints . t ( ) , cTestPoints = rTestPoints . t ( ) ;
CvMat _points , _testPoints , _avg , _eval , _evec , _prjTestPoints , _backPrjTestPoints ;
# endif
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// check eigen()
double eigenEps = 1e-6 ;
double err ;
for ( int i = 0 ; i < Q . rows ; i + + )
{
Mat v = evec . row ( i ) . t ( ) ;
Mat Qv = Q * v ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
Mat lv = eval . at < float > ( i , 0 ) * v ;
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( Qv , lv , NORM_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > eigenEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of eigen(); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
}
// check pca eigenvalues
2011-04-17 21:14:45 +08:00
evalEps = 1e-6 , evecEps = 1e-3 ;
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( rPCA . eigenvalues , subEval , NORM_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > evalEps )
{
ts - > printf ( cvtest : : TS : : LOG , " pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
// check pca eigenvectors
2011-04-17 21:14:45 +08:00
for ( int i = 0 ; i < subEvec . rows ; i + + )
2011-02-10 04:55:11 +08:00
{
2011-04-17 21:14:45 +08:00
Mat r0 = rPCA . eigenvectors . row ( i ) ;
Mat r1 = subEvec . row ( i ) ;
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( r0 , r1 , CV_L2 ) ;
2011-04-17 21:14:45 +08:00
if ( err > evecEps )
{
r1 * = - 1 ;
2014-04-08 05:11:58 +08:00
double err2 = cvtest : : norm ( r0 , r1 , CV_L2 ) ;
2011-04-17 21:14:45 +08:00
if ( err2 > evecEps )
{
Mat tmp ;
absdiff ( rPCA . eigenvectors , subEvec , tmp ) ;
double mval = 0 ; Point mloc ;
minMaxLoc ( tmp , 0 , & mval , 0 , & mloc ) ;
2012-06-09 23:00:04 +08:00
2011-04-17 21:14:45 +08:00
ts - > printf ( cvtest : : TS : : LOG , " pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW); err = %f \n " , err ) ;
ts - > printf ( cvtest : : TS : : LOG , " max diff is %g at (i=%d, j=%d) (%g vs %g) \n " ,
mval , mloc . y , mloc . x , rPCA . eigenvectors . at < float > ( mloc . y , mloc . x ) ,
subEvec . at < float > ( mloc . y , mloc . x ) ) ;
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
}
}
2011-02-10 04:55:11 +08:00
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
prjEps = 1.265 , backPrjEps = 1.265 ;
for ( int i = 0 ; i < rTestPoints . rows ; i + + )
{
// check pca project
Mat subEvec_t = subEvec . t ( ) ;
Mat prj = rTestPoints . row ( i ) - avg ; prj * = subEvec_t ;
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( rPrjTestPoints . row ( i ) , prj , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > prjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of project() (CV_PCA_DATA_AS_ROW); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
// check pca backProject
Mat backPrj = rPrjTestPoints . row ( i ) * subEvec + avg ;
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( rBackPrjTestPoints . row ( i ) , backPrj , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > backPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of backProject() (CV_PCA_DATA_AS_ROW); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// 2. check C++ PCA & COL
cPCA ( rPoints . t ( ) , Mat ( ) , CV_PCA_DATA_AS_COL , maxComponents ) ;
diffPrjEps = 1 , diffBackPrjEps = 1 ;
2011-04-17 21:14:45 +08:00
Mat ocvPrjTestPoints = cPCA . project ( rTestPoints . t ( ) ) ;
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( cv : : abs ( ocvPrjTestPoints ) , cv : : abs ( rPrjTestPoints . t ( ) ) , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > diffPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of project() (CV_PCA_DATA_AS_COL); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( cPCA . backProject ( ocvPrjTestPoints ) , rBackPrjTestPoints . t ( ) , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > diffBackPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of backProject() (CV_PCA_DATA_AS_COL); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
2012-10-17 15:12:04 +08:00
2012-08-23 11:21:49 +08:00
// 3. check C++ PCA w/retainedVariance
cPCA ( rPoints . t ( ) , Mat ( ) , CV_PCA_DATA_AS_COL , retainedVariance ) ;
diffPrjEps = 1 , diffBackPrjEps = 1 ;
2012-10-17 15:12:04 +08:00
Mat rvPrjTestPoints = cPCA . project ( rTestPoints . t ( ) ) ;
2012-08-23 11:21:49 +08:00
if ( cPCA . eigenvectors . rows > maxComponents )
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( cv : : abs ( rvPrjTestPoints . rowRange ( 0 , maxComponents ) ) , cv : : abs ( rPrjTestPoints . t ( ) ) , CV_RELATIVE_L2 ) ;
2012-08-23 11:21:49 +08:00
else
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( cv : : abs ( rvPrjTestPoints ) , cv : : abs ( rPrjTestPoints . colRange ( 0 , cPCA . eigenvectors . rows ) . t ( ) ) , CV_RELATIVE_L2 ) ;
2012-10-17 15:12:04 +08:00
2012-08-23 11:21:49 +08:00
if ( err > diffPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f \n " , err ) ;
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
}
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( cPCA . backProject ( rvPrjTestPoints ) , rBackPrjTestPoints . t ( ) , CV_RELATIVE_L2 ) ;
2012-08-23 11:21:49 +08:00
if ( err > diffBackPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f \n " , err ) ;
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
}
2012-10-17 15:12:04 +08:00
2011-02-10 04:55:11 +08:00
# ifdef CHECK_C
2012-08-23 11:21:49 +08:00
// 4. check C PCA & ROW
2011-02-10 04:55:11 +08:00
_points = rPoints ;
_testPoints = rTestPoints ;
_avg = avg ;
_eval = eval ;
_evec = evec ;
prjTestPoints . create ( rTestPoints . rows , maxComponents , rTestPoints . type ( ) ) ;
backPrjTestPoints . create ( rPoints . size ( ) , rPoints . type ( ) ) ;
_prjTestPoints = prjTestPoints ;
_backPrjTestPoints = backPrjTestPoints ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
cvCalcPCA ( & _points , & _avg , & _eval , & _evec , CV_PCA_DATA_AS_ROW ) ;
cvProjectPCA ( & _testPoints , & _avg , & _evec , & _prjTestPoints ) ;
cvBackProjectPCA ( & _prjTestPoints , & _avg , & _evec , & _backPrjTestPoints ) ;
2012-06-09 23:00:04 +08:00
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( prjTestPoints , rPrjTestPoints , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > diffPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( backPrjTestPoints , rBackPrjTestPoints , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > diffBackPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
2012-06-09 23:00:04 +08:00
2012-08-23 11:21:49 +08:00
// 5. check C PCA & COL
2011-02-10 04:55:11 +08:00
_points = cPoints ;
_testPoints = cTestPoints ;
avg = avg . t ( ) ; _avg = avg ;
eval = eval . t ( ) ; _eval = eval ;
evec = evec . t ( ) ; _evec = evec ;
prjTestPoints = prjTestPoints . t ( ) ; _prjTestPoints = prjTestPoints ;
backPrjTestPoints = backPrjTestPoints . t ( ) ; _backPrjTestPoints = backPrjTestPoints ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
cvCalcPCA ( & _points , & _avg , & _eval , & _evec , CV_PCA_DATA_AS_COL ) ;
cvProjectPCA ( & _testPoints , & _avg , & _evec , & _prjTestPoints ) ;
cvBackProjectPCA ( & _prjTestPoints , & _avg , & _evec , & _backPrjTestPoints ) ;
2012-06-09 23:00:04 +08:00
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( cv : : abs ( prjTestPoints ) , cv : : abs ( rPrjTestPoints . t ( ) ) , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > diffPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( backPrjTestPoints , rBackPrjTestPoints . t ( ) , CV_RELATIVE_L2 ) ;
2011-02-10 04:55:11 +08:00
if ( err > diffBackPrjEps )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL); err = %f \n " , err ) ;
2011-04-17 21:14:45 +08:00
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
return ;
2011-02-10 04:55:11 +08:00
}
# endif
2013-08-05 08:06:55 +08:00
// Test read and write
FileStorage fs ( " PCA_store.yml " , FileStorage : : WRITE ) ;
rPCA . write ( fs ) ;
fs . release ( ) ;
PCA lPCA ;
fs . open ( " PCA_store.yml " , FileStorage : : READ ) ;
lPCA . read ( fs . root ( ) ) ;
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( rPCA . eigenvectors , lPCA . eigenvectors , CV_RELATIVE_L2 ) ;
2013-08-05 08:06:55 +08:00
if ( err > 0 )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of write/load functions (YML); err = %f \n " , err ) ;
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
}
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( rPCA . eigenvalues , lPCA . eigenvalues , CV_RELATIVE_L2 ) ;
2013-08-05 08:06:55 +08:00
if ( err > 0 )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of write/load functions (YML); err = %f \n " , err ) ;
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
}
2014-04-08 05:11:58 +08:00
err = cvtest : : norm ( rPCA . mean , lPCA . mean , CV_RELATIVE_L2 ) ;
2013-08-05 08:06:55 +08:00
if ( err > 0 )
{
ts - > printf ( cvtest : : TS : : LOG , " bad accuracy of write/load functions (YML); err = %f \n " , err ) ;
ts - > set_failed_test_info ( cvtest : : TS : : FAIL_BAD_ACCURACY ) ;
}
2011-02-10 04:55:11 +08:00
}
} ;
class Core_ArrayOpTest : public cvtest : : BaseTest
{
public :
Core_ArrayOpTest ( ) ;
2012-06-09 23:00:04 +08:00
~ Core_ArrayOpTest ( ) ;
2011-02-10 04:55:11 +08:00
protected :
2012-06-09 23:00:04 +08:00
void run ( int ) ;
2011-02-10 04:55:11 +08:00
} ;
Core_ArrayOpTest : : Core_ArrayOpTest ( )
{
}
Core_ArrayOpTest : : ~ Core_ArrayOpTest ( ) { }
static string idx2string ( const int * idx , int dims )
{
char buf [ 256 ] ;
char * ptr = buf ;
for ( int k = 0 ; k < dims ; k + + )
{
sprintf ( ptr , " %4d " , idx [ k ] ) ;
ptr + = strlen ( ptr ) ;
}
ptr [ - 1 ] = ' \0 ' ;
return string ( buf ) ;
}
static const int * string2idx ( const string & s , int * idx , int dims )
{
const char * ptr = s . c_str ( ) ;
for ( int k = 0 ; k < dims ; k + + )
{
int n = 0 ;
sscanf ( ptr , " %d%n " , idx + k , & n ) ;
ptr + = n ;
}
return idx ;
}
static double getValue ( SparseMat & M , const int * idx , RNG & rng )
{
int d = M . dims ( ) ;
size_t hv = 0 , * phv = 0 ;
if ( ( unsigned ) rng % 2 )
{
hv = d = = 2 ? M . hash ( idx [ 0 ] , idx [ 1 ] ) :
d = = 3 ? M . hash ( idx [ 0 ] , idx [ 1 ] , idx [ 2 ] ) : M . hash ( idx ) ;
phv = & hv ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
const uchar * ptr = d = = 2 ? M . ptr ( idx [ 0 ] , idx [ 1 ] , false , phv ) :
d = = 3 ? M . ptr ( idx [ 0 ] , idx [ 1 ] , idx [ 2 ] , false , phv ) :
M . ptr ( idx , false , phv ) ;
return ! ptr ? 0 : M . type ( ) = = CV_32F ? * ( float * ) ptr : M . type ( ) = = CV_64F ? * ( double * ) ptr : 0 ;
}
static double getValue ( const CvSparseMat * M , const int * idx )
{
int type = 0 ;
const uchar * ptr = cvPtrND ( M , idx , & type , 0 ) ;
return ! ptr ? 0 : type = = CV_32F ? * ( float * ) ptr : type = = CV_64F ? * ( double * ) ptr : 0 ;
}
static void eraseValue ( SparseMat & M , const int * idx , RNG & rng )
{
int d = M . dims ( ) ;
size_t hv = 0 , * phv = 0 ;
if ( ( unsigned ) rng % 2 )
{
hv = d = = 2 ? M . hash ( idx [ 0 ] , idx [ 1 ] ) :
d = = 3 ? M . hash ( idx [ 0 ] , idx [ 1 ] , idx [ 2 ] ) : M . hash ( idx ) ;
phv = & hv ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
if ( d = = 2 )
M . erase ( idx [ 0 ] , idx [ 1 ] , phv ) ;
else if ( d = = 3 )
M . erase ( idx [ 0 ] , idx [ 1 ] , idx [ 2 ] , phv ) ;
else
M . erase ( idx , phv ) ;
}
static void eraseValue ( CvSparseMat * M , const int * idx )
{
cvClearND ( M , idx ) ;
}
static void setValue ( SparseMat & M , const int * idx , double value , RNG & rng )
{
int d = M . dims ( ) ;
size_t hv = 0 , * phv = 0 ;
if ( ( unsigned ) rng % 2 )
{
hv = d = = 2 ? M . hash ( idx [ 0 ] , idx [ 1 ] ) :
d = = 3 ? M . hash ( idx [ 0 ] , idx [ 1 ] , idx [ 2 ] ) : M . hash ( idx ) ;
phv = & hv ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
uchar * ptr = d = = 2 ? M . ptr ( idx [ 0 ] , idx [ 1 ] , true , phv ) :
d = = 3 ? M . ptr ( idx [ 0 ] , idx [ 1 ] , idx [ 2 ] , true , phv ) :
M . ptr ( idx , true , phv ) ;
if ( M . type ( ) = = CV_32F )
* ( float * ) ptr = ( float ) value ;
else if ( M . type ( ) = = CV_64F )
* ( double * ) ptr = value ;
else
CV_Error ( CV_StsUnsupportedFormat , " " ) ;
}
2014-01-06 00:42:45 +08:00
template < typename Pixel >
struct InitializerFunctor {
/// Initializer for cv::Mat::forEach test
void operator ( ) ( Pixel & pixel , const int * idx ) const {
pixel . x = idx [ 0 ] ;
pixel . y = idx [ 1 ] ;
pixel . z = idx [ 2 ] ;
}
} ;
2017-03-24 21:54:10 +08:00
template < typename Pixel >
struct InitializerFunctor5D {
/// Initializer for cv::Mat::forEach test (5 dimensional case)
void operator ( ) ( Pixel & pixel , const int * idx ) const {
pixel [ 0 ] = idx [ 0 ] ;
pixel [ 1 ] = idx [ 1 ] ;
pixel [ 2 ] = idx [ 2 ] ;
pixel [ 3 ] = idx [ 3 ] ;
pixel [ 4 ] = idx [ 4 ] ;
}
} ;
2017-09-07 16:35:14 +08:00
template < typename Pixel >
struct EmptyFunctor
{
void operator ( ) ( const Pixel & , const int * ) const { }
} ;
2011-02-10 04:55:11 +08:00
void Core_ArrayOpTest : : run ( int /* start_from */ )
{
int errcount = 0 ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
// dense matrix operations
{
int sz3 [ ] = { 5 , 10 , 15 } ;
MatND A ( 3 , sz3 , CV_32F ) , B ( 3 , sz3 , CV_16SC4 ) ;
CvMatND matA = A , matB = B ;
RNG rng ;
rng . fill ( A , CV_RAND_UNI , Scalar : : all ( - 10 ) , Scalar : : all ( 10 ) ) ;
rng . fill ( B , CV_RAND_UNI , Scalar : : all ( - 10 ) , Scalar : : all ( 10 ) ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
int idx0 [ ] = { 3 , 4 , 5 } , idx1 [ ] = { 0 , 9 , 7 } ;
float val0 = 130 ;
Scalar val1 ( - 1000 , 30 , 3 , 8 ) ;
cvSetRealND ( & matA , idx0 , val0 ) ;
cvSetReal3D ( & matA , idx1 [ 0 ] , idx1 [ 1 ] , idx1 [ 2 ] , - val0 ) ;
cvSetND ( & matB , idx0 , val1 ) ;
cvSet3D ( & matB , idx1 [ 0 ] , idx1 [ 1 ] , idx1 [ 2 ] , - val1 ) ;
2013-08-13 20:22:07 +08:00
Ptr < CvMatND > matC ( cvCloneMatND ( & matB ) ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
if ( A . at < float > ( idx0 [ 0 ] , idx0 [ 1 ] , idx0 [ 2 ] ) ! = val0 | |
A . at < float > ( idx1 [ 0 ] , idx1 [ 1 ] , idx1 [ 2 ] ) ! = - val0 | |
cvGetReal3D ( & matA , idx0 [ 0 ] , idx0 [ 1 ] , idx0 [ 2 ] ) ! = val0 | |
cvGetRealND ( & matA , idx1 ) ! = - val0 | |
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
Scalar ( B . at < Vec4s > ( idx0 [ 0 ] , idx0 [ 1 ] , idx0 [ 2 ] ) ) ! = val1 | |
Scalar ( B . at < Vec4s > ( idx1 [ 0 ] , idx1 [ 1 ] , idx1 [ 2 ] ) ) ! = - val1 | |
Scalar ( cvGet3D ( matC , idx0 [ 0 ] , idx0 [ 1 ] , idx0 [ 2 ] ) ) ! = val1 | |
Scalar ( cvGetND ( matC , idx1 ) ) ! = - val1 )
{
ts - > printf ( cvtest : : TS : : LOG , " one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND "
" or the corresponding *Get* functions is not correct \n " ) ;
errcount + + ;
}
}
2014-01-06 00:42:45 +08:00
// test cv::Mat::forEach
{
const int dims [ 3 ] = { 101 , 107 , 7 } ;
typedef cv : : Point3i Pixel ;
cv : : Mat a = cv : : Mat : : zeros ( 3 , dims , CV_32SC3 ) ;
InitializerFunctor < Pixel > initializer ;
a . forEach < Pixel > ( initializer ) ;
uint64 total = 0 ;
bool error_reported = false ;
for ( int i0 = 0 ; i0 < dims [ 0 ] ; + + i0 ) {
for ( int i1 = 0 ; i1 < dims [ 1 ] ; + + i1 ) {
for ( int i2 = 0 ; i2 < dims [ 2 ] ; + + i2 ) {
Pixel & pixel = a . at < Pixel > ( i0 , i1 , i2 ) ;
if ( pixel . x ! = i0 | | pixel . y ! = i1 | | pixel . z ! = i2 ) {
if ( ! error_reported ) {
ts - > printf ( cvtest : : TS : : LOG , " forEach is not correct. \n "
" First error detected at (%d, %d, %d). \n " , pixel . x , pixel . y , pixel . z ) ;
error_reported = true ;
}
errcount + + ;
}
total + = pixel . x ;
total + = pixel . y ;
total + = pixel . z ;
}
}
}
uint64 total2 = 0 ;
for ( size_t i = 0 ; i < sizeof ( dims ) / sizeof ( dims [ 0 ] ) ; + + i ) {
total2 + = ( ( dims [ i ] - 1 ) * dims [ i ] / 2 ) * dims [ 0 ] * dims [ 1 ] * dims [ 2 ] / dims [ i ] ;
}
if ( total ! = total2 ) {
ts - > printf ( cvtest : : TS : : LOG , " forEach is not correct because total is invalid. \n " ) ;
errcount + + ;
}
}
2012-06-09 23:00:04 +08:00
2017-03-24 21:54:10 +08:00
// test cv::Mat::forEach
// with a matrix that has more dimensions than columns
// See https://github.com/opencv/opencv/issues/8447
{
const int dims [ 5 ] = { 2 , 2 , 2 , 2 , 2 } ;
typedef cv : : Vec < int , 5 > Pixel ;
cv : : Mat a = cv : : Mat : : zeros ( 5 , dims , CV_32SC ( 5 ) ) ;
InitializerFunctor5D < Pixel > initializer ;
a . forEach < Pixel > ( initializer ) ;
uint64 total = 0 ;
bool error_reported = false ;
for ( int i0 = 0 ; i0 < dims [ 0 ] ; + + i0 ) {
for ( int i1 = 0 ; i1 < dims [ 1 ] ; + + i1 ) {
for ( int i2 = 0 ; i2 < dims [ 2 ] ; + + i2 ) {
for ( int i3 = 0 ; i3 < dims [ 3 ] ; + + i3 ) {
for ( int i4 = 0 ; i4 < dims [ 4 ] ; + + i4 ) {
const int i [ 5 ] = { i0 , i1 , i2 , i3 , i4 } ;
Pixel & pixel = a . at < Pixel > ( i ) ;
if ( pixel [ 0 ] ! = i0 | | pixel [ 1 ] ! = i1 | | pixel [ 2 ] ! = i2 | | pixel [ 3 ] ! = i3 | | pixel [ 4 ] ! = i4 ) {
if ( ! error_reported ) {
ts - > printf ( cvtest : : TS : : LOG , " forEach is not correct. \n "
" First error detected at position (%d, %d, %d, %d, %d), got value (%d, %d, %d, %d, %d). \n " ,
i0 , i1 , i2 , i3 , i4 ,
pixel [ 0 ] , pixel [ 1 ] , pixel [ 2 ] , pixel [ 3 ] , pixel [ 4 ] ) ;
error_reported = true ;
}
errcount + + ;
}
total + = pixel [ 0 ] ;
total + = pixel [ 1 ] ;
total + = pixel [ 2 ] ;
total + = pixel [ 3 ] ;
total + = pixel [ 4 ] ;
}
}
}
}
}
uint64 total2 = 0 ;
for ( size_t i = 0 ; i < sizeof ( dims ) / sizeof ( dims [ 0 ] ) ; + + i ) {
total2 + = ( ( dims [ i ] - 1 ) * dims [ i ] / 2 ) * dims [ 0 ] * dims [ 1 ] * dims [ 2 ] * dims [ 3 ] * dims [ 4 ] / dims [ i ] ;
}
if ( total ! = total2 ) {
ts - > printf ( cvtest : : TS : : LOG , " forEach is not correct because total is invalid. \n " ) ;
errcount + + ;
}
}
2017-09-07 16:35:14 +08:00
// test const cv::Mat::forEach
{
const Mat a ( 10 , 10 , CV_32SC3 ) ;
Mat b ( 10 , 10 , CV_32SC3 ) ;
const Mat & c = b ;
a . forEach < Point3i > ( EmptyFunctor < Point3i > ( ) ) ;
b . forEach < Point3i > ( EmptyFunctor < const Point3i > ( ) ) ;
c . forEach < Point3i > ( EmptyFunctor < Point3i > ( ) ) ;
// tests compilation, no runtime check is needed
}
2011-02-10 04:55:11 +08:00
RNG rng ;
const int MAX_DIM = 5 , MAX_DIM_SZ = 10 ;
// sparse matrix operations
for ( int si = 0 ; si < 10 ; si + + )
{
int depth = ( unsigned ) rng % 2 = = 0 ? CV_32F : CV_64F ;
int dims = ( ( unsigned ) rng % MAX_DIM ) + 1 ;
int i , k , size [ MAX_DIM ] = { 0 } , idx [ MAX_DIM ] = { 0 } ;
vector < string > all_idxs ;
vector < double > all_vals ;
vector < double > all_vals2 ;
string sidx , min_sidx , max_sidx ;
double min_val = 0 , max_val = 0 ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
int p = 1 ;
for ( k = 0 ; k < dims ; k + + )
{
size [ k ] = ( ( unsigned ) rng % MAX_DIM_SZ ) + 1 ;
p * = size [ k ] ;
}
SparseMat M ( dims , size , depth ) ;
map < string , double > M0 ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
int nz0 = ( unsigned ) rng % max ( p / 5 , 10 ) ;
nz0 = min ( max ( nz0 , 1 ) , p ) ;
all_vals . resize ( nz0 ) ;
all_vals2 . resize ( nz0 ) ;
Mat_ < double > _all_vals ( all_vals ) , _all_vals2 ( all_vals2 ) ;
rng . fill ( _all_vals , CV_RAND_UNI , Scalar ( - 1000 ) , Scalar ( 1000 ) ) ;
if ( depth = = CV_32F )
{
Mat _all_vals_f ;
_all_vals . convertTo ( _all_vals_f , CV_32F ) ;
_all_vals_f . convertTo ( _all_vals , CV_64F ) ;
}
_all_vals . convertTo ( _all_vals2 , _all_vals2 . type ( ) , 2 ) ;
if ( depth = = CV_32F )
{
Mat _all_vals2_f ;
_all_vals2 . convertTo ( _all_vals2_f , CV_32F ) ;
_all_vals2_f . convertTo ( _all_vals2 , CV_64F ) ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
minMaxLoc ( _all_vals , & min_val , & max_val ) ;
2014-04-08 05:11:58 +08:00
double _norm0 = cvtest : : norm ( _all_vals , CV_C ) ;
double _norm1 = cvtest : : norm ( _all_vals , CV_L1 ) ;
double _norm2 = cvtest : : norm ( _all_vals , CV_L2 ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
for ( i = 0 ; i < nz0 ; i + + )
{
for ( ; ; )
{
for ( k = 0 ; k < dims ; k + + )
idx [ k ] = ( unsigned ) rng % size [ k ] ;
sidx = idx2string ( idx , dims ) ;
if ( M0 . count ( sidx ) = = 0 )
break ;
}
all_idxs . push_back ( sidx ) ;
M0 [ sidx ] = all_vals [ i ] ;
if ( all_vals [ i ] = = min_val )
min_sidx = sidx ;
if ( all_vals [ i ] = = max_val )
max_sidx = sidx ;
setValue ( M , idx , all_vals [ i ] , rng ) ;
double v = getValue ( M , idx , rng ) ;
if ( v ! = all_vals [ i ] )
{
ts - > printf ( cvtest : : TS : : LOG , " %d. immediately after SparseMat[%s]=%.20g the current value is %.20g \n " ,
i , sidx . c_str ( ) , all_vals [ i ] , v ) ;
errcount + + ;
break ;
}
}
2012-06-09 23:00:04 +08:00
2013-08-13 20:22:07 +08:00
Ptr < CvSparseMat > M2 ( cvCreateSparseMat ( M ) ) ;
2011-02-10 04:55:11 +08:00
MatND Md ;
M . copyTo ( Md ) ;
SparseMat M3 ; SparseMat ( Md ) . convertTo ( M3 , Md . type ( ) , 2 ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
int nz1 = ( int ) M . nzcount ( ) , nz2 = ( int ) M3 . nzcount ( ) ;
double norm0 = norm ( M , CV_C ) ;
double norm1 = norm ( M , CV_L1 ) ;
double norm2 = norm ( M , CV_L2 ) ;
double eps = depth = = CV_32F ? FLT_EPSILON * 100 : DBL_EPSILON * 1000 ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
if ( nz1 ! = nz0 | | nz2 ! = nz0 )
{
errcount + + ;
ts - > printf ( cvtest : : TS : : LOG , " %d: The number of non-zero elements before/after converting to/from dense matrix is not correct: %d/%d (while it should be %d) \n " ,
si , nz1 , nz2 , nz0 ) ;
break ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
if ( fabs ( norm0 - _norm0 ) > fabs ( _norm0 ) * eps | |
fabs ( norm1 - _norm1 ) > fabs ( _norm1 ) * eps | |
fabs ( norm2 - _norm2 ) > fabs ( _norm2 ) * eps )
{
errcount + + ;
ts - > printf ( cvtest : : TS : : LOG , " %d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g \n " ,
si , norm0 , norm1 , norm2 , _norm0 , _norm1 , _norm2 ) ;
break ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
int n = ( unsigned ) rng % max ( p / 5 , 10 ) ;
n = min ( max ( n , 1 ) , p ) + nz0 ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
for ( i = 0 ; i < n ; i + + )
{
double val1 , val2 , val3 , val0 ;
if ( i < nz0 )
{
sidx = all_idxs [ i ] ;
string2idx ( sidx , idx , dims ) ;
val0 = all_vals [ i ] ;
}
else
{
for ( k = 0 ; k < dims ; k + + )
idx [ k ] = ( unsigned ) rng % size [ k ] ;
sidx = idx2string ( idx , dims ) ;
val0 = M0 [ sidx ] ;
}
val1 = getValue ( M , idx , rng ) ;
val2 = getValue ( M2 , idx ) ;
val3 = getValue ( M3 , idx , rng ) ;
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
if ( val1 ! = val0 | | val2 ! = val0 | | fabs ( val3 - val0 * 2 ) > fabs ( val0 * 2 ) * FLT_EPSILON )
{
errcount + + ;
ts - > printf ( cvtest : : TS : : LOG , " SparseMat M[%s] = %g/%g/%g (while it should be %g) \n " , sidx . c_str ( ) , val1 , val2 , val3 , val0 ) ;
break ;
}
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
for ( i = 0 ; i < n ; i + + )
{
double val1 , val2 ;
if ( i < nz0 )
{
sidx = all_idxs [ i ] ;
string2idx ( sidx , idx , dims ) ;
}
else
{
for ( k = 0 ; k < dims ; k + + )
idx [ k ] = ( unsigned ) rng % size [ k ] ;
sidx = idx2string ( idx , dims ) ;
}
eraseValue ( M , idx , rng ) ;
eraseValue ( M2 , idx ) ;
val1 = getValue ( M , idx , rng ) ;
val2 = getValue ( M2 , idx ) ;
if ( val1 ! = 0 | | val2 ! = 0 )
{
errcount + + ;
ts - > printf ( cvtest : : TS : : LOG , " SparseMat: after deleting M[%s], it is =%g/%g (while it should be 0) \n " , sidx . c_str ( ) , val1 , val2 ) ;
break ;
2012-06-09 23:00:04 +08:00
}
2011-02-10 04:55:11 +08:00
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
int nz = ( int ) M . nzcount ( ) ;
if ( nz ! = 0 )
{
errcount + + ;
ts - > printf ( cvtest : : TS : : LOG , " The number of non-zero elements after removing all the elements = %d (while it should be 0) \n " , nz ) ;
break ;
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
int idx1 [ MAX_DIM ] , idx2 [ MAX_DIM ] ;
double val1 = 0 , val2 = 0 ;
M3 = SparseMat ( Md ) ;
minMaxLoc ( M3 , & val1 , & val2 , idx1 , idx2 ) ;
string s1 = idx2string ( idx1 , dims ) , s2 = idx2string ( idx2 , dims ) ;
if ( val1 ! = min_val | | val2 ! = max_val | | s1 ! = min_sidx | | s2 ! = max_sidx )
{
errcount + + ;
ts - > printf ( cvtest : : TS : : LOG , " %d. Sparse: The value and positions of minimum/maximum elements are different from the reference values and positions: \n \t "
" (%g, %g, %s, %s) vs (%g, %g, %s, %s) \n " , si , val1 , val2 , s1 . c_str ( ) , s2 . c_str ( ) ,
min_val , max_val , min_sidx . c_str ( ) , max_sidx . c_str ( ) ) ;
break ;
}
2012-06-09 23:00:04 +08:00
2011-04-17 21:14:45 +08:00
minMaxIdx ( Md , & val1 , & val2 , idx1 , idx2 ) ;
2011-02-10 04:55:11 +08:00
s1 = idx2string ( idx1 , dims ) , s2 = idx2string ( idx2 , dims ) ;
if ( ( min_val < 0 & & ( val1 ! = min_val | | s1 ! = min_sidx ) ) | |
( max_val > 0 & & ( val2 ! = max_val | | s2 ! = max_sidx ) ) )
{
errcount + + ;
ts - > printf ( cvtest : : TS : : LOG , " %d. Dense: The value and positions of minimum/maximum elements are different from the reference values and positions: \n \t "
" (%g, %g, %s, %s) vs (%g, %g, %s, %s) \n " , si , val1 , val2 , s1 . c_str ( ) , s2 . c_str ( ) ,
min_val , max_val , min_sidx . c_str ( ) , max_sidx . c_str ( ) ) ;
break ;
}
}
2012-06-09 23:00:04 +08:00
2011-02-10 04:55:11 +08:00
ts - > set_failed_test_info ( errcount = = 0 ? cvtest : : TS : : OK : cvtest : : TS : : FAIL_INVALID_OUTPUT ) ;
}
2012-10-20 23:37:19 +08:00
template < class ElemType >
int calcDiffElemCountImpl ( const vector < Mat > & mv , const Mat & m )
{
int diffElemCount = 0 ;
2012-11-08 07:15:43 +08:00
const int mChannels = m . channels ( ) ;
2012-10-20 23:37:19 +08:00
for ( int y = 0 ; y < m . rows ; y + + )
{
for ( int x = 0 ; x < m . cols ; x + + )
{
const ElemType * mElem = & m . at < ElemType > ( y , x * mChannels ) ;
2013-02-25 15:08:27 +08:00
size_t loc = 0 ;
2012-10-20 23:37:19 +08:00
for ( size_t i = 0 ; i < mv . size ( ) ; i + + )
{
const size_t mvChannel = mv [ i ] . channels ( ) ;
2012-11-08 07:15:43 +08:00
const ElemType * mvElem = & mv [ i ] . at < ElemType > ( y , x * ( int ) mvChannel ) ;
2012-10-20 23:37:19 +08:00
for ( size_t li = 0 ; li < mvChannel ; li + + )
if ( mElem [ loc + li ] ! = mvElem [ li ] )
diffElemCount + + ;
loc + = mvChannel ;
}
2013-02-25 15:08:27 +08:00
CV_Assert ( loc = = ( size_t ) mChannels ) ;
2012-10-20 23:37:19 +08:00
}
}
return diffElemCount ;
}
static
int calcDiffElemCount ( const vector < Mat > & mv , const Mat & m )
{
int depth = m . depth ( ) ;
switch ( depth )
{
case CV_8U :
return calcDiffElemCountImpl < uchar > ( mv , m ) ;
case CV_8S :
return calcDiffElemCountImpl < char > ( mv , m ) ;
case CV_16U :
return calcDiffElemCountImpl < unsigned short > ( mv , m ) ;
case CV_16S :
return calcDiffElemCountImpl < short int > ( mv , m ) ;
case CV_32S :
return calcDiffElemCountImpl < int > ( mv , m ) ;
case CV_32F :
return calcDiffElemCountImpl < float > ( mv , m ) ;
case CV_64F :
return calcDiffElemCountImpl < double > ( mv , m ) ;
}
return INT_MAX ;
}
class Core_MergeSplitBaseTest : public cvtest : : BaseTest
{
protected :
virtual int run_case ( int depth , size_t channels , const Size & size , RNG & rng ) = 0 ;
virtual void run ( int )
{
// m is Mat
// mv is vector<Mat>
const int minMSize = 1 ;
const int maxMSize = 100 ;
const size_t maxMvSize = 10 ;
RNG & rng = theRNG ( ) ;
Size mSize ( rng . uniform ( minMSize , maxMSize ) , rng . uniform ( minMSize , maxMSize ) ) ;
2013-01-16 21:55:27 +08:00
size_t mvSize = rng . uniform ( 1 , maxMvSize ) ;
2012-10-20 23:37:19 +08:00
int res = cvtest : : TS : : OK , curRes = res ;
curRes = run_case ( CV_8U , mvSize , mSize , rng ) ;
res = curRes ! = cvtest : : TS : : OK ? curRes : res ;
curRes = run_case ( CV_8S , mvSize , mSize , rng ) ;
res = curRes ! = cvtest : : TS : : OK ? curRes : res ;
curRes = run_case ( CV_16U , mvSize , mSize , rng ) ;
res = curRes ! = cvtest : : TS : : OK ? curRes : res ;
curRes = run_case ( CV_16S , mvSize , mSize , rng ) ;
res = curRes ! = cvtest : : TS : : OK ? curRes : res ;
curRes = run_case ( CV_32S , mvSize , mSize , rng ) ;
res = curRes ! = cvtest : : TS : : OK ? curRes : res ;
curRes = run_case ( CV_32F , mvSize , mSize , rng ) ;
res = curRes ! = cvtest : : TS : : OK ? curRes : res ;
curRes = run_case ( CV_64F , mvSize , mSize , rng ) ;
res = curRes ! = cvtest : : TS : : OK ? curRes : res ;
ts - > set_failed_test_info ( res ) ;
}
} ;
class Core_MergeTest : public Core_MergeSplitBaseTest
{
public :
Core_MergeTest ( ) { }
~ Core_MergeTest ( ) { }
protected :
virtual int run_case ( int depth , size_t matCount , const Size & size , RNG & rng )
{
const int maxMatChannels = 10 ;
vector < Mat > src ( matCount ) ;
int channels = 0 ;
for ( size_t i = 0 ; i < src . size ( ) ; i + + )
{
Mat m ( size , CV_MAKETYPE ( depth , rng . uniform ( 1 , maxMatChannels ) ) ) ;
rng . fill ( m , RNG : : UNIFORM , 0 , 100 , true ) ;
channels + = m . channels ( ) ;
src [ i ] = m ;
}
Mat dst ;
merge ( src , dst ) ;
// check result
stringstream commonLog ;
commonLog < < " Depth " < < depth < < " : " ;
if ( dst . depth ( ) ! = depth )
{
ts - > printf ( cvtest : : TS : : LOG , " %s incorrect depth of dst (%d instead of %d) \n " ,
commonLog . str ( ) . c_str ( ) , dst . depth ( ) , depth ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
if ( dst . size ( ) ! = size )
{
ts - > printf ( cvtest : : TS : : LOG , " %s incorrect size of dst (%d x %d instead of %d x %d) \n " ,
commonLog . str ( ) . c_str ( ) , dst . rows , dst . cols , size . height , size . width ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
if ( dst . channels ( ) ! = channels )
{
ts - > printf ( cvtest : : TS : : LOG , " %s: incorrect channels count of dst (%d instead of %d) \n " ,
commonLog . str ( ) . c_str ( ) , dst . channels ( ) , channels ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
int diffElemCount = calcDiffElemCount ( src , dst ) ;
if ( diffElemCount > 0 )
{
ts - > printf ( cvtest : : TS : : LOG , " %s: there are incorrect elements in dst (part of them is %f) \n " ,
commonLog . str ( ) . c_str ( ) , static_cast < float > ( diffElemCount ) / ( channels * size . area ( ) ) ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
return cvtest : : TS : : OK ;
}
} ;
class Core_SplitTest : public Core_MergeSplitBaseTest
{
public :
Core_SplitTest ( ) { }
~ Core_SplitTest ( ) { }
protected :
virtual int run_case ( int depth , size_t channels , const Size & size , RNG & rng )
{
2012-11-08 07:15:43 +08:00
Mat src ( size , CV_MAKETYPE ( depth , ( int ) channels ) ) ;
2012-10-20 23:37:19 +08:00
rng . fill ( src , RNG : : UNIFORM , 0 , 100 , true ) ;
vector < Mat > dst ;
split ( src , dst ) ;
// check result
stringstream commonLog ;
commonLog < < " Depth " < < depth < < " : " ;
if ( dst . size ( ) ! = channels )
{
ts - > printf ( cvtest : : TS : : LOG , " %s incorrect count of matrices in dst (%d instead of %d) \n " ,
commonLog . str ( ) . c_str ( ) , dst . size ( ) , channels ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
for ( size_t i = 0 ; i < dst . size ( ) ; i + + )
{
if ( dst [ i ] . size ( ) ! = size )
{
ts - > printf ( cvtest : : TS : : LOG , " %s incorrect size of dst[%d] (%d x %d instead of %d x %d) \n " ,
commonLog . str ( ) . c_str ( ) , i , dst [ i ] . rows , dst [ i ] . cols , size . height , size . width ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
if ( dst [ i ] . depth ( ) ! = depth )
{
ts - > printf ( cvtest : : TS : : LOG , " %s: incorrect depth of dst[%d] (%d instead of %d) \n " ,
commonLog . str ( ) . c_str ( ) , i , dst [ i ] . depth ( ) , depth ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
if ( dst [ i ] . channels ( ) ! = 1 )
{
ts - > printf ( cvtest : : TS : : LOG , " %s: incorrect channels count of dst[%d] (%d instead of %d) \n " ,
commonLog . str ( ) . c_str ( ) , i , dst [ i ] . channels ( ) , 1 ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
}
int diffElemCount = calcDiffElemCount ( dst , src ) ;
if ( diffElemCount > 0 )
{
ts - > printf ( cvtest : : TS : : LOG , " %s: there are incorrect elements in dst (part of them is %f) \n " ,
commonLog . str ( ) . c_str ( ) , static_cast < float > ( diffElemCount ) / ( channels * size . area ( ) ) ) ;
return cvtest : : TS : : FAIL_INVALID_OUTPUT ;
}
return cvtest : : TS : : OK ;
}
} ;
2011-02-10 04:55:11 +08:00
TEST ( Core_PCA , accuracy ) { Core_PCATest test ; test . safe_run ( ) ; }
TEST ( Core_Reduce , accuracy ) { Core_ReduceTest test ; test . safe_run ( ) ; }
TEST ( Core_Array , basic_operations ) { Core_ArrayOpTest test ; test . safe_run ( ) ; }
2011-04-17 21:14:45 +08:00
2012-10-20 23:37:19 +08:00
TEST ( Core_Merge , shape_operations ) { Core_MergeTest test ; test . safe_run ( ) ; }
TEST ( Core_Split , shape_operations ) { Core_SplitTest test ; test . safe_run ( ) ; }
2011-04-17 21:14:45 +08:00
2012-03-26 16:18:53 +08:00
TEST ( Core_IOArray , submat_assignment )
{
Mat1f A = Mat1f : : zeros ( 2 , 2 ) ;
Mat1f B = Mat1f : : ones ( 1 , 3 ) ;
EXPECT_THROW ( B . colRange ( 0 , 3 ) . copyTo ( A . row ( 0 ) ) , cv : : Exception ) ;
EXPECT_NO_THROW ( B . colRange ( 0 , 2 ) . copyTo ( A . row ( 0 ) ) ) ;
EXPECT_EQ ( 1.0f , A ( 0 , 0 ) ) ;
EXPECT_EQ ( 1.0f , A ( 0 , 1 ) ) ;
}
void OutputArray_create1 ( OutputArray m ) { m . create ( 1 , 2 , CV_32S ) ; }
void OutputArray_create2 ( OutputArray m ) { m . create ( 1 , 3 , CV_32F ) ; }
TEST ( Core_IOArray , submat_create )
{
Mat1f A = Mat1f : : zeros ( 2 , 2 ) ;
EXPECT_THROW ( OutputArray_create1 ( A . row ( 0 ) ) , cv : : Exception ) ;
EXPECT_THROW ( OutputArray_create2 ( A . row ( 0 ) ) , cv : : Exception ) ;
}
2012-05-16 23:11:17 +08:00
2015-07-02 20:10:12 +08:00
TEST ( Core_Mat , issue4457_pass_null_ptr )
{
ASSERT_ANY_THROW ( cv : : Mat mask ( 45 , 45 , CV_32F , 0 ) ) ;
}
2012-05-16 23:11:17 +08:00
TEST ( Core_Mat , reshape_1942 )
{
cv : : Mat A = ( cv : : Mat_ < float > ( 2 , 3 ) < < 3.4884074 , 1.4159607 , 0.78737736 , 2.3456569 , - 0.88010466 , 0.3009364 ) ;
int cn = 0 ;
ASSERT_NO_THROW (
cv : : Mat_ < float > M = A . reshape ( 3 ) ;
cn = M . channels ( ) ;
) ;
ASSERT_EQ ( 1 , cn ) ;
2012-08-23 11:21:49 +08:00
}
2014-01-17 18:18:31 +08:00
2015-08-22 00:26:29 +08:00
static void check_ndim_shape ( const cv : : Mat & mat , int cn , int ndims , const int * sizes )
{
EXPECT_EQ ( mat . channels ( ) , cn ) ;
EXPECT_EQ ( mat . dims , ndims ) ;
if ( mat . dims ! = ndims )
return ;
for ( int i = 0 ; i < ndims ; i + + )
EXPECT_EQ ( mat . size [ i ] , sizes [ i ] ) ;
}
TEST ( Core_Mat , reshape_ndims_2 )
{
const cv : : Mat A ( 8 , 16 , CV_8UC3 ) ;
cv : : Mat B ;
{
int new_sizes_mask [ ] = { 0 , 3 , 4 , 4 } ;
int new_sizes_real [ ] = { 8 , 3 , 4 , 4 } ;
ASSERT_NO_THROW ( B = A . reshape ( 1 , 4 , new_sizes_mask ) ) ;
check_ndim_shape ( B , 1 , 4 , new_sizes_real ) ;
}
{
int new_sizes [ ] = { 16 , 8 } ;
ASSERT_NO_THROW ( B = A . reshape ( 0 , 2 , new_sizes ) ) ;
check_ndim_shape ( B , 3 , 2 , new_sizes ) ;
EXPECT_EQ ( B . rows , new_sizes [ 0 ] ) ;
EXPECT_EQ ( B . cols , new_sizes [ 1 ] ) ;
}
{
int new_sizes [ ] = { 2 , 5 , 1 , 3 } ;
cv : : Mat A_sliced = A ( cv : : Range : : all ( ) , cv : : Range ( 0 , 15 ) ) ;
ASSERT_ANY_THROW ( A_sliced . reshape ( 4 , 4 , new_sizes ) ) ;
}
}
TEST ( Core_Mat , reshape_ndims_4 )
{
const int sizes [ ] = { 2 , 6 , 4 , 12 } ;
const cv : : Mat A ( 4 , sizes , CV_8UC3 ) ;
cv : : Mat B ;
{
int new_sizes_mask [ ] = { 0 , 864 } ;
int new_sizes_real [ ] = { 2 , 864 } ;
ASSERT_NO_THROW ( B = A . reshape ( 1 , 2 , new_sizes_mask ) ) ;
check_ndim_shape ( B , 1 , 2 , new_sizes_real ) ;
EXPECT_EQ ( B . rows , new_sizes_real [ 0 ] ) ;
EXPECT_EQ ( B . cols , new_sizes_real [ 1 ] ) ;
}
{
int new_sizes_mask [ ] = { 4 , 0 , 0 , 2 , 3 } ;
int new_sizes_real [ ] = { 4 , 6 , 4 , 2 , 3 } ;
ASSERT_NO_THROW ( B = A . reshape ( 0 , 5 , new_sizes_mask ) ) ;
check_ndim_shape ( B , 3 , 5 , new_sizes_real ) ;
}
{
int new_sizes_mask [ ] = { 1 , 1 } ;
ASSERT_ANY_THROW ( A . reshape ( 0 , 2 , new_sizes_mask ) ) ;
}
{
int new_sizes_mask [ ] = { 4 , 6 , 3 , 3 , 0 } ;
ASSERT_ANY_THROW ( A . reshape ( 0 , 5 , new_sizes_mask ) ) ;
}
}
2015-06-05 17:46:16 +08:00
TEST ( Core_Mat , push_back )
{
Mat a = ( Mat_ < float > ( 1 , 2 ) < < 3.4884074f , 1.4159607f ) ;
Mat b = ( Mat_ < float > ( 1 , 2 ) < < 0.78737736f , 2.3456569f ) ;
a . push_back ( b ) ;
ASSERT_EQ ( 2 , a . cols ) ;
ASSERT_EQ ( 2 , a . rows ) ;
ASSERT_FLOAT_EQ ( 3.4884074f , a . at < float > ( 0 , 0 ) ) ;
ASSERT_FLOAT_EQ ( 1.4159607f , a . at < float > ( 0 , 1 ) ) ;
ASSERT_FLOAT_EQ ( 0.78737736f , a . at < float > ( 1 , 0 ) ) ;
ASSERT_FLOAT_EQ ( 2.3456569f , a . at < float > ( 1 , 1 ) ) ;
Mat c = ( Mat_ < float > ( 2 , 2 ) < < - 0.88010466f , 0.3009364f , 2.22399974f , - 5.45933905f ) ;
ASSERT_EQ ( c . rows , a . cols ) ;
a . push_back ( c . t ( ) ) ;
ASSERT_EQ ( 2 , a . cols ) ;
ASSERT_EQ ( 4 , a . rows ) ;
ASSERT_FLOAT_EQ ( 3.4884074f , a . at < float > ( 0 , 0 ) ) ;
ASSERT_FLOAT_EQ ( 1.4159607f , a . at < float > ( 0 , 1 ) ) ;
ASSERT_FLOAT_EQ ( 0.78737736f , a . at < float > ( 1 , 0 ) ) ;
ASSERT_FLOAT_EQ ( 2.3456569f , a . at < float > ( 1 , 1 ) ) ;
ASSERT_FLOAT_EQ ( - 0.88010466f , a . at < float > ( 2 , 0 ) ) ;
ASSERT_FLOAT_EQ ( 2.22399974f , a . at < float > ( 2 , 1 ) ) ;
ASSERT_FLOAT_EQ ( 0.3009364f , a . at < float > ( 3 , 0 ) ) ;
ASSERT_FLOAT_EQ ( - 5.45933905f , a . at < float > ( 3 , 1 ) ) ;
a . push_back ( Mat : : ones ( 2 , 2 , CV_32FC1 ) ) ;
ASSERT_EQ ( 6 , a . rows ) ;
for ( int row = 4 ; row < a . rows ; row + + ) {
for ( int col = 0 ; col < a . cols ; col + + ) {
ASSERT_FLOAT_EQ ( 1.f , a . at < float > ( row , col ) ) ;
}
}
}
2014-01-17 18:18:31 +08:00
TEST ( Core_Mat , copyNx1ToVector )
{
cv : : Mat_ < uchar > src ( 5 , 1 ) ;
cv : : Mat_ < uchar > ref_dst8 ;
cv : : Mat_ < ushort > ref_dst16 ;
std : : vector < uchar > dst8 ;
std : : vector < ushort > dst16 ;
src < < 1 , 2 , 3 , 4 , 5 ;
src . copyTo ( ref_dst8 ) ;
src . copyTo ( dst8 ) ;
ASSERT_PRED_FORMAT2 ( cvtest : : MatComparator ( 0 , 0 ) , ref_dst8 , cv : : Mat_ < uchar > ( dst8 ) ) ;
src . convertTo ( ref_dst16 , CV_16U ) ;
src . convertTo ( dst16 , CV_16U ) ;
ASSERT_PRED_FORMAT2 ( cvtest : : MatComparator ( 0 , 0 ) , ref_dst16 , cv : : Mat_ < ushort > ( dst16 ) ) ;
}
2015-04-29 21:09:58 +08:00
2015-05-02 02:49:11 +08:00
TEST ( Core_Matx , fromMat_ )
{
Mat_ < double > a = ( Mat_ < double > ( 2 , 2 ) < < 10 , 11 , 12 , 13 ) ;
Matx22d b ( a ) ;
2015-06-16 22:56:00 +08:00
ASSERT_EQ ( cvtest : : norm ( a , b , NORM_INF ) , 0. ) ;
2015-05-02 02:49:11 +08:00
}
2017-07-15 01:17:09 +08:00
# ifdef CV_CXX11
2017-09-01 13:20:43 +08:00
2017-07-15 01:17:09 +08:00
TEST ( Core_Matx , from_initializer_list )
{
Mat_ < double > a = ( Mat_ < double > ( 2 , 2 ) < < 10 , 11 , 12 , 13 ) ;
Matx22d b = { 10 , 11 , 12 , 13 } ;
ASSERT_EQ ( cvtest : : norm ( a , b , NORM_INF ) , 0. ) ;
}
2017-09-01 13:20:43 +08:00
TEST ( Core_Mat , regression_9507 )
{
cv : : Mat m = Mat : : zeros ( 5 , 5 , CV_8UC3 ) ;
cv : : Mat m2 { m } ;
EXPECT_EQ ( 25u , m2 . total ( ) ) ;
}
# endif // CXX11
2017-07-15 01:17:09 +08:00
2015-05-03 01:38:30 +08:00
TEST ( Core_InputArray , empty )
{
vector < vector < Point > > data ;
ASSERT_TRUE ( _InputArray ( data ) . empty ( ) ) ;
}
2015-05-03 07:46:33 +08:00
TEST ( Core_CopyMask , bug1918 )
{
Mat_ < unsigned char > tmpSrc ( 100 , 100 ) ;
tmpSrc = 124 ;
Mat_ < unsigned char > tmpMask ( 100 , 100 ) ;
tmpMask = 255 ;
Mat_ < unsigned char > tmpDst ( 100 , 100 ) ;
tmpDst = 2 ;
tmpSrc . copyTo ( tmpDst , tmpMask ) ;
ASSERT_EQ ( sum ( tmpDst ) [ 0 ] , 124 * 100 * 100 ) ;
}
2015-04-29 21:09:58 +08:00
TEST ( Core_SVD , orthogonality )
{
for ( int i = 0 ; i < 2 ; i + + )
{
int type = i = = 0 ? CV_32F : CV_64F ;
Mat mat_D ( 2 , 2 , type ) ;
mat_D . setTo ( 88. ) ;
Mat mat_U , mat_W ;
SVD : : compute ( mat_D , mat_W , mat_U , noArray ( ) , SVD : : FULL_UV ) ;
mat_U * = mat_U . t ( ) ;
ASSERT_LT ( norm ( mat_U , Mat : : eye ( 2 , 2 , type ) , NORM_INF ) , 1e-5 ) ;
}
}
2015-05-15 04:29:09 +08:00
TEST ( Core_SparseMat , footprint )
{
int n = 1000000 ;
int sz [ ] = { n , n } ;
SparseMat m ( 2 , sz , CV_64F ) ;
int nodeSize0 = ( int ) m . hdr - > nodeSize ;
double dataSize0 = ( ( double ) m . hdr - > pool . size ( ) + ( double ) m . hdr - > hashtab . size ( ) * sizeof ( size_t ) ) * 1e-6 ;
printf ( " before: node size=%d bytes, data size=%.0f Mbytes \n " , nodeSize0 , dataSize0 ) ;
for ( int i = 0 ; i < n ; i + + )
{
m . ref < double > ( i , i ) = 1 ;
}
double dataSize1 = ( ( double ) m . hdr - > pool . size ( ) + ( double ) m . hdr - > hashtab . size ( ) * sizeof ( size_t ) ) * 1e-6 ;
double threshold = ( n * nodeSize0 * 1.6 + n * 2. * sizeof ( size_t ) ) * 1e-6 ;
printf ( " after: data size=%.0f Mbytes, threshold=%.0f MBytes \n " , dataSize1 , threshold ) ;
ASSERT_LE ( ( int ) m . hdr - > nodeSize , 32 ) ;
ASSERT_LE ( dataSize1 , threshold ) ;
}
2015-06-26 18:35:27 +08:00
2016-07-19 21:18:48 +08:00
// Can't fix without dirty hacks or broken user code (PR #4159)
2015-07-02 01:08:36 +08:00
TEST ( Core_Mat_vector , DISABLED_OutputArray_create_getMat )
2015-06-26 18:35:27 +08:00
{
cv : : Mat_ < uchar > src_base ( 5 , 1 ) ;
std : : vector < uchar > dst8 ;
src_base < < 1 , 2 , 3 , 4 , 5 ;
Mat src ( src_base ) ;
OutputArray _dst ( dst8 ) ;
{
_dst . create ( src . rows , src . cols , src . type ( ) ) ;
Mat dst = _dst . getMat ( ) ;
EXPECT_EQ ( src . dims , dst . dims ) ;
EXPECT_EQ ( src . cols , dst . cols ) ;
EXPECT_EQ ( src . rows , dst . rows ) ;
}
}
TEST ( Core_Mat_vector , copyTo_roi_column )
{
cv : : Mat_ < uchar > src_base ( 5 , 2 ) ;
std : : vector < uchar > dst1 ;
src_base < < 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ;
Mat src_full ( src_base ) ;
Mat src ( src_full . col ( 0 ) ) ;
2016-07-19 21:18:48 +08:00
#if 0 // Can't fix without dirty hacks or broken user code (PR #4159)
2015-06-26 18:35:27 +08:00
OutputArray _dst ( dst1 ) ;
{
_dst . create ( src . rows , src . cols , src . type ( ) ) ;
Mat dst = _dst . getMat ( ) ;
EXPECT_EQ ( src . dims , dst . dims ) ;
EXPECT_EQ ( src . cols , dst . cols ) ;
EXPECT_EQ ( src . rows , dst . rows ) ;
}
2015-07-02 01:08:36 +08:00
# endif
2015-06-26 18:35:27 +08:00
std : : vector < uchar > dst2 ;
src . copyTo ( dst2 ) ;
std : : cout < < " src = " < < src < < std : : endl ;
std : : cout < < " dst = " < < Mat ( dst2 ) < < std : : endl ;
EXPECT_EQ ( ( size_t ) 5 , dst2 . size ( ) ) ;
EXPECT_EQ ( 1 , ( int ) dst2 [ 0 ] ) ;
EXPECT_EQ ( 3 , ( int ) dst2 [ 1 ] ) ;
EXPECT_EQ ( 5 , ( int ) dst2 [ 2 ] ) ;
EXPECT_EQ ( 7 , ( int ) dst2 [ 3 ] ) ;
EXPECT_EQ ( 9 , ( int ) dst2 [ 4 ] ) ;
}
TEST ( Core_Mat_vector , copyTo_roi_row )
{
cv : : Mat_ < uchar > src_base ( 2 , 5 ) ;
std : : vector < uchar > dst1 ;
src_base < < 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ;
Mat src_full ( src_base ) ;
Mat src ( src_full . row ( 0 ) ) ;
OutputArray _dst ( dst1 ) ;
{
_dst . create ( src . rows , src . cols , src . type ( ) ) ;
Mat dst = _dst . getMat ( ) ;
EXPECT_EQ ( src . dims , dst . dims ) ;
EXPECT_EQ ( src . cols , dst . cols ) ;
EXPECT_EQ ( src . rows , dst . rows ) ;
}
std : : vector < uchar > dst2 ;
src . copyTo ( dst2 ) ;
std : : cout < < " src = " < < src < < std : : endl ;
std : : cout < < " dst = " < < Mat ( dst2 ) < < std : : endl ;
EXPECT_EQ ( ( size_t ) 5 , dst2 . size ( ) ) ;
EXPECT_EQ ( 1 , ( int ) dst2 [ 0 ] ) ;
EXPECT_EQ ( 2 , ( int ) dst2 [ 1 ] ) ;
EXPECT_EQ ( 3 , ( int ) dst2 [ 2 ] ) ;
EXPECT_EQ ( 4 , ( int ) dst2 [ 3 ] ) ;
EXPECT_EQ ( 5 , ( int ) dst2 [ 4 ] ) ;
}
2016-01-26 18:49:11 +08:00
TEST ( Mat , regression_5991 )
{
int sz [ ] = { 2 , 3 , 2 } ;
Mat mat ( 3 , sz , CV_32F , Scalar ( 1 ) ) ;
ASSERT_NO_THROW ( mat . convertTo ( mat , CV_8U ) ) ;
EXPECT_EQ ( sz [ 0 ] , mat . size [ 0 ] ) ;
EXPECT_EQ ( sz [ 1 ] , mat . size [ 1 ] ) ;
EXPECT_EQ ( sz [ 2 ] , mat . size [ 2 ] ) ;
EXPECT_EQ ( 0 , cvtest : : norm ( mat , Mat ( 3 , sz , CV_8U , Scalar ( 1 ) ) , NORM_INF ) ) ;
}
2016-07-08 22:46:08 +08:00
# 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 < Mat > planes ;
split ( destImageBGR , planes ) ;
planes . push_back ( destImageA ) ;
merge ( planes , destImageBGR ) ;
EXPECT_EQ ( 1 , destImageBGR . at < Vec4b > ( 0 ) [ 0 ] ) ;
EXPECT_EQ ( 2 , destImageBGR . at < Vec4b > ( 0 ) [ 1 ] ) ;
EXPECT_EQ ( 3 , destImageBGR . at < Vec4b > ( 0 ) [ 2 ] ) ;
EXPECT_EQ ( 4 , destImageBGR . at < Vec4b > ( 0 ) [ 3 ] ) ;
EXPECT_EQ ( 1 , destImageBGR . at < Vec4b > ( height - 1 , width - 1 ) [ 0 ] ) ;
EXPECT_EQ ( 2 , destImageBGR . at < Vec4b > ( height - 1 , width - 1 ) [ 1 ] ) ;
EXPECT_EQ ( 3 , destImageBGR . at < Vec4b > ( height - 1 , width - 1 ) [ 2 ] ) ;
EXPECT_EQ ( 4 , destImageBGR . at < Vec4b > ( height - 1 , width - 1 ) [ 3 ] ) ;
}
# endif
2016-07-14 21:09:28 +08:00
TEST ( Reduce , regression_should_fail_bug_4594 )
{
cv : : Mat src = cv : : Mat : : eye ( 4 , 4 , CV_8U ) ;
std : : vector < int > dst ;
EXPECT_THROW ( cv : : reduce ( src , dst , 0 , CV_REDUCE_MIN , CV_32S ) , cv : : Exception ) ;
EXPECT_THROW ( cv : : reduce ( src , dst , 0 , CV_REDUCE_MAX , CV_32S ) , cv : : Exception ) ;
EXPECT_NO_THROW ( cv : : reduce ( src , dst , 0 , CV_REDUCE_SUM , CV_32S ) ) ;
EXPECT_NO_THROW ( cv : : reduce ( src , dst , 0 , CV_REDUCE_AVG , CV_32S ) ) ;
}
2016-07-14 22:13:09 +08:00
TEST ( Mat , push_back_vector )
{
cv : : Mat result ( 1 , 5 , CV_32FC1 ) ;
std : : vector < float > vec1 ( result . cols + 1 ) ;
std : : vector < int > vec2 ( result . cols ) ;
EXPECT_THROW ( result . push_back ( vec1 ) , cv : : Exception ) ;
EXPECT_THROW ( result . push_back ( vec2 ) , cv : : Exception ) ;
vec1 . resize ( result . cols ) ;
for ( int i = 0 ; i < 5 ; + + i )
result . push_back ( cv : : Mat ( vec1 ) . reshape ( 1 , 1 ) ) ;
ASSERT_EQ ( 6 , result . rows ) ;
}
2016-07-14 21:36:57 +08:00
TEST ( Mat , regression_5917_clone_empty )
{
Mat cloned ;
Mat_ < Point2f > source ( 5 , 0 ) ;
ASSERT_NO_THROW ( cloned = source . clone ( ) ) ;
}
2016-12-15 23:16:40 +08:00
TEST ( Mat , regression_7873_mat_vector_initialize )
{
std : : vector < int > dims ;
dims . push_back ( 12 ) ;
dims . push_back ( 3 ) ;
dims . push_back ( 2 ) ;
Mat multi_mat ( dims , CV_32FC1 , cv : : Scalar ( 0 ) ) ;
ASSERT_EQ ( 3 , multi_mat . dims ) ;
ASSERT_EQ ( 12 , multi_mat . size [ 0 ] ) ;
ASSERT_EQ ( 3 , multi_mat . size [ 1 ] ) ;
ASSERT_EQ ( 2 , multi_mat . size [ 2 ] ) ;
std : : vector < Range > ranges ;
ranges . push_back ( Range ( 1 , 2 ) ) ;
ranges . push_back ( Range : : all ( ) ) ;
ranges . push_back ( Range : : all ( ) ) ;
Mat sub_mat = multi_mat ( ranges ) ;
ASSERT_EQ ( 3 , sub_mat . dims ) ;
ASSERT_EQ ( 1 , sub_mat . size [ 0 ] ) ;
ASSERT_EQ ( 3 , sub_mat . size [ 1 ] ) ;
ASSERT_EQ ( 2 , sub_mat . size [ 2 ] ) ;
}
2017-04-19 18:13:39 +08:00
# ifdef CV_CXX_STD_ARRAY
TEST ( Core_Mat_array , outputArray_create_getMat )
{
cv : : Mat_ < uchar > src_base ( 5 , 1 ) ;
std : : array < uchar , 5 > dst8 ;
src_base < < 1 , 2 , 3 , 4 , 5 ;
Mat src ( src_base ) ;
OutputArray _dst ( dst8 ) ;
{
_dst . create ( src . rows , src . cols , src . type ( ) ) ;
Mat dst = _dst . getMat ( ) ;
EXPECT_EQ ( src . dims , dst . dims ) ;
EXPECT_EQ ( src . cols , dst . cols ) ;
EXPECT_EQ ( src . rows , dst . rows ) ;
}
}
TEST ( Core_Mat_array , copyTo_roi_column )
{
cv : : Mat_ < uchar > src_base ( 5 , 2 ) ;
src_base < < 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ;
Mat src_full ( src_base ) ;
Mat src ( src_full . col ( 0 ) ) ;
std : : array < uchar , 5 > dst1 ;
src . copyTo ( dst1 ) ;
std : : cout < < " src = " < < src < < std : : endl ;
std : : cout < < " dst = " < < Mat ( dst1 ) < < std : : endl ;
EXPECT_EQ ( ( size_t ) 5 , dst1 . size ( ) ) ;
EXPECT_EQ ( 1 , ( int ) dst1 [ 0 ] ) ;
EXPECT_EQ ( 3 , ( int ) dst1 [ 1 ] ) ;
EXPECT_EQ ( 5 , ( int ) dst1 [ 2 ] ) ;
EXPECT_EQ ( 7 , ( int ) dst1 [ 3 ] ) ;
EXPECT_EQ ( 9 , ( int ) dst1 [ 4 ] ) ;
}
TEST ( Core_Mat_array , copyTo_roi_row )
{
cv : : Mat_ < uchar > src_base ( 2 , 5 ) ;
std : : array < uchar , 5 > dst1 ;
src_base < < 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ;
Mat src_full ( src_base ) ;
Mat src ( src_full . row ( 0 ) ) ;
OutputArray _dst ( dst1 ) ;
{
_dst . create ( 5 , 1 , src . type ( ) ) ;
Mat dst = _dst . getMat ( ) ;
EXPECT_EQ ( src . dims , dst . dims ) ;
EXPECT_EQ ( 1 , dst . cols ) ;
EXPECT_EQ ( 5 , dst . rows ) ;
}
std : : array < uchar , 5 > dst2 ;
src . copyTo ( dst2 ) ;
std : : cout < < " src = " < < src < < std : : endl ;
std : : cout < < " dst = " < < Mat ( dst2 ) < < std : : endl ;
EXPECT_EQ ( 1 , ( int ) dst2 [ 0 ] ) ;
EXPECT_EQ ( 2 , ( int ) dst2 [ 1 ] ) ;
EXPECT_EQ ( 3 , ( int ) dst2 [ 2 ] ) ;
EXPECT_EQ ( 4 , ( int ) dst2 [ 3 ] ) ;
EXPECT_EQ ( 5 , ( int ) dst2 [ 4 ] ) ;
}
TEST ( Core_Mat_array , SplitMerge )
{
std : : array < cv : : Mat , 3 > src ;
for ( size_t i = 0 ; i < src . size ( ) ; + + i ) {
src [ i ] . create ( 10 , 10 , CV_8U ) ;
src [ i ] = 127 * i ;
}
Mat merged ;
merge ( src , merged ) ;
std : : array < cv : : Mat , 3 > dst ;
split ( merged , dst ) ;
Mat diff ;
for ( size_t i = 0 ; i < dst . size ( ) ; + + i ) {
absdiff ( src [ i ] , dst [ i ] , diff ) ;
EXPECT_EQ ( 0 , countNonZero ( diff ) ) ;
}
}
2017-05-23 17:20:48 +08:00
# endif
TEST ( Mat , regression_8680 )
{
Mat_ < Point2i > mat ( 3 , 1 ) ;
ASSERT_EQ ( mat . channels ( ) , 2 ) ;
mat . release ( ) ;
ASSERT_EQ ( mat . channels ( ) , 2 ) ;
}
2017-07-03 17:42:47 +08:00
2017-07-15 01:17:09 +08:00
# ifdef CV_CXX11
2017-07-03 17:42:47 +08:00
TEST ( Mat_ , range_based_for )
{
Mat_ < uchar > img = Mat_ < uchar > : : zeros ( 3 , 3 ) ;
for ( auto & pixel : img )
{
pixel = 1 ;
}
Mat_ < uchar > ref ( 3 , 3 ) ;
ref . setTo ( Scalar ( 1 ) ) ;
ASSERT_DOUBLE_EQ ( norm ( img , ref ) , 0. ) ;
}
2017-07-15 01:17:09 +08:00
TEST ( Mat , from_initializer_list )
{
Mat A ( { 1.f , 2.f , 3.f } ) ;
Mat_ < float > B ( 3 , 1 ) ; B < < 1 , 2 , 3 ;
ASSERT_EQ ( A . type ( ) , CV_32F ) ;
ASSERT_DOUBLE_EQ ( norm ( A , B , NORM_INF ) , 0. ) ;
}
TEST ( Mat_ , from_initializer_list )
{
Mat_ < float > A = { 1 , 2 , 3 } ;
Mat_ < float > B ( 3 , 1 ) ; B < < 1 , 2 , 3 ;
ASSERT_DOUBLE_EQ ( norm ( A , B , NORM_INF ) , 0. ) ;
}
2017-10-10 13:28:07 +08:00
TEST ( Mat , template_based_ptr )
{
Mat mat = ( Mat_ < float > ( 2 , 2 ) < < 11.0f , 22.0f , 33.0f , 44.0f ) ;
int idx [ 2 ] = { 1 , 0 } ;
ASSERT_FLOAT_EQ ( 33.0f , * ( mat . ptr < float > ( idx ) ) ) ;
idx [ 0 ] = 1 ;
idx [ 1 ] = 1 ;
ASSERT_FLOAT_EQ ( 44.0f , * ( mat . ptr < float > ( idx ) ) ) ;
}
TEST ( Mat_ , template_based_ptr )
{
int dim [ 4 ] = { 2 , 2 , 1 , 2 } ;
Mat_ < float > mat = ( Mat_ < float > ( 4 , dim ) < < 11.0f , 22.0f , 33.0f , 44.0f ,
55.0f , 66.0f , 77.0f , 88.0f ) ;
int idx [ 4 ] = { 1 , 0 , 0 , 1 } ;
ASSERT_FLOAT_EQ ( 66.0f , * ( mat . ptr < float > ( idx ) ) ) ;
}
2017-07-03 17:42:47 +08:00
# endif