opencv/tests/cxcore/src/areduce.cpp
2010-07-09 09:09:20 +00:00

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;