/*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 "cxcoretest.h" using namespace cv; class CV_ReduceTest : public CvTest { public: CV_ReduceTest() : CvTest( "reduce", "reduce" ) {} protected: void run( int); int checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim, double eps ); int checkCase( int srcType, int dstType, int dim, Size sz ); int checkDim( int dim, Size sz ); int checkSize( Size sz ); }; template void testReduce( const Mat& src, Mat& sum, Mat& avg, Mat& max, Mat& min, int dim ) { assert( src.channels() == 1 ); if( dim == 0 ) // row { sum.create( 1, src.cols, CV_64FC1 ); max.create( 1, src.cols, CV_64FC1 ); min.create( 1, src.cols, CV_64FC1 ); } else { sum.create( src.rows, 1, CV_64FC1 ); 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)); const Mat_& src_ = src; Mat_& sum_ = (Mat_&)sum; Mat_& min_ = (Mat_&)min; Mat_& max_ = (Mat_&)max; 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"; } int CV_ReduceTest::checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim, double eps ) { 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 CvTS::OK; assert( opRes.type() == CV_64FC1 ); Mat _dst, dst; reduce( src, _dst, dim, opType, dstType ); _dst.convertTo( dst, CV_64FC1 ); if( norm( opRes, dst, NORM_INF ) > eps ) { 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"; sprintf( msg, "bad accuracy with srcType = %s, dstType = %s, opType = %s, dim = %s", srcTypeStr.c_str(), dstTypeStr.c_str(), opTypeStr, dimStr ); ts->printf( CvTS::LOG, msg ); return CvTS::FAIL_BAD_ACCURACY; } return CvTS::OK; } int CV_ReduceTest::checkCase( int srcType, int dstType, int dim, Size sz ) { int code = CvTS::OK, tempCode; Mat src, sum, avg, max, min; src.create( sz, srcType ); randu( src, Scalar(0), Scalar(100) ); if( srcType == CV_8UC1 ) testReduce( src, sum, avg, max, min, dim ); else if( srcType == CV_8SC1 ) testReduce( src, sum, avg, max, min, dim ); else if( srcType == CV_16UC1 ) testReduce( src, sum, avg, max, min, dim ); else if( srcType == CV_16SC1 ) testReduce( src, sum, avg, max, min, dim ); else if( srcType == CV_32SC1 ) testReduce( src, sum, avg, max, min, dim ); else if( srcType == CV_32FC1 ) testReduce( src, sum, avg, max, min, dim ); else if( srcType == CV_64FC1 ) testReduce( src, sum, avg, max, min, dim ); else assert( 0 ); // 1. sum tempCode = checkOp( src, dstType, CV_REDUCE_SUM, sum, dim, srcType == CV_32FC1 && dstType == CV_32FC1 ? 0.05 : FLT_EPSILON ); code = tempCode != CvTS::OK ? tempCode : code; // 2. avg tempCode = checkOp( src, dstType, CV_REDUCE_AVG, avg, dim, dstType == CV_32SC1 ? 0.6 : 0.00007 ); code = tempCode != CvTS::OK ? tempCode : code; // 3. max tempCode = checkOp( src, dstType, CV_REDUCE_MAX, max, dim, FLT_EPSILON ); code = tempCode != CvTS::OK ? tempCode : code; // 4. min tempCode = checkOp( src, dstType, CV_REDUCE_MIN, min, dim, FLT_EPSILON ); code = tempCode != CvTS::OK ? tempCode : code; return code; } int CV_ReduceTest::checkDim( int dim, Size sz ) { int code = CvTS::OK, tempCode; // CV_8UC1 tempCode = checkCase( CV_8UC1, CV_8UC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkCase( CV_8UC1, CV_32SC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkCase( CV_8UC1, CV_32FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkCase( CV_8UC1, CV_64FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; // CV_16UC1 tempCode = checkCase( CV_16UC1, CV_32FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkCase( CV_16UC1, CV_64FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; // CV_16SC1 tempCode = checkCase( CV_16SC1, CV_32FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkCase( CV_16SC1, CV_64FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; // CV_32FC1 tempCode = checkCase( CV_32FC1, CV_32FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkCase( CV_32FC1, CV_64FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; // CV_64FC1 tempCode = checkCase( CV_64FC1, CV_64FC1, dim, sz ); code = tempCode != CvTS::OK ? tempCode : code; return code; } int CV_ReduceTest::checkSize( Size sz ) { int code = CvTS::OK, tempCode; tempCode = checkDim( 0, sz ); // rows code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkDim( 1, sz ); // cols code = tempCode != CvTS::OK ? tempCode : code; return code; } void CV_ReduceTest::run( int ) { int code = CvTS::OK, tempCode; tempCode = checkSize( Size(1,1) ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkSize( Size(1,100) ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkSize( Size(100,1) ); code = tempCode != CvTS::OK ? tempCode : code; tempCode = checkSize( Size(1000,500) ); code = tempCode != CvTS::OK ? tempCode : code; ts->set_failed_test_info( code ); } CV_ReduceTest reduce_test;