309 lines
11 KiB
C++
309 lines
11 KiB
C++
/*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<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
|
|
{
|
|
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_<Type>& src_ = src;
|
|
Mat_<double>& sum_ = (Mat_<double>&)sum;
|
|
Mat_<double>& min_ = (Mat_<double>&)min;
|
|
Mat_<double>& max_ = (Mat_<double>&)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<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 );
|
|
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;
|