reworked nearly all of the OpenCV tests (except for opencv_gpu tests) - they now use the Google Test engine.

This commit is contained in:
Vadim Pisarevsky
2011-02-09 20:55:11 +00:00
parent 63806c9ab9
commit 061b49e0b2
122 changed files with 39081 additions and 28854 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,829 @@
#include "test_precomp.hpp"
using namespace cv;
using namespace std;
namespace cvtest
{
static Mat initDFTWave( int n, bool inv )
{
int i;
double angle = (inv ? 1 : -1)*CV_PI*2/n;
Complexd wi, w1;
Mat wave(1, n, CV_64FC2);
Complexd* w = wave.ptr<Complexd>();
w1.re = cos(angle);
w1.im = sin(angle);
w[0].re = wi.re = 1.;
w[0].im = wi.im = 0.;
for( i = 1; i < n; i++ )
{
double t = wi.re*w1.re - wi.im*w1.im;
wi.im = wi.re*w1.im + wi.im*w1.re;
wi.re = t;
w[i] = wi;
}
return wave;
}
static void DFT_1D( const Mat& _src, Mat& _dst, int flags, const Mat& _wave=Mat())
{
_dst.create(_src.size(), _src.type());
int i, j, k, n = _dst.cols + _dst.rows - 1;
Mat wave = _wave;
double scale = (flags & DFT_SCALE) ? 1./n : 1.;
size_t esz = _src.elemSize();
size_t srcstep = esz, dststep = esz;
const uchar* src0 = _src.data;
uchar* dst0 = _dst.data;
CV_Assert( _src.cols + _src.rows - 1 == n );
if( wave.empty() )
wave = initDFTWave( n, (flags & DFT_INVERSE) != 0 );
const Complexd* w = wave.ptr<Complexd>();
if( !_src.isContinuous() )
srcstep = _src.step;
if( !_dst.isContinuous() )
dststep = _dst.step;
if( _src.type() == CV_32FC2 )
{
for( i = 0; i < n; i++ )
{
Complexf* dst = (Complexf*)(dst0 + i*dststep);
Complexd sum(0,0);
int delta = i;
k = 0;
for( j = 0; j < n; j++ )
{
const Complexf* src = (const Complexf*)(src0 + j*srcstep);
sum.re += src->re*w[k].re - src->im*w[k].im;
sum.im += src->re*w[k].im + src->im*w[k].re;
k += delta;
k -= (k >= n ? n : 0);
}
dst->re = (float)(sum.re*scale);
dst->im = (float)(sum.im*scale);
}
}
else if( _src.type() == CV_64FC2 )
{
for( i = 0; i < n; i++ )
{
Complexd* dst = (Complexd*)(dst0 + i*dststep);
Complexd sum(0,0);
int delta = i;
k = 0;
for( j = 0; j < n; j++ )
{
const Complexd* src = (const Complexd*)(src0 + j*srcstep);
sum.re += src->re*w[k].re - src->im*w[k].im;
sum.im += src->re*w[k].im + src->im*w[k].re;
k += delta;
k -= (k >= n ? n : 0);
}
dst->re = sum.re*scale;
dst->im = sum.im*scale;
}
}
else
CV_Error(CV_StsUnsupportedFormat, "");
}
static void DFT_2D( const Mat& src, Mat& dst, int flags )
{
const int cn = 2;
int i;
dst.create(src.size(), src.type());
Mat tmp( src.cols, src.rows, src.type());
Mat wave = initDFTWave( dst.cols, (flags & DFT_INVERSE) != 0 );
// 1. row-wise transform
for( i = 0; i < dst.rows; i++ )
{
Mat srci = src.row(i).reshape(cn, src.cols), dsti = tmp.col(i);
DFT_1D(srci, dsti, flags, wave );
}
if( (flags & DFT_ROWS) == 0 )
{
if( dst.cols != dst.rows )
wave = initDFTWave( dst.rows, (flags & DFT_INVERSE) != 0 );
// 2. column-wise transform
for( i = 0; i < dst.cols; i++ )
{
Mat srci = tmp.row(i).reshape(cn, tmp.cols), dsti = dst.col(i);
DFT_1D(srci, dsti, flags, wave );
}
}
else
cvtest::transpose(tmp, dst);
}
static Mat initDCTWave( int n, bool inv )
{
int i, k;
double angle = CV_PI*0.5/n;
Mat wave(n, n, CV_64F);
double scale = sqrt(1./n);
for( k = 0; k < n; k++ )
wave.at<double>(0, k) = scale;
scale *= sqrt(2.);
for( i = 1; i < n; i++ )
for( k = 0; k < n; k++ )
wave.at<double>(i, k) = scale*cos( angle*i*(2*k + 1) );
if( inv )
cv::transpose( wave, wave );
return wave;
}
static void DCT_1D( const Mat& _src, Mat& _dst, int flags, const Mat& _wave=Mat() )
{
_dst.create( _src.size(), _src.type() );
int i, j, n = _dst.cols + _dst.rows - 1;
Mat wave = _wave;
int srcstep = 1, dststep = 1;
double* w;
CV_Assert( _src.cols + _src.rows - 1 == n);
if( wave.empty() )
wave = initDCTWave( n, (flags & DFT_INVERSE) != 0 );
w = wave.ptr<double>();
if( !_src.isContinuous() )
srcstep = _src.step/_src.elemSize();
if( !_dst.isContinuous() )
dststep = _dst.step/_dst.elemSize();
if( _src.type() == CV_32FC1 )
{
float *dst = _dst.ptr<float>();
for( i = 0; i < n; i++, dst += dststep )
{
const float* src = _src.ptr<float>();
double sum = 0;
for( j = 0; j < n; j++, src += srcstep )
sum += src[0]*w[j];
w += n;
dst[0] = (float)sum;
}
}
else if( _src.type() == CV_64FC1 )
{
double *dst = _dst.ptr<double>();
for( i = 0; i < n; i++, dst += dststep )
{
const double* src = _src.ptr<double>();
double sum = 0;
for( j = 0; j < n; j++, src += srcstep )
sum += src[0]*w[j];
w += n;
dst[0] = sum;
}
}
else
assert(0);
}
static void DCT_2D( const Mat& src, Mat& dst, int flags )
{
const int cn = 1;
int i;
dst.create( src.size(), src.type() );
Mat tmp(dst.cols, dst.rows, dst.type() );
Mat wave = initDCTWave( dst.cols, (flags & DCT_INVERSE) != 0 );
// 1. row-wise transform
for( i = 0; i < dst.rows; i++ )
{
Mat srci = src.row(i).reshape(cn, src.cols);
Mat dsti = tmp.col(i);
DCT_1D(srci, dsti, flags, wave);
}
if( (flags & DCT_ROWS) == 0 )
{
if( dst.cols != dst.rows )
wave = initDCTWave( dst.rows, (flags & DCT_INVERSE) != 0 );
// 2. column-wise transform
for( i = 0; i < dst.cols; i++ )
{
Mat srci = tmp.row(i).reshape(cn, tmp.cols);
Mat dsti = dst.col(i);
DCT_1D( srci, dsti, flags, wave );
}
}
else
cvtest::transpose( tmp, dst );
}
static void convertFromCCS( const Mat& _src0, const Mat& _src1, Mat& _dst, int flags )
{
if( _dst.rows > 1 && (_dst.cols > 1 || (flags & DFT_ROWS)) )
{
int i, count = _dst.rows, len = _dst.cols;
bool is2d = (flags & DFT_ROWS) == 0;
Mat src0row, src1row, dstrow;
for( i = 0; i < count; i++ )
{
int j = !is2d || i == 0 ? i : count - i;
src0row = _src0.row(i);
src1row = _src1.row(j);
dstrow = _dst.row(i);
convertFromCCS( src0row, src1row, dstrow, 0 );
}
if( is2d )
{
src0row = _src0.col(0);
dstrow = _dst.col(0);
convertFromCCS( src0row, src0row, dstrow, 0 );
if( (len & 1) == 0 )
{
src0row = _src0.col(_src0.cols - 1);
dstrow = _dst.col(len/2);
convertFromCCS( src0row, src0row, dstrow, 0 );
}
}
}
else
{
int i, n = _dst.cols + _dst.rows - 1, n2 = (n+1) >> 1;
int cn = _src0.channels();
int srcstep = cn, dststep = 1;
if( !_dst.isContinuous() )
dststep = _dst.step/_dst.elemSize();
if( !_src0.isContinuous() )
srcstep = _src0.step/_src0.elemSize1();
if( _dst.depth() == CV_32F )
{
Complexf* dst = _dst.ptr<Complexf>();
const float* src0 = _src0.ptr<float>();
const float* src1 = _src1.ptr<float>();
int delta0, delta1;
dst->re = src0[0];
dst->im = 0;
if( (n & 1) == 0 )
{
dst[n2*dststep].re = src0[(cn == 1 ? n-1 : n2)*srcstep];
dst[n2*dststep].im = 0;
}
delta0 = srcstep;
delta1 = delta0 + (cn == 1 ? srcstep : 1);
if( cn == 1 )
srcstep *= 2;
for( i = 1; i < n2; i++, delta0 += srcstep, delta1 += srcstep )
{
float t0 = src0[delta0];
float t1 = src0[delta1];
dst[i*dststep].re = t0;
dst[i*dststep].im = t1;
t0 = src1[delta0];
t1 = -src1[delta1];
dst[(n-i)*dststep].re = t0;
dst[(n-i)*dststep].im = t1;
}
}
else
{
Complexd* dst = _dst.ptr<Complexd>();
const double* src0 = _src0.ptr<double>();
const double* src1 = _src1.ptr<double>();
int delta0, delta1;
dst->re = src0[0];
dst->im = 0;
if( (n & 1) == 0 )
{
dst[n2*dststep].re = src0[(cn == 1 ? n-1 : n2)*srcstep];
dst[n2*dststep].im = 0;
}
delta0 = srcstep;
delta1 = delta0 + (cn == 1 ? srcstep : 1);
if( cn == 1 )
srcstep *= 2;
for( i = 1; i < n2; i++, delta0 += srcstep, delta1 += srcstep )
{
double t0 = src0[delta0];
double t1 = src0[delta1];
dst[i*dststep].re = t0;
dst[i*dststep].im = t1;
t0 = src1[delta0];
t1 = -src1[delta1];
dst[(n-i)*dststep].re = t0;
dst[(n-i)*dststep].im = t1;
}
}
}
}
static void fixCCS( Mat& mat, int cols, int flags )
{
int i, rows = mat.rows;
int rows2 = (flags & DFT_ROWS) ? rows : rows/2 + 1, cols2 = cols/2 + 1;
CV_Assert( cols2 == mat.cols );
if( mat.type() == CV_32FC2 )
{
for( i = 0; i < rows2; i++ )
{
Complexf* row = mat.ptr<Complexf>(i);
if( (flags & DFT_ROWS) || i == 0 || (i == rows2 - 1 && rows % 2 == 0) )
{
row[0].im = 0;
if( cols % 2 == 0 )
row[cols2-1].im = 0;
}
else
{
Complexf* row2 = mat.ptr<Complexf>(rows-i);
row2[0].re = row[0].re;
row2[0].im = -row[0].im;
if( cols % 2 == 0 )
{
row2[cols2-1].re = row[cols2-1].re;
row2[cols2-1].im = -row[cols2-1].im;
}
}
}
}
else if( mat.type() == CV_64FC2 )
{
for( i = 0; i < rows2; i++ )
{
Complexd* row = mat.ptr<Complexd>(i);
if( (flags & DFT_ROWS) || i == 0 || (i == rows2 - 1 && rows % 2 == 0) )
{
row[0].im = 0;
if( cols % 2 == 0 )
row[cols2-1].im = 0;
}
else
{
Complexd* row2 = mat.ptr<Complexd>(rows-i);
row2[0].re = row[0].re;
row2[0].im = -row[0].im;
if( cols % 2 == 0 )
{
row2[cols2-1].re = row[cols2-1].re;
row2[cols2-1].im = -row[cols2-1].im;
}
}
}
}
}
static void mulComplex( const Mat& src1, const Mat& src2, Mat& dst, int flags )
{
dst.create(src1.rows, src1.cols, src1.type());
int i, j, depth = src1.depth(), cols = src1.cols*2;
CV_Assert( src1.size == src2.size && src1.type() == src2.type() &&
(src1.type() == CV_32FC2 || src1.type() == CV_64FC2) );
for( i = 0; i < dst.rows; i++ )
{
if( depth == CV_32F )
{
const float* a = src1.ptr<float>(i);
const float* b = src2.ptr<float>(i);
float* c = dst.ptr<float>(i);
if( !(flags & CV_DXT_MUL_CONJ) )
for( j = 0; j < cols; j += 2 )
{
double re = (double)a[j]*b[j] - (double)a[j+1]*b[j+1];
double im = (double)a[j+1]*b[j] + (double)a[j]*b[j+1];
c[j] = (float)re;
c[j+1] = (float)im;
}
else
for( j = 0; j < cols; j += 2 )
{
double re = (double)a[j]*b[j] + (double)a[j+1]*b[j+1];
double im = (double)a[j+1]*b[j] - (double)a[j]*b[j+1];
c[j] = (float)re;
c[j+1] = (float)im;
}
}
else
{
const double* a = src1.ptr<double>(i);
const double* b = src2.ptr<double>(i);
double* c = dst.ptr<double>(i);
if( !(flags & CV_DXT_MUL_CONJ) )
for( j = 0; j < cols; j += 2 )
{
double re = a[j]*b[j] - a[j+1]*b[j+1];
double im = a[j+1]*b[j] + a[j]*b[j+1];
c[j] = re;
c[j+1] = im;
}
else
for( j = 0; j < cols; j += 2 )
{
double re = a[j]*b[j] + a[j+1]*b[j+1];
double im = a[j+1]*b[j] - a[j]*b[j+1];
c[j] = re;
c[j+1] = im;
}
}
}
}
}
class CxCore_DXTBaseTest : public cvtest::ArrayTest
{
public:
typedef cvtest::ArrayTest Base;
CxCore_DXTBaseTest( bool _allow_complex=false, bool _allow_odd=false,
bool _spectrum_mode=false );
protected:
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
int prepare_test_case( int test_case_idx );
double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
int flags; // transformation flags
bool allow_complex; // whether input/output may be complex or not:
// true for DFT and MulSpectrums, false for DCT
bool allow_odd; // whether input/output may be have odd (!=1) dimensions:
// true for DFT and MulSpectrums, false for DCT
bool spectrum_mode; // (2 complex/ccs inputs, 1 complex/ccs output):
// true for MulSpectrums, false for DFT and DCT
bool inplace; // inplace operation (set for each individual test case)
bool temp_dst; // use temporary destination (for real->ccs DFT and ccs MulSpectrums)
};
CxCore_DXTBaseTest::CxCore_DXTBaseTest( bool _allow_complex, bool _allow_odd, bool _spectrum_mode )
: Base(), flags(0), allow_complex(_allow_complex), allow_odd(_allow_odd),
spectrum_mode(_spectrum_mode), inplace(false), temp_dst(false)
{
test_array[INPUT].push_back(NULL);
if( spectrum_mode )
test_array[INPUT].push_back(NULL);
test_array[OUTPUT].push_back(NULL);
test_array[REF_OUTPUT].push_back(NULL);
test_array[TEMP].push_back(NULL);
test_array[TEMP].push_back(NULL);
max_log_array_size = 9;
element_wise_relative_error = spectrum_mode;
}
void CxCore_DXTBaseTest::get_test_array_types_and_sizes( int test_case_idx,
vector<vector<Size> >& sizes,
vector<vector<int> >& types )
{
RNG& rng = ts->get_rng();
int bits = cvtest::randInt(rng);
int depth = cvtest::randInt(rng)%2 + CV_32F;
int cn = !allow_complex || !(bits & 256) ? 1 : 2;
Size size;
Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
flags = bits & (CV_DXT_INVERSE | CV_DXT_SCALE | CV_DXT_ROWS | CV_DXT_MUL_CONJ);
if( spectrum_mode )
flags &= ~CV_DXT_INVERSE;
types[TEMP][0] = types[TEMP][1] = types[INPUT][0] =
types[OUTPUT][0] = CV_MAKETYPE(depth, cn);
size = sizes[INPUT][0];
temp_dst = false;
if( flags & CV_DXT_ROWS && (bits&1024) )
{
if( bits&16 )
size.width = 1;
else
size.height = 1;
flags &= ~CV_DXT_ROWS;
}
const int P2_MIN_SIZE = 32;
if( ((bits >> 10) & 1) == 0 )
{
size.width = (size.width / P2_MIN_SIZE)*P2_MIN_SIZE;
size.width = MAX(size.width, 1);
size.height = (size.height / P2_MIN_SIZE)*P2_MIN_SIZE;
size.height = MAX(size.height, 1);
}
if( !allow_odd )
{
if( size.width > 1 && (size.width&1) != 0 )
size.width = (size.width + 1) & -2;
if( size.height > 1 && (size.height&1) != 0 && !(flags & CV_DXT_ROWS) )
size.height = (size.height + 1) & -2;
}
sizes[INPUT][0] = sizes[OUTPUT][0] = size;
sizes[TEMP][0] = sizes[TEMP][1] = cvSize(0,0);
if( spectrum_mode )
{
if( cn == 1 )
{
types[OUTPUT][0] = depth + 8;
sizes[TEMP][0] = size;
}
sizes[INPUT][0] = sizes[INPUT][1] = size;
types[INPUT][1] = types[INPUT][0];
}
else if( /*(cn == 2 && (bits&32)) ||*/ (cn == 1 && allow_complex) )
{
types[TEMP][0] = depth + 8; // CV_??FC2
sizes[TEMP][0] = size;
size = cvSize(size.width/2+1, size.height);
if( flags & CV_DXT_INVERSE )
{
if( cn == 2 )
{
types[OUTPUT][0] = depth;
sizes[INPUT][0] = size;
}
types[TEMP][1] = types[TEMP][0];
sizes[TEMP][1] = sizes[TEMP][0];
}
else
{
if( allow_complex )
types[OUTPUT][0] = depth + 8;
if( cn == 2 )
{
types[INPUT][0] = depth;
types[TEMP][1] = types[TEMP][0];
sizes[TEMP][1] = size;
}
else
{
types[TEMP][1] = depth;
sizes[TEMP][1] = sizes[TEMP][0];
}
temp_dst = true;
}
}
inplace = false;
if( spectrum_mode ||
(!temp_dst && types[INPUT][0] == types[OUTPUT][0]) ||
(temp_dst && types[INPUT][0] == types[TEMP][1]) )
inplace = (bits & 64) != 0;
types[REF_OUTPUT][0] = types[OUTPUT][0];
sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
}
double CxCore_DXTBaseTest::get_success_error_level( int test_case_idx, int i, int j )
{
return Base::get_success_error_level( test_case_idx, i, j );
}
int CxCore_DXTBaseTest::prepare_test_case( int test_case_idx )
{
int code = Base::prepare_test_case( test_case_idx );
if( code > 0 )
{
int in_type = test_mat[INPUT][0].type();
int out_type = test_mat[OUTPUT][0].type();
if( CV_MAT_CN(in_type) == 2 && CV_MAT_CN(out_type) == 1 )
cvtest::fixCCS( test_mat[INPUT][0], test_mat[OUTPUT][0].cols, flags );
if( inplace )
cvtest::copy( test_mat[INPUT][test_case_idx & (int)spectrum_mode],
temp_dst ? test_mat[TEMP][1] :
in_type == out_type ? test_mat[OUTPUT][0] :
test_mat[TEMP][0] );
}
return code;
}
////////////////////// FFT ////////////////////////
class CxCore_DFTTest : public CxCore_DXTBaseTest
{
public:
CxCore_DFTTest();
protected:
void run_func();
void prepare_to_validation( int test_case_idx );
};
CxCore_DFTTest::CxCore_DFTTest() : CxCore_DXTBaseTest( true, true, false )
{
}
void CxCore_DFTTest::run_func()
{
Mat& dst = temp_dst ? test_mat[TEMP][1] : test_mat[OUTPUT][0];
const Mat& src = inplace ? dst : test_mat[INPUT][0];
if(!(flags & CV_DXT_INVERSE))
cv::dft( src, dst, flags );
else
cv::idft(src, dst, flags & ~CV_DXT_INVERSE);
}
void CxCore_DFTTest::prepare_to_validation( int /*test_case_idx*/ )
{
Mat& src = test_mat[INPUT][0];
Mat& dst = test_mat[REF_OUTPUT][0];
Mat* tmp_src = &src;
Mat* tmp_dst = &dst;
int src_cn = src.channels();
int dst_cn = dst.channels();
if( src_cn != 2 || dst_cn != 2 )
{
tmp_src = &test_mat[TEMP][0];
if( !(flags & CV_DXT_INVERSE ) )
{
Mat& cvdft_dst = test_mat[TEMP][1];
cvtest::convertFromCCS( cvdft_dst, cvdft_dst,
test_mat[OUTPUT][0], flags );
*tmp_src = Scalar::all(0);
cvtest::insert( src, *tmp_src, 0 );
}
else
{
cvtest::convertFromCCS( src, src, *tmp_src, flags );
tmp_dst = &test_mat[TEMP][1];
}
}
if( src.rows == 1 || (src.cols == 1 && !(flags & CV_DXT_ROWS)) )
cvtest::DFT_1D( *tmp_src, *tmp_dst, flags );
else
cvtest::DFT_2D( *tmp_src, *tmp_dst, flags );
if( tmp_dst != &dst )
cvtest::extract( *tmp_dst, dst, 0 );
}
////////////////////// DCT ////////////////////////
class CxCore_DCTTest : public CxCore_DXTBaseTest
{
public:
CxCore_DCTTest();
protected:
void run_func();
void prepare_to_validation( int test_case_idx );
};
CxCore_DCTTest::CxCore_DCTTest() : CxCore_DXTBaseTest( false, false, false )
{
}
void CxCore_DCTTest::run_func()
{
Mat& dst = test_mat[OUTPUT][0];
const Mat& src = inplace ? dst : test_mat[INPUT][0];
if(!(flags & CV_DXT_INVERSE))
cv::dct( src, dst, flags );
else
cv::idct( src, dst, flags & ~CV_DXT_INVERSE);
}
void CxCore_DCTTest::prepare_to_validation( int /*test_case_idx*/ )
{
const Mat& src = test_mat[INPUT][0];
Mat& dst = test_mat[REF_OUTPUT][0];
if( src.rows == 1 || (src.cols == 1 && !(flags & CV_DXT_ROWS)) )
cvtest::DCT_1D( src, dst, flags );
else
cvtest::DCT_2D( src, dst, flags );
}
////////////////////// MulSpectrums ////////////////////////
class CxCore_MulSpectrumsTest : public CxCore_DXTBaseTest
{
public:
CxCore_MulSpectrumsTest();
protected:
void run_func();
void prepare_to_validation( int test_case_idx );
};
CxCore_MulSpectrumsTest::CxCore_MulSpectrumsTest() : CxCore_DXTBaseTest( true, true, true )
{
}
void CxCore_MulSpectrumsTest::run_func()
{
Mat& dst = !test_mat[TEMP].empty() && !test_mat[TEMP][0].empty() ?
test_mat[TEMP][0] : test_mat[OUTPUT][0];
const Mat* src1 = &test_mat[INPUT][0], *src2 = &test_mat[INPUT][1];
if( inplace )
{
if( ts->get_current_test_info()->test_case_idx & 1 )
src2 = &dst;
else
src1 = &dst;
}
cv::mulSpectrums( *src1, *src2, dst, flags, (flags & CV_DXT_MUL_CONJ) != 0 );
}
void CxCore_MulSpectrumsTest::prepare_to_validation( int /*test_case_idx*/ )
{
Mat* src1 = &test_mat[INPUT][0];
Mat* src2 = &test_mat[INPUT][1];
Mat& dst = test_mat[OUTPUT][0];
Mat& dst0 = test_mat[REF_OUTPUT][0];
int cn = src1->channels();
if( cn == 1 )
{
cvtest::convertFromCCS( *src1, *src1, dst, flags );
cvtest::convertFromCCS( *src2, *src2, dst0, flags );
src1 = &dst;
src2 = &dst0;
}
cvtest::mulComplex( *src1, *src2, dst0, flags );
if( cn == 1 )
{
Mat& temp = test_mat[TEMP][0];
cvtest::convertFromCCS( temp, temp, dst, flags );
}
}
TEST(Core_DCT, accuracy) { CxCore_DCTTest test; test.safe_run(); }
TEST(Core_DFT, accuracy) { CxCore_DFTTest test; test.safe_run(); }
TEST(Core_MulSpectrums, accuracy) { CxCore_MulSpectrumsTest test; test.safe_run(); }

View File

@@ -0,0 +1,382 @@
#include "test_precomp.hpp"
using namespace cv;
using namespace std;
static SparseMat cvTsGetRandomSparseMat(int dims, const int* sz, int type,
int nzcount, double a, double b, RNG& rng)
{
SparseMat m(dims, sz, type);
int i, j;
CV_Assert(CV_MAT_CN(type) == 1);
for( i = 0; i < nzcount; i++ )
{
int idx[CV_MAX_DIM];
for( j = 0; j < dims; j++ )
idx[j] = cvtest::randInt(rng) % sz[j];
double val = cvtest::randReal(rng)*(b - a) + a;
uchar* ptr = m.ptr(idx, true, 0);
if( type == CV_8U )
*(uchar*)ptr = saturate_cast<uchar>(val);
else if( type == CV_8S )
*(schar*)ptr = saturate_cast<schar>(val);
else if( type == CV_16U )
*(ushort*)ptr = saturate_cast<ushort>(val);
else if( type == CV_16S )
*(short*)ptr = saturate_cast<short>(val);
else if( type == CV_32S )
*(int*)ptr = saturate_cast<int>(val);
else if( type == CV_32F )
*(float*)ptr = saturate_cast<float>(val);
else
*(double*)ptr = saturate_cast<double>(val);
}
return m;
}
static bool cvTsCheckSparse(const CvSparseMat* m1, const CvSparseMat* m2, double eps)
{
CvSparseMatIterator it1;
CvSparseNode* node1;
int depth = CV_MAT_DEPTH(m1->type);
if( m1->heap->active_count != m2->heap->active_count ||
m1->dims != m2->dims || CV_MAT_TYPE(m1->type) != CV_MAT_TYPE(m2->type) )
return false;
for( node1 = cvInitSparseMatIterator( m1, &it1 );
node1 != 0; node1 = cvGetNextSparseNode( &it1 ))
{
uchar* v1 = (uchar*)CV_NODE_VAL(m1,node1);
uchar* v2 = cvPtrND( m2, CV_NODE_IDX(m1,node1), 0, 0, &node1->hashval );
if( !v2 )
return false;
if( depth == CV_8U || depth == CV_8S )
{
if( *v1 != *v2 )
return false;
}
else if( depth == CV_16U || depth == CV_16S )
{
if( *(ushort*)v1 != *(ushort*)v2 )
return false;
}
else if( depth == CV_32S )
{
if( *(int*)v1 != *(int*)v2 )
return false;
}
else if( depth == CV_32F )
{
if( fabs(*(float*)v1 - *(float*)v2) > eps*(fabs(*(float*)v2) + 1) )
return false;
}
else if( fabs(*(double*)v1 - *(double*)v2) > eps*(fabs(*(double*)v2) + 1) )
return false;
}
return true;
}
class Core_IOTest : public cvtest::BaseTest
{
public:
Core_IOTest() {};
protected:
void run(int)
{
double ranges[][2] = {{0, 256}, {-128, 128}, {0, 65536}, {-32768, 32768},
{-1000000, 1000000}, {-10, 10}, {-10, 10}};
RNG& rng = ts->get_rng();
RNG rng0;
test_case_count = 2;
int progress = 0;
MemStorage storage(cvCreateMemStorage(0));
for( int idx = 0; idx < test_case_count; idx++ )
{
ts->update_context( this, idx, false );
progress = update_progress( progress, idx, test_case_count, 0 );
cvClearMemStorage(storage);
char buf[L_tmpnam+16];
char* filename = tmpnam(buf);
strcat(filename, idx % 2 ? ".yml" : ".xml");
if(filename[0] == '\\')
filename++;
FileStorage fs(filename, FileStorage::WRITE);
int test_int = (int)cvtest::randInt(rng);
double test_real = (cvtest::randInt(rng)%2?1:-1)*exp(cvtest::randReal(rng)*18-9);
string test_string = "vw wv23424rt\"&amp;&lt;&gt;&amp;&apos;@#$@$%$%&%IJUKYILFD@#$@%$&*&() ";
int depth = cvtest::randInt(rng) % (CV_64F+1);
int cn = cvtest::randInt(rng) % 4 + 1;
Mat test_mat(cvtest::randInt(rng)%30+1, cvtest::randInt(rng)%30+1, CV_MAKETYPE(depth, cn));
rng0.fill(test_mat, CV_RAND_UNI, Scalar::all(ranges[depth][0]), Scalar::all(ranges[depth][1]));
if( depth >= CV_32F )
{
exp(test_mat, test_mat);
Mat test_mat_scale(test_mat.size(), test_mat.type());
rng0.fill(test_mat_scale, CV_RAND_UNI, Scalar::all(-1), Scalar::all(1));
multiply(test_mat, test_mat_scale, test_mat);
}
CvSeq* seq = cvCreateSeq(test_mat.type(), (int)sizeof(CvSeq),
(int)test_mat.elemSize(), storage);
cvSeqPushMulti(seq, test_mat.data, test_mat.cols*test_mat.rows);
CvGraph* graph = cvCreateGraph( CV_ORIENTED_GRAPH,
sizeof(CvGraph), sizeof(CvGraphVtx),
sizeof(CvGraphEdge), storage );
int edges[][2] = {{0,1},{1,2},{2,0},{0,3},{3,4},{4,1}};
int i, vcount = 5, ecount = 6;
for( i = 0; i < vcount; i++ )
cvGraphAddVtx(graph);
for( i = 0; i < ecount; i++ )
{
CvGraphEdge* edge;
cvGraphAddEdge(graph, edges[i][0], edges[i][1], 0, &edge);
edge->weight = (float)(i+1);
}
depth = cvtest::randInt(rng) % (CV_64F+1);
cn = cvtest::randInt(rng) % 4 + 1;
int sz[] = {cvtest::randInt(rng)%10+1, cvtest::randInt(rng)%10+1, cvtest::randInt(rng)%10+1};
MatND test_mat_nd(3, sz, CV_MAKETYPE(depth, cn));
rng0.fill(test_mat_nd, CV_RAND_UNI, Scalar::all(ranges[depth][0]), Scalar::all(ranges[depth][1]));
if( depth >= CV_32F )
{
exp(test_mat_nd, test_mat_nd);
MatND test_mat_scale(test_mat_nd.dims, test_mat_nd.size, test_mat_nd.type());
rng0.fill(test_mat_scale, CV_RAND_UNI, Scalar::all(-1), Scalar::all(1));
multiply(test_mat_nd, test_mat_scale, test_mat_nd);
}
int ssz[] = {cvtest::randInt(rng)%10+1, cvtest::randInt(rng)%10+1,
cvtest::randInt(rng)%10+1,cvtest::randInt(rng)%10+1};
SparseMat test_sparse_mat = cvTsGetRandomSparseMat(4, ssz, cvtest::randInt(rng)%(CV_64F+1),
cvtest::randInt(rng) % 10000, 0, 100, rng);
fs << "test_int" << test_int << "test_real" << test_real << "test_string" << test_string;
fs << "test_mat" << test_mat;
fs << "test_mat_nd" << test_mat_nd;
fs << "test_sparse_mat" << test_sparse_mat;
fs << "test_list" << "[" << 0.0000000000001 << 2 << CV_PI << -3435345 << "2-502 2-029 3egegeg" <<
"{:" << "month" << 12 << "day" << 31 << "year" << 1969 << "}" << "]";
fs << "test_map" << "{" << "x" << 1 << "y" << 2 << "width" << 100 << "height" << 200 << "lbp" << "[:";
const uchar arr[] = {0, 1, 1, 0, 1, 1, 0, 1};
fs.writeRaw("u", arr, (int)(sizeof(arr)/sizeof(arr[0])));
fs << "]" << "}";
cvWriteComment(*fs, "test comment", 0);
fs.writeObj("test_seq", seq);
fs.writeObj("test_graph",graph);
CvGraph* graph2 = (CvGraph*)cvClone(graph);
fs.release();
if(!fs.open(filename, FileStorage::READ))
{
ts->printf( cvtest::TS::LOG, "filename %s can not be read\n", filename );
ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
return;
}
int real_int = (int)fs["test_int"];
double real_real = (double)fs["test_real"];
string real_string = (string)fs["test_string"];
if( real_int != test_int ||
fabs(real_real - test_real) > DBL_EPSILON*(fabs(test_real)+1) ||
real_string != test_string )
{
ts->printf( cvtest::TS::LOG, "the read scalars are not correct\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
CvMat* m = (CvMat*)fs["test_mat"].readObj();
CvMat _test_mat = test_mat;
double max_diff = 0;
CvMat stub1, _test_stub1;
cvReshape(m, &stub1, 1, 0);
cvReshape(&_test_mat, &_test_stub1, 1, 0);
vector<int> pt;
if( !m || !CV_IS_MAT(m) || m->rows != test_mat.rows || m->cols != test_mat.cols ||
cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 )
{
ts->printf( cvtest::TS::LOG, "the read matrix is not correct: (%.20g vs %.20g) at (%d,%d)\n",
cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[0], pt[1]),
pt[0], pt[1] );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
if( m && CV_IS_MAT(m))
cvReleaseMat(&m);
CvMatND* m_nd = (CvMatND*)fs["test_mat_nd"].readObj();
CvMatND _test_mat_nd = test_mat_nd;
if( !m_nd || !CV_IS_MATND(m_nd) )
{
ts->printf( cvtest::TS::LOG, "the read nd-matrix is not correct\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
CvMat stub, _test_stub;
cvGetMat(m_nd, &stub, 0, 1);
cvGetMat(&_test_mat_nd, &_test_stub, 0, 1);
cvReshape(&stub, &stub1, 1, 0);
cvReshape(&_test_stub, &_test_stub1, 1, 0);
if( !CV_ARE_TYPES_EQ(&stub, &_test_stub) ||
!CV_ARE_SIZES_EQ(&stub, &_test_stub) ||
//cvNorm(&stub, &_test_stub, CV_L2) != 0 )
cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 )
{
ts->printf( cvtest::TS::LOG, "readObj method: the read nd matrix is not correct: (%.20g vs %.20g) vs at (%d,%d)\n",
cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[0], pt[1]),
pt[0], pt[1] );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
MatND mat_nd2;
fs["test_mat_nd"] >> mat_nd2;
CvMatND m_nd2 = mat_nd2;
cvGetMat(&m_nd2, &stub, 0, 1);
cvReshape(&stub, &stub1, 1, 0);
if( !CV_ARE_TYPES_EQ(&stub, &_test_stub) ||
!CV_ARE_SIZES_EQ(&stub, &_test_stub) ||
//cvNorm(&stub, &_test_stub, CV_L2) != 0 )
cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 )
{
ts->printf( cvtest::TS::LOG, "C++ method: the read nd matrix is not correct: (%.20g vs %.20g) vs at (%d,%d)\n",
cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[1], pt[0]),
pt[0], pt[1] );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
cvRelease((void**)&m_nd);
Ptr<CvSparseMat> m_s = (CvSparseMat*)fs["test_sparse_mat"].readObj();
Ptr<CvSparseMat> _test_sparse_ = (CvSparseMat*)test_sparse_mat;
Ptr<CvSparseMat> _test_sparse = (CvSparseMat*)cvClone(_test_sparse_);
SparseMat m_s2;
fs["test_sparse_mat"] >> m_s2;
Ptr<CvSparseMat> _m_s2 = (CvSparseMat*)m_s2;
if( !m_s || !CV_IS_SPARSE_MAT(m_s) ||
!cvTsCheckSparse(m_s, _test_sparse,0) ||
!cvTsCheckSparse(_m_s2, _test_sparse,0))
{
ts->printf( cvtest::TS::LOG, "the read sparse matrix is not correct\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
FileNode tl = fs["test_list"];
if( tl.type() != FileNode::SEQ || tl.size() != 6 ||
fabs((double)tl[0] - 0.0000000000001) >= DBL_EPSILON ||
(int)tl[1] != 2 ||
fabs((double)tl[2] - CV_PI) >= DBL_EPSILON ||
(int)tl[3] != -3435345 ||
(string)tl[4] != "2-502 2-029 3egegeg" ||
tl[5].type() != FileNode::MAP || tl[5].size() != 3 ||
(int)tl[5]["month"] != 12 ||
(int)tl[5]["day"] != 31 ||
(int)tl[5]["year"] != 1969 )
{
ts->printf( cvtest::TS::LOG, "the test list is incorrect\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
FileNode tm = fs["test_map"];
FileNode tm_lbp = tm["lbp"];
int real_x = (int)tm["x"];
int real_y = (int)tm["y"];
int real_width = (int)tm["width"];
int real_height = (int)tm["height"];
int real_lbp_val = 0;
FileNodeIterator it;
it = tm_lbp.begin();
real_lbp_val |= (int)*it << 0;
++it;
real_lbp_val |= (int)*it << 1;
it++;
real_lbp_val |= (int)*it << 2;
it += 1;
real_lbp_val |= (int)*it << 3;
FileNodeIterator it2(it);
it2 += 4;
real_lbp_val |= (int)*it2 << 7;
--it2;
real_lbp_val |= (int)*it2 << 6;
it2--;
real_lbp_val |= (int)*it2 << 5;
it2 -= 1;
real_lbp_val |= (int)*it2 << 4;
it2 += -1;
CV_Assert( it == it2 );
if( tm.type() != FileNode::MAP || tm.size() != 5 ||
real_x != 1 ||
real_y != 2 ||
real_width != 100 ||
real_height != 200 ||
tm_lbp.type() != FileNode::SEQ ||
tm_lbp.size() != 8 ||
real_lbp_val != 0xb6 )
{
ts->printf( cvtest::TS::LOG, "the test map is incorrect\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
CvGraph* graph3 = (CvGraph*)fs["test_graph"].readObj();
if(graph2->active_count != vcount || graph3->active_count != vcount ||
graph2->edges->active_count != ecount || graph3->edges->active_count != ecount)
{
ts->printf( cvtest::TS::LOG, "the cloned or read graph have wrong number of vertices or edges\n" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
for( i = 0; i < ecount; i++ )
{
CvGraphEdge* edge2 = cvFindGraphEdge(graph2, edges[i][0], edges[i][1]);
CvGraphEdge* edge3 = cvFindGraphEdge(graph3, edges[i][0], edges[i][1]);
if( !edge2 || edge2->weight != (float)(i+1) ||
!edge3 || edge3->weight != (float)(i+1) )
{
ts->printf( cvtest::TS::LOG, "the cloned or read graph do not have the edge (%d, %d)\n", edges[i][0], edges[i][1] );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
}
fs.release();
remove(filename);
}
}
};
TEST(Core_InputOutput, write_read_consistency) { Core_IOTest test; test.safe_run(); }

View File

@@ -1,2 +1,3 @@
#include "test_precomp.hpp"
#include "opencv2/gtest/gtest_main.hpp"
CV_TEST_MAIN("cv")

View File

@@ -0,0 +1,811 @@
#include "test_precomp.hpp"
using namespace cv;
using namespace std;
class Core_ReduceTest : public cvtest::BaseTest
{
public:
Core_ReduceTest() {};
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 Core_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 cvtest::TS::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( 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;
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 != cvtest::TS::OK ? tempCode : code;
// 2. avg
tempCode = checkOp( src, dstType, CV_REDUCE_AVG, avg, dim,
dstType == CV_32SC1 ? 0.6 : 0.00007 );
code = tempCode != cvtest::TS::OK ? tempCode : code;
// 3. max
tempCode = checkOp( src, dstType, CV_REDUCE_MAX, max, dim, FLT_EPSILON );
code = tempCode != cvtest::TS::OK ? tempCode : code;
// 4. min
tempCode = checkOp( src, dstType, CV_REDUCE_MIN, min, dim, FLT_EPSILON );
code = tempCode != cvtest::TS::OK ? tempCode : code;
return code;
}
int Core_ReduceTest::checkDim( int dim, Size sz )
{
int code = cvtest::TS::OK, tempCode;
// CV_8UC1
tempCode = checkCase( CV_8UC1, CV_8UC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkCase( CV_8UC1, CV_32SC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkCase( CV_8UC1, CV_32FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkCase( CV_8UC1, CV_64FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
// CV_16UC1
tempCode = checkCase( CV_16UC1, CV_32FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkCase( CV_16UC1, CV_64FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
// CV_16SC1
tempCode = checkCase( CV_16SC1, CV_32FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkCase( CV_16SC1, CV_64FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
// CV_32FC1
tempCode = checkCase( CV_32FC1, CV_32FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkCase( CV_32FC1, CV_64FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
// CV_64FC1
tempCode = checkCase( CV_64FC1, CV_64FC1, dim, sz );
code = tempCode != cvtest::TS::OK ? tempCode : code;
return code;
}
int Core_ReduceTest::checkSize( Size sz )
{
int code = cvtest::TS::OK, tempCode;
tempCode = checkDim( 0, sz ); // rows
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkDim( 1, sz ); // cols
code = tempCode != cvtest::TS::OK ? tempCode : code;
return code;
}
void Core_ReduceTest::run( int )
{
int code = cvtest::TS::OK, tempCode;
tempCode = checkSize( Size(1,1) );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkSize( Size(1,100) );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkSize( Size(100,1) );
code = tempCode != cvtest::TS::OK ? tempCode : code;
tempCode = checkSize( Size(1000,500) );
code = tempCode != cvtest::TS::OK ? tempCode : code;
ts->set_failed_test_info( code );
}
#define CHECK_C
Size sz(200, 500);
class Core_PCATest : public cvtest::BaseTest
{
public:
Core_PCATest() {}
protected:
void run(int)
{
int code = cvtest::TS::OK;
double diffPrjEps, diffBackPrjEps,
prjEps, backPrjEps,
evalEps, evecEps;
int maxComponents = 100;
Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1);
RNG& rng = ts->get_rng();
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) );
PCA rPCA( rPoints, Mat(), CV_PCA_DATA_AS_ROW, maxComponents ), cPCA;
// 1. check C++ PCA & ROW
Mat rPrjTestPoints = rPCA.project( rTestPoints );
Mat rBackPrjTestPoints = rPCA.backProject( rPrjTestPoints );
Mat avg(1, sz.width, CV_32FC1 );
reduce( rPoints, avg, 0, CV_REDUCE_AVG );
Mat Q = rPoints - repeat( avg, rPoints.rows, 1 ), Qt = Q.t(), eval, evec;
Q = Qt * Q;
Q = Q /(float)rPoints.rows;
eigen( Q, eval, evec );
/*SVD svd(Q);
evec = svd.vt;
eval = svd.w;*/
Mat subEval( maxComponents, 1, eval.type(), eval.data ),
subEvec( maxComponents, evec.cols, evec.type(), evec.data );
#ifdef CHECK_C
Mat prjTestPoints, backPrjTestPoints, cPoints = rPoints.t(), cTestPoints = rTestPoints.t();
CvMat _points, _testPoints, _avg, _eval, _evec, _prjTestPoints, _backPrjTestPoints;
#endif
// 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;
Mat lv = eval.at<float>(i,0) * v;
err = norm( Qv, lv );
if( err > eigenEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of eigen(); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
}
// check pca eigenvalues
evalEps = 1e-6, evecEps = 1;
err = norm( rPCA.eigenvalues, subEval );
if( err > evalEps )
{
ts->printf( cvtest::TS::LOG, "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
// check pca eigenvectors
err = norm( rPCA.eigenvectors, subEvec, CV_RELATIVE_L2 );
if( err > evecEps )
{
ts->printf( cvtest::TS::LOG, "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
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;
err = norm(rPrjTestPoints.row(i), prj, CV_RELATIVE_L2);
if( err > prjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
// check pca backProject
Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg;
err = norm( rBackPrjTestPoints.row(i), backPrj, CV_RELATIVE_L2 );
if( err > backPrjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
}
// 2. check C++ PCA & COL
cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents );
diffPrjEps = 1, diffBackPrjEps = 1;
err = norm(cPCA.project(rTestPoints.t()), rPrjTestPoints.t(), CV_RELATIVE_L2 );
if( err > diffPrjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
err = norm(cPCA.backProject(rPrjTestPoints.t()), rBackPrjTestPoints.t(), CV_RELATIVE_L2 );
if( err > diffBackPrjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
#ifdef CHECK_C
// 3. check C PCA & ROW
_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;
cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_ROW );
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
err = norm(prjTestPoints, rPrjTestPoints, CV_RELATIVE_L2);
if( err > diffPrjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
err = norm(backPrjTestPoints, rBackPrjTestPoints, CV_RELATIVE_L2);
if( err > diffBackPrjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
// 3. check C PCA & COL
_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;
cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_COL );
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
err = norm(prjTestPoints, rPrjTestPoints.t(), CV_RELATIVE_L2 );
if( err > diffPrjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
err = norm(backPrjTestPoints, rBackPrjTestPoints.t(), CV_RELATIVE_L2);
if( err > diffBackPrjEps )
{
ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto exit_func;
}
#endif
exit_func:
RNG& _rng = ts->get_rng();
_rng = rng;
ts->set_failed_test_info( code );
}
};
class Core_ArrayOpTest : public cvtest::BaseTest
{
public:
Core_ArrayOpTest();
~Core_ArrayOpTest();
protected:
void run(int);
};
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;
}
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;
}
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;
}
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, "");
}
void Core_ArrayOpTest::run( int /* start_from */)
{
int errcount = 0;
// 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));
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);
Ptr<CvMatND> matC = cvCloneMatND(&matB);
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 ||
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++;
}
}
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;
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;
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);
}
minMaxLoc(_all_vals, &min_val, &max_val);
double _norm0 = norm(_all_vals, CV_C);
double _norm1 = norm(_all_vals, CV_L1);
double _norm2 = norm(_all_vals, CV_L2);
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;
}
}
Ptr<CvSparseMat> M2 = (CvSparseMat*)M;
MatND Md;
M.copyTo(Md);
SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2);
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;
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;
}
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;
}
int n = (unsigned)rng % max(p/5,10);
n = min(max(n, 1), p) + nz0;
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);
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;
}
}
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;
}
}
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;
}
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;
}
minMaxLoc(Md, &val1, &val2, idx1, idx2);
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;
}
}
ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT);
}
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(); }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,829 @@
/*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.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., 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 the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#include <limits>
#include <numeric>
using namespace cv;
using namespace std;
class CV_OperationsTest : public cvtest::BaseTest
{
public:
CV_OperationsTest();
~CV_OperationsTest();
protected:
void run(int);
struct test_excep
{
test_excep(const string& _s=string("")) : s(_s) {};
string s;
};
bool SomeMatFunctions();
bool TestMat();
bool TestTemplateMat();
bool TestMatND();
bool TestSparseMat();
bool operations1();
void checkDiff(const Mat& m1, const Mat& m2, const string& s) { if (norm(m1, m2, NORM_INF) != 0) throw test_excep(s); }
void checkDiffF(const Mat& m1, const Mat& m2, const string& s) { if (norm(m1, m2, NORM_INF) > 1e-5) throw test_excep(s); }
};
CV_OperationsTest::CV_OperationsTest()
{
}
CV_OperationsTest::~CV_OperationsTest() {}
#define STR(a) STR2(a)
#define STR2(a) #a
#define CHECK_DIFF(a, b) checkDiff(a, b, "(" #a ") != (" #b ") at l." STR(__LINE__))
#define CHECK_DIFF_FLT(a, b) checkDiffF(a, b, "(" #a ") !=(eps) (" #b ") at l." STR(__LINE__))
#if defined _MSC_VER && _MSC_VER < 1400
#define MSVC_OLD 1
#else
#define MSVC_OLD 0
#endif
bool CV_OperationsTest::TestMat()
{
try
{
Mat one_3x1(3, 1, CV_32F, Scalar(1.0));
Mat shi_3x1(3, 1, CV_32F, Scalar(1.2));
Mat shi_2x1(2, 1, CV_32F, Scalar(-1));
Scalar shift = Scalar::all(15);
float data[] = { sqrt(2.f)/2, -sqrt(2.f)/2, 1.f, sqrt(2.f)/2, sqrt(2.f)/2, 10.f };
Mat rot_2x3(2, 3, CV_32F, data);
Mat res = one_3x1 + shi_3x1 + shi_3x1 + shi_3x1;
res = Mat(Mat(2 * rot_2x3) * res - shi_2x1) + shift;
Mat tmp, res2;
add(one_3x1, shi_3x1, tmp);
add(tmp, shi_3x1, tmp);
add(tmp, shi_3x1, tmp);
gemm(rot_2x3, tmp, 2, shi_2x1, -1, res2, 0);
add(res2, Mat(2, 1, CV_32F, shift), res2);
CHECK_DIFF(res, res2);
Mat mat4x4(4, 4, CV_32F);
randu(mat4x4, Scalar(0), Scalar(10));
Mat roi1 = mat4x4(Rect(Point(1, 1), Size(2, 2)));
Mat roi2 = mat4x4(Range(1, 3), Range(1, 3));
CHECK_DIFF(roi1, roi2);
CHECK_DIFF(mat4x4, mat4x4(Rect(Point(0,0), mat4x4.size())));
Mat intMat10(3, 3, CV_32S, Scalar(10));
Mat intMat11(3, 3, CV_32S, Scalar(11));
Mat resMat(3, 3, CV_8U, Scalar(255));
CHECK_DIFF(resMat, intMat10 == intMat10);
CHECK_DIFF(resMat, intMat10 < intMat11);
CHECK_DIFF(resMat, intMat11 > intMat10);
CHECK_DIFF(resMat, intMat10 <= intMat11);
CHECK_DIFF(resMat, intMat11 >= intMat10);
CHECK_DIFF(resMat, intMat11 != intMat10);
CHECK_DIFF(resMat, intMat10 == 10.0);
CHECK_DIFF(resMat, 10.0 == intMat10);
CHECK_DIFF(resMat, intMat10 < 11.0);
CHECK_DIFF(resMat, 11.0 > intMat10);
CHECK_DIFF(resMat, 10.0 < intMat11);
CHECK_DIFF(resMat, 11.0 >= intMat10);
CHECK_DIFF(resMat, 10.0 <= intMat11);
CHECK_DIFF(resMat, 10.0 != intMat11);
CHECK_DIFF(resMat, intMat11 != 10.0);
Mat eye = Mat::eye(3, 3, CV_16S);
Mat maskMat4(3, 3, CV_16S, Scalar(4));
Mat maskMat1(3, 3, CV_16S, Scalar(1));
Mat maskMat5(3, 3, CV_16S, Scalar(5));
Mat maskMat0(3, 3, CV_16S, Scalar(0));
CHECK_DIFF(maskMat0, maskMat4 & maskMat1);
CHECK_DIFF(maskMat0, Scalar(1) & maskMat4);
CHECK_DIFF(maskMat0, maskMat4 & Scalar(1));
Mat m;
m = maskMat4.clone(); m &= maskMat1; CHECK_DIFF(maskMat0, m);
m = maskMat4.clone(); m &= maskMat1 | maskMat1; CHECK_DIFF(maskMat0, m);
m = maskMat4.clone(); m &= (2* maskMat1 - maskMat1); CHECK_DIFF(maskMat0, m);
m = maskMat4.clone(); m &= Scalar(1); CHECK_DIFF(maskMat0, m);
m = maskMat4.clone(); m |= maskMat1; CHECK_DIFF(maskMat5, m);
m = maskMat5.clone(); m ^= maskMat1; CHECK_DIFF(maskMat4, m);
m = maskMat4.clone(); m |= (2* maskMat1 - maskMat1); CHECK_DIFF(maskMat5, m);
m = maskMat5.clone(); m ^= (2* maskMat1 - maskMat1); CHECK_DIFF(maskMat4, m);
m = maskMat4.clone(); m |= Scalar(1); CHECK_DIFF(maskMat5, m);
m = maskMat5.clone(); m ^= Scalar(1); CHECK_DIFF(maskMat4, m);
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & (maskMat1 | maskMat1));
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & maskMat1);
CHECK_DIFF(maskMat0, maskMat4 & (maskMat1 | maskMat1));
CHECK_DIFF(maskMat0, (maskMat1 | maskMat1) & Scalar(4));
CHECK_DIFF(maskMat0, Scalar(4) & (maskMat1 | maskMat1));
CHECK_DIFF(maskMat0, maskMat5 ^ (maskMat4 | maskMat1));
CHECK_DIFF(maskMat0, (maskMat4 | maskMat1) ^ maskMat5);
CHECK_DIFF(maskMat0, (maskMat4 + maskMat1) ^ (maskMat4 + maskMat1));
CHECK_DIFF(maskMat0, Scalar(5) ^ (maskMat4 | Scalar(1)));
CHECK_DIFF(maskMat1, Scalar(5) ^ maskMat4);
CHECK_DIFF(maskMat0, Scalar(5) ^ (maskMat4 + maskMat1));
CHECK_DIFF(maskMat5, Scalar(5) | (maskMat4 + maskMat1));
CHECK_DIFF(maskMat0, (maskMat4 + maskMat1) ^ Scalar(5));
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ maskMat1));
CHECK_DIFF(maskMat5, (maskMat4 ^ maskMat1) | maskMat5);
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ Scalar(1)));
CHECK_DIFF(maskMat5, (maskMat4 | maskMat4) | Scalar(1));
CHECK_DIFF(maskMat5, Scalar(1) | (maskMat4 | maskMat4));
CHECK_DIFF(maskMat5, Scalar(1) | maskMat4);
CHECK_DIFF(maskMat5, (maskMat5 | maskMat5) | (maskMat4 ^ maskMat1));
CHECK_DIFF(maskMat1, min(maskMat1, maskMat5));
CHECK_DIFF(maskMat1, min(Mat(maskMat1 | maskMat1), maskMat5 | maskMat5));
CHECK_DIFF(maskMat5, max(maskMat1, maskMat5));
CHECK_DIFF(maskMat5, max(Mat(maskMat1 | maskMat1), maskMat5 | maskMat5));
CHECK_DIFF(maskMat1, min(maskMat1, maskMat5 | maskMat5));
CHECK_DIFF(maskMat1, min(maskMat1 | maskMat1, maskMat5));
CHECK_DIFF(maskMat5, max(maskMat1 | maskMat1, maskMat5));
CHECK_DIFF(maskMat5, max(maskMat1, maskMat5 | maskMat5));
CHECK_DIFF(~maskMat1, maskMat1 ^ -1);
CHECK_DIFF(~(maskMat1 | maskMat1), maskMat1 ^ -1);
CHECK_DIFF(maskMat1, maskMat4/4.0);
/////////////////////////////
CHECK_DIFF(1.0 - (maskMat5 | maskMat5), -maskMat4);
CHECK_DIFF((maskMat4 | maskMat4) * 1.0 + 1.0, maskMat5);
CHECK_DIFF(1.0 + (maskMat4 | maskMat4) * 1.0, maskMat5);
CHECK_DIFF((maskMat5 | maskMat5) * 1.0 - 1.0, maskMat4);
CHECK_DIFF(5.0 - (maskMat4 | maskMat4) * 1.0, maskMat1);
CHECK_DIFF((maskMat4 | maskMat4) * 1.0 + 0.5 + 0.5, maskMat5);
CHECK_DIFF(0.5 + ((maskMat4 | maskMat4) * 1.0 + 0.5), maskMat5);
CHECK_DIFF(((maskMat4 | maskMat4) * 1.0 + 2.0) - 1.0, maskMat5);
CHECK_DIFF(5.0 - ((maskMat1 | maskMat1) * 1.0 + 3.0), maskMat1);
CHECK_DIFF( ( (maskMat1 | maskMat1) * 2.0 + 2.0) * 1.25, maskMat5);
CHECK_DIFF( 1.25 * ( (maskMat1 | maskMat1) * 2.0 + 2.0), maskMat5);
CHECK_DIFF( -( (maskMat1 | maskMat1) * (-2.0) + 1.0), maskMat1);
CHECK_DIFF( maskMat1 * 1.0 + maskMat4 * 0.5 + 2.0, maskMat5);
CHECK_DIFF( 1.0 + (maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0), maskMat5);
CHECK_DIFF( (maskMat1 * 1.0 + maskMat4 * 0.5 + 2.0) - 1.0, maskMat4);
CHECK_DIFF(5.0 - (maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0), maskMat1);
CHECK_DIFF((maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0)*1.25, maskMat5);
CHECK_DIFF(1.25 * (maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0), maskMat5);
CHECK_DIFF(-(maskMat1 * 2.0 + maskMat4 * (-1) + 1.0), maskMat1);
CHECK_DIFF((maskMat1 * 1.0 + maskMat4), maskMat5);
CHECK_DIFF((maskMat4 + maskMat1 * 1.0), maskMat5);
CHECK_DIFF((maskMat1 * 3.0 + 1.0) + maskMat1, maskMat5);
CHECK_DIFF(maskMat1 + (maskMat1 * 3.0 + 1.0), maskMat5);
CHECK_DIFF(maskMat1*4.0 + (maskMat1 | maskMat1), maskMat5);
CHECK_DIFF((maskMat1 | maskMat1) + maskMat1*4.0, maskMat5);
CHECK_DIFF((maskMat1*3.0 + 1.0) + (maskMat1 | maskMat1), maskMat5);
CHECK_DIFF((maskMat1 | maskMat1) + (maskMat1*3.0 + 1.0), maskMat5);
CHECK_DIFF(maskMat1*4.0 + maskMat4*2.0, maskMat1 * 12);
CHECK_DIFF((maskMat1*3.0 + 1.0) + maskMat4*2.0, maskMat1 * 12);
CHECK_DIFF(maskMat4*2.0 + (maskMat1*3.0 + 1.0), maskMat1 * 12);
CHECK_DIFF((maskMat1*3.0 + 1.0) + (maskMat1*2.0 + 2.0), maskMat1 * 8);
CHECK_DIFF(maskMat5*1.0 - maskMat4, maskMat1);
CHECK_DIFF(maskMat5 - maskMat1 * 4.0, maskMat1);
CHECK_DIFF((maskMat4 * 1.0 + 4.0)- maskMat4, maskMat4);
CHECK_DIFF(maskMat5 - (maskMat1 * 2.0 + 2.0), maskMat1);
CHECK_DIFF(maskMat5*1.0 - (maskMat4 | maskMat4), maskMat1);
CHECK_DIFF((maskMat5 | maskMat5) - maskMat1 * 4.0, maskMat1);
CHECK_DIFF((maskMat4 * 1.0 + 4.0)- (maskMat4 | maskMat4), maskMat4);
CHECK_DIFF((maskMat5 | maskMat5) - (maskMat1 * 2.0 + 2.0), maskMat1);
CHECK_DIFF(maskMat1*5.0 - maskMat4 * 1.0, maskMat1);
CHECK_DIFF((maskMat1*5.0 + 3.0)- maskMat4 * 1.0, maskMat4);
CHECK_DIFF(maskMat4 * 2.0 - (maskMat1*4.0 + 3.0), maskMat1);
CHECK_DIFF((maskMat1 * 2.0 + 3.0) - (maskMat1*3.0 + 1.0), maskMat1);
CHECK_DIFF((maskMat5 - maskMat4)* 4.0, maskMat4);
CHECK_DIFF(4.0 * (maskMat5 - maskMat4), maskMat4);
CHECK_DIFF(-((maskMat4 | maskMat4) - (maskMat5 | maskMat5)), maskMat1);
CHECK_DIFF(4.0 * (maskMat1 | maskMat1), maskMat4);
CHECK_DIFF((maskMat4 | maskMat4)/4.0, maskMat1);
#if !MSVC_OLD
CHECK_DIFF(2.0 * (maskMat1 * 2.0) , maskMat4);
#endif
CHECK_DIFF((maskMat4 / 2.0) / 2.0 , maskMat1);
CHECK_DIFF(-(maskMat4 - maskMat5) , maskMat1);
CHECK_DIFF(-((maskMat4 - maskMat5) * 1.0), maskMat1);
/////////////////////////////
CHECK_DIFF(maskMat4 / maskMat4, maskMat1);
///// Element-wise multiplication
CHECK_DIFF(maskMat4.mul(maskMat4, 0.25), maskMat4);
CHECK_DIFF(maskMat4.mul(maskMat1 * 4, 0.25), maskMat4);
CHECK_DIFF(maskMat4.mul(maskMat4 / 4), maskMat4);
CHECK_DIFF(maskMat4.mul(maskMat4 / 4), maskMat4);
CHECK_DIFF(maskMat4.mul(maskMat4) * 0.25, maskMat4);
CHECK_DIFF(0.25 * maskMat4.mul(maskMat4), maskMat4);
////// Element-wise division
CHECK_DIFF(maskMat4 / maskMat4, maskMat1);
CHECK_DIFF((maskMat4 & maskMat4) / (maskMat1 * 4), maskMat1);
CHECK_DIFF((maskMat4 & maskMat4) / maskMat4, maskMat1);
CHECK_DIFF(maskMat4 / (maskMat4 & maskMat4), maskMat1);
CHECK_DIFF((maskMat1 * 4) / maskMat4, maskMat1);
CHECK_DIFF(maskMat4 / (maskMat1 * 4), maskMat1);
CHECK_DIFF((maskMat4 * 0.5 )/ (maskMat1 * 2), maskMat1);
CHECK_DIFF(maskMat4 / maskMat4.mul(maskMat1), maskMat1);
CHECK_DIFF((maskMat4 & maskMat4) / maskMat4.mul(maskMat1), maskMat1);
CHECK_DIFF(4.0 / maskMat4, maskMat1);
CHECK_DIFF(4.0 / (maskMat4 | maskMat4), maskMat1);
CHECK_DIFF(4.0 / (maskMat1 * 4.0), maskMat1);
CHECK_DIFF(4.0 / (maskMat4 / maskMat1), maskMat1);
m = maskMat4.clone(); m/=4.0; CHECK_DIFF(m, maskMat1);
m = maskMat4.clone(); m/=maskMat4; CHECK_DIFF(m, maskMat1);
m = maskMat4.clone(); m/=(maskMat1 * 4.0); CHECK_DIFF(m, maskMat1);
m = maskMat4.clone(); m/=(maskMat4 / maskMat1); CHECK_DIFF(m, maskMat1);
/////////////////////////////
float matrix_data[] = { 3, 1, -4, -5, 1, 0, 0, 1.1f, 1.5f};
Mat mt(3, 3, CV_32F, matrix_data);
Mat mi = mt.inv();
Mat d1 = Mat::eye(3, 3, CV_32F);
Mat d2 = d1 * 2;
MatExpr mt_tr = mt.t();
MatExpr mi_tr = mi.t();
Mat mi2 = mi * 2;
CHECK_DIFF_FLT( mi2 * mt, d2 );
CHECK_DIFF_FLT( mi * mt, d1 );
CHECK_DIFF_FLT( mt_tr * mi_tr, d1 );
m = mi.clone(); m*=mt; CHECK_DIFF_FLT(m, d1);
m = mi.clone(); m*= (2 * mt - mt) ; CHECK_DIFF_FLT(m, d1);
m = maskMat4.clone(); m+=(maskMat1 * 1.0); CHECK_DIFF(m, maskMat5);
m = maskMat5.clone(); m-=(maskMat1 * 4.0); CHECK_DIFF(m, maskMat1);
m = maskMat1.clone(); m+=(maskMat1 * 3.0 + 1.0); CHECK_DIFF(m, maskMat5);
m = maskMat5.clone(); m-=(maskMat1 * 3.0 + 1.0); CHECK_DIFF(m, maskMat1);
#if !MSVC_OLD
m = mi.clone(); m+=(3.0 * mi * mt + d1); CHECK_DIFF_FLT(m, mi + d1 * 4);
m = mi.clone(); m-=(3.0 * mi * mt + d1); CHECK_DIFF_FLT(m, mi - d1 * 4);
m = mi.clone(); m*=(mt * 1.0); CHECK_DIFF_FLT(m, d1);
m = mi.clone(); m*=(mt * 1.0 + Mat::eye(m.size(), m.type())); CHECK_DIFF_FLT(m, d1 + mi);
m = mi.clone(); m*=mt_tr.t(); CHECK_DIFF_FLT(m, d1);
CHECK_DIFF_FLT( (mi * 2) * mt, d2);
CHECK_DIFF_FLT( mi * (2 * mt), d2);
CHECK_DIFF_FLT( mt.t() * mi_tr, d1 );
CHECK_DIFF_FLT( mt_tr * mi.t(), d1 );
CHECK_DIFF_FLT( (mi * 0.4) * (mt * 5), d2);
CHECK_DIFF_FLT( mt.t() * (mi_tr * 2), d2 );
CHECK_DIFF_FLT( (mt_tr * 2) * mi.t(), d2 );
CHECK_DIFF_FLT(mt.t() * mi.t(), d1);
CHECK_DIFF_FLT( (mi * mt) * 2.0, d2);
CHECK_DIFF_FLT( 2.0 * (mi * mt), d2);
CHECK_DIFF_FLT( -(mi * mt), -d1);
CHECK_DIFF_FLT( (mi * mt) / 2.0, d1 / 2);
Mat mt_mul_2_plus_1;
gemm(mt, d1, 2, Mat::ones(3, 3, CV_32F), 1, mt_mul_2_plus_1);
CHECK_DIFF( (mt * 2.0 + 1.0) * mi, mt_mul_2_plus_1 * mi); // (A*alpha + beta)*B
CHECK_DIFF( mi * (mt * 2.0 + 1.0), mi * mt_mul_2_plus_1); // A*(B*alpha + beta)
CHECK_DIFF( (mt * 2.0 + 1.0) * (mi * 2), mt_mul_2_plus_1 * mi2); // (A*alpha + beta)*(B*gamma)
CHECK_DIFF( (mi *2)* (mt * 2.0 + 1.0), mi2 * mt_mul_2_plus_1); // (A*gamma)*(B*alpha + beta)
CHECK_DIFF_FLT( (mt * 2.0 + 1.0) * mi.t(), mt_mul_2_plus_1 * mi_tr); // (A*alpha + beta)*B^t
CHECK_DIFF_FLT( mi.t() * (mt * 2.0 + 1.0), mi_tr * mt_mul_2_plus_1); // A^t*(B*alpha + beta)
CHECK_DIFF_FLT( (mi * mt + d2)*5, d1 * 3 * 5);
CHECK_DIFF_FLT( mi * mt + d2, d1 * 3);
CHECK_DIFF_FLT( -(mi * mt) + d2, d1);
CHECK_DIFF_FLT( (mi * mt) + d1, d2);
CHECK_DIFF_FLT( d1 + (mi * mt), d2);
CHECK_DIFF_FLT( (mi * mt) - d2, -d1);
CHECK_DIFF_FLT( d2 - (mi * mt), d1);
CHECK_DIFF_FLT( (mi * mt) + d2 * 0.5, d2);
CHECK_DIFF_FLT( d2 * 0.5 + (mi * mt), d2);
CHECK_DIFF_FLT( (mi * mt) - d1 * 2, -d1);
CHECK_DIFF_FLT( d1 * 2 - (mi * mt), d1);
CHECK_DIFF_FLT( (mi * mt) + mi.t(), mi_tr + d1);
CHECK_DIFF_FLT( mi.t() + (mi * mt), mi_tr + d1);
CHECK_DIFF_FLT( (mi * mt) - mi.t(), d1 - mi_tr);
CHECK_DIFF_FLT( mi.t() - (mi * mt), mi_tr - d1);
CHECK_DIFF_FLT( 2.0 *(mi * mt + d2), d1 * 6);
CHECK_DIFF_FLT( -(mi * mt + d2), d1 * -3);
CHECK_DIFF_FLT(mt.inv() * mt, d1);
CHECK_DIFF_FLT(mt.inv() * (2*mt - mt), d1);
#endif
}
catch (const test_excep& e)
{
ts->printf(cvtest::TS::LOG, "%s\n", e.s.c_str());
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
return true;
}
bool CV_OperationsTest::SomeMatFunctions()
{
try
{
Mat rgba( 10, 10, CV_8UC4, Scalar(1,2,3,4) );
Mat bgr( rgba.rows, rgba.cols, CV_8UC3 );
Mat alpha( rgba.rows, rgba.cols, CV_8UC1 );
Mat out[] = { bgr, alpha };
// rgba[0] -> bgr[2], rgba[1] -> bgr[1],
// rgba[2] -> bgr[0], rgba[3] -> alpha[0]
int from_to[] = { 0,2, 1,1, 2,0, 3,3 };
mixChannels( &rgba, 1, out, 2, from_to, 4 );
Mat bgr_exp( rgba.size(), CV_8UC3, Scalar(3,2,1));
Mat alpha_exp( rgba.size(), CV_8UC1, Scalar(4));
CHECK_DIFF(bgr_exp, bgr);
CHECK_DIFF(alpha_exp, alpha);
}
catch (const test_excep& e)
{
ts->printf(cvtest::TS::LOG, "%s\n", e.s.c_str());
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
return true;
}
bool CV_OperationsTest::TestTemplateMat()
{
try
{
Mat_<float> one_3x1(3, 1, 1.0f);
Mat_<float> shi_3x1(3, 1, 1.2f);
Mat_<float> shi_2x1(2, 1, -2);
Scalar shift = Scalar::all(15);
float data[] = { sqrt(2.f)/2, -sqrt(2.f)/2, 1.f, sqrt(2.f)/2, sqrt(2.f)/2, 10.f };
Mat_<float> rot_2x3(2, 3, data);
Mat_<float> res = Mat(Mat(2 * rot_2x3) * Mat(one_3x1 + shi_3x1 + shi_3x1 + shi_3x1) - shi_2x1) + shift;
Mat_<float> resS = rot_2x3 * one_3x1;
Mat_<float> tmp, res2, resS2;
add(one_3x1, shi_3x1, tmp);
add(tmp, shi_3x1, tmp);
add(tmp, shi_3x1, tmp);
gemm(rot_2x3, tmp, 2, shi_2x1, -1, res2, 0);
add(res2, Mat(2, 1, CV_32F, shift), res2);
gemm(rot_2x3, one_3x1, 1, shi_2x1, 0, resS2, 0);
CHECK_DIFF(res, res2);
CHECK_DIFF(resS, resS2);
Mat_<float> mat4x4(4, 4);
randu(mat4x4, Scalar(0), Scalar(10));
Mat_<float> roi1 = mat4x4(Rect(Point(1, 1), Size(2, 2)));
Mat_<float> roi2 = mat4x4(Range(1, 3), Range(1, 3));
CHECK_DIFF(roi1, roi2);
CHECK_DIFF(mat4x4, mat4x4(Rect(Point(0,0), mat4x4.size())));
Mat_<int> intMat10(3, 3, 10);
Mat_<int> intMat11(3, 3, 11);
Mat_<uchar> resMat(3, 3, 255);
CHECK_DIFF(resMat, intMat10 == intMat10);
CHECK_DIFF(resMat, intMat10 < intMat11);
CHECK_DIFF(resMat, intMat11 > intMat10);
CHECK_DIFF(resMat, intMat10 <= intMat11);
CHECK_DIFF(resMat, intMat11 >= intMat10);
CHECK_DIFF(resMat, intMat10 == 10.0);
CHECK_DIFF(resMat, intMat10 < 11.0);
CHECK_DIFF(resMat, intMat11 > 10.0);
CHECK_DIFF(resMat, intMat10 <= 11.0);
CHECK_DIFF(resMat, intMat11 >= 10.0);
Mat_<uchar> maskMat4(3, 3, 4);
Mat_<uchar> maskMat1(3, 3, 1);
Mat_<uchar> maskMat5(3, 3, 5);
Mat_<uchar> maskMat0(3, 3, (uchar)0);
CHECK_DIFF(maskMat0, maskMat4 & maskMat1);
CHECK_DIFF(maskMat0, Scalar(1) & maskMat4);
CHECK_DIFF(maskMat0, maskMat4 & Scalar(1));
Mat_<uchar> m;
m = maskMat4.clone(); m&=maskMat1; CHECK_DIFF(maskMat0, m);
m = maskMat4.clone(); m&=Scalar(1); CHECK_DIFF(maskMat0, m);
m = maskMat4.clone(); m|=maskMat1; CHECK_DIFF(maskMat5, m);
m = maskMat4.clone(); m^=maskMat1; CHECK_DIFF(maskMat5, m);
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & (maskMat1 | maskMat1));
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & maskMat1);
CHECK_DIFF(maskMat0, maskMat4 & (maskMat1 | maskMat1));
CHECK_DIFF(maskMat0, maskMat5 ^ (maskMat4 | maskMat1));
CHECK_DIFF(maskMat0, Scalar(5) ^ (maskMat4 | Scalar(1)));
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ maskMat1));
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ Scalar(1)));
CHECK_DIFF(~maskMat1, maskMat1 ^ 0xFF);
CHECK_DIFF(~(maskMat1 | maskMat1), maskMat1 ^ 0xFF);
CHECK_DIFF(maskMat1 + maskMat4, maskMat5);
CHECK_DIFF(maskMat1 + Scalar(4), maskMat5);
CHECK_DIFF(Scalar(4) + maskMat1, maskMat5);
CHECK_DIFF(Scalar(4) + (maskMat1 & maskMat1), maskMat5);
CHECK_DIFF(maskMat1 + 4.0, maskMat5);
CHECK_DIFF((maskMat1 & 0xFF) + 4.0, maskMat5);
CHECK_DIFF(4.0 + maskMat1, maskMat5);
m = maskMat4.clone(); m+=Scalar(1); CHECK_DIFF(m, maskMat5);
m = maskMat4.clone(); m+=maskMat1; CHECK_DIFF(m, maskMat5);
m = maskMat4.clone(); m+=(maskMat1 | maskMat1); CHECK_DIFF(m, maskMat5);
CHECK_DIFF(maskMat5 - maskMat1, maskMat4);
CHECK_DIFF(maskMat5 - Scalar(1), maskMat4);
CHECK_DIFF((maskMat5 | maskMat5) - Scalar(1), maskMat4);
CHECK_DIFF(maskMat5 - 1, maskMat4);
CHECK_DIFF((maskMat5 | maskMat5) - 1, maskMat4);
CHECK_DIFF((maskMat5 | maskMat5) - (maskMat1 | maskMat1), maskMat4);
CHECK_DIFF(maskMat1, min(maskMat1, maskMat5));
CHECK_DIFF(maskMat5, max(maskMat1, maskMat5));
m = maskMat5.clone(); m-=Scalar(1); CHECK_DIFF(m, maskMat4);
m = maskMat5.clone(); m-=maskMat1; CHECK_DIFF(m, maskMat4);
m = maskMat5.clone(); m-=(maskMat1 | maskMat1); CHECK_DIFF(m, maskMat4);
m = maskMat4.clone(); m |= Scalar(1); CHECK_DIFF(maskMat5, m);
m = maskMat5.clone(); m ^= Scalar(1); CHECK_DIFF(maskMat4, m);
CHECK_DIFF(maskMat1, maskMat4/4.0);
Mat_<float> negf(3, 3, -3.0);
Mat_<float> posf = -negf;
Mat_<float> posf2 = posf * 2;
Mat_<int> negi(3, 3, -3);
CHECK_DIFF(abs(negf), -negf);
CHECK_DIFF(abs(posf - posf2), -negf);
CHECK_DIFF(abs(negi), -(negi & negi));
CHECK_DIFF(5.0 - maskMat4, maskMat1);
CHECK_DIFF(maskMat4.mul(maskMat4, 0.25), maskMat4);
CHECK_DIFF(maskMat4.mul(maskMat1 * 4, 0.25), maskMat4);
CHECK_DIFF(maskMat4.mul(maskMat4 / 4), maskMat4);
////// Element-wise division
CHECK_DIFF(maskMat4 / maskMat4, maskMat1);
CHECK_DIFF(4.0 / maskMat4, maskMat1);
m = maskMat4.clone(); m/=4.0; CHECK_DIFF(m, maskMat1);
////////////////////////////////
typedef Mat_<int> TestMat_t;
const TestMat_t cnegi = negi.clone();
TestMat_t::iterator beg = negi.begin();
TestMat_t::iterator end = negi.end();
TestMat_t::const_iterator cbeg = cnegi.begin();
TestMat_t::const_iterator cend = cnegi.end();
int sum = 0;
for(; beg!=end; ++beg)
sum+=*beg;
for(; cbeg!=cend; ++cbeg)
sum-=*cbeg;
if (sum != 0) throw test_excep();
CHECK_DIFF(negi.col(1), negi.col(2));
CHECK_DIFF(negi.row(1), negi.row(2));
CHECK_DIFF(negi.col(1), negi.diag());
if (Mat_<Point2f>(1, 1).elemSize1() != sizeof(float)) throw test_excep();
if (Mat_<Point2f>(1, 1).elemSize() != 2 * sizeof(float)) throw test_excep();
if (Mat_<Point2f>(1, 1).depth() != CV_32F) throw test_excep();
if (Mat_<float>(1, 1).depth() != CV_32F) throw test_excep();
if (Mat_<int>(1, 1).depth() != CV_32S) throw test_excep();
if (Mat_<double>(1, 1).depth() != CV_64F) throw test_excep();
if (Mat_<Point3d>(1, 1).depth() != CV_64F) throw test_excep();
if (Mat_<signed char>(1, 1).depth() != CV_8S) throw test_excep();
if (Mat_<unsigned short>(1, 1).depth() != CV_16U) throw test_excep();
if (Mat_<unsigned short>(1, 1).channels() != 1) throw test_excep();
if (Mat_<Point2f>(1, 1).channels() != 2) throw test_excep();
if (Mat_<Point3f>(1, 1).channels() != 3) throw test_excep();
if (Mat_<Point3d>(1, 1).channels() != 3) throw test_excep();
Mat_<uchar> eye = Mat_<uchar>::zeros(2, 2); CHECK_DIFF(Mat_<uchar>::zeros(Size(2, 2)), eye);
eye.at<uchar>(Point(0,0)) = 1; eye.at<uchar>(1, 1) = 1;
CHECK_DIFF(Mat_<uchar>::eye(2, 2), eye);
CHECK_DIFF(eye, Mat_<uchar>::eye(Size(2,2)));
Mat_<uchar> ones(2, 2, (uchar)1);
CHECK_DIFF(ones, Mat_<uchar>::ones(Size(2,2)));
CHECK_DIFF(Mat_<uchar>::ones(2, 2), ones);
Mat_<Point2f> pntMat(2, 2, Point2f(1, 0));
if(pntMat.stepT() != 2) throw test_excep();
uchar uchar_data[] = {1, 0, 0, 1};
Mat_<uchar> matFromData(1, 4, uchar_data);
const Mat_<uchar> mat2 = matFromData.clone();
CHECK_DIFF(matFromData, eye.reshape(1));
if (matFromData(Point(0,0)) != uchar_data[0])throw test_excep();
if (mat2(Point(0,0)) != uchar_data[0]) throw test_excep();
if (matFromData(0,0) != uchar_data[0])throw test_excep();
if (mat2(0,0) != uchar_data[0]) throw test_excep();
Mat_<uchar> rect(eye, Rect(0, 0, 1, 1));
if (rect.cols != 1 || rect.rows != 1 || rect(0,0) != uchar_data[0]) throw test_excep();
//cv::Mat_<_Tp>::adjustROI(int,int,int,int)
//cv::Mat_<_Tp>::cross(const Mat_&) const
//cv::Mat_<_Tp>::Mat_(const vector<_Tp>&,bool)
//cv::Mat_<_Tp>::Mat_(int,int,_Tp*,size_t)
//cv::Mat_<_Tp>::Mat_(int,int,const _Tp&)
//cv::Mat_<_Tp>::Mat_(Size,const _Tp&)
//cv::Mat_<_Tp>::mul(const Mat_<_Tp>&,double) const
//cv::Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat_<_Tp>,double,Mat_<_Tp>,MatOp_DivRS_<Mat> >,Mat_<_Tp> >&,double) const
//cv::Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat_<_Tp>,double,Mat_<_Tp>,MatOp_Scale_<Mat> >,Mat_<_Tp> >&,double) const
//cv::Mat_<_Tp>::operator Mat_<T2>() const
//cv::Mat_<_Tp>::operator MatExpr_<Mat_<_Tp>,Mat_<_Tp> >() const
//cv::Mat_<_Tp>::operator()(const Range&,const Range&) const
//cv::Mat_<_Tp>::operator()(const Rect&) const
//cv::Mat_<_Tp>::operator=(const MatExpr_Base&)
//cv::Mat_<_Tp>::operator[](int) const
///////////////////////////////
float matrix_data[] = { 3, 1, -4, -5, 1, 0, 0, 1.1f, 1.5f};
Mat_<float> mt(3, 3, matrix_data);
Mat_<float> mi = mt.inv();
Mat_<float> d1 = Mat_<float>::eye(3, 3);
Mat_<float> d2 = d1 * 2;
Mat_<float> mt_tr = mt.t();
Mat_<float> mi_tr = mi.t();
Mat_<float> mi2 = mi * 2;
CHECK_DIFF_FLT( mi2 * mt, d2 );
CHECK_DIFF_FLT( mi * mt, d1 );
CHECK_DIFF_FLT( mt_tr * mi_tr, d1 );
Mat_<float> mf;
mf = mi.clone(); mf*=mt; CHECK_DIFF_FLT(mf, d1);
////// typedefs //////
if (Mat1b(1, 1).elemSize() != sizeof(uchar)) throw test_excep();
if (Mat2b(1, 1).elemSize() != 2 * sizeof(uchar)) throw test_excep();
if (Mat3b(1, 1).elemSize() != 3 * sizeof(uchar)) throw test_excep();
if (Mat1f(1, 1).elemSize() != sizeof(float)) throw test_excep();
if (Mat2f(1, 1).elemSize() != 2 * sizeof(float)) throw test_excep();
if (Mat3f(1, 1).elemSize() != 3 * sizeof(float)) throw test_excep();
if (Mat1f(1, 1).depth() != CV_32F) throw test_excep();
if (Mat3f(1, 1).depth() != CV_32F) throw test_excep();
if (Mat3f(1, 1).type() != CV_32FC3) throw test_excep();
if (Mat1i(1, 1).depth() != CV_32S) throw test_excep();
if (Mat1d(1, 1).depth() != CV_64F) throw test_excep();
if (Mat1b(1, 1).depth() != CV_8U) throw test_excep();
if (Mat3b(1, 1).type() != CV_8UC3) throw test_excep();
if (Mat1w(1, 1).depth() != CV_16U) throw test_excep();
if (Mat1s(1, 1).depth() != CV_16S) throw test_excep();
if (Mat1f(1, 1).channels() != 1) throw test_excep();
if (Mat1b(1, 1).channels() != 1) throw test_excep();
if (Mat1i(1, 1).channels() != 1) throw test_excep();
if (Mat1w(1, 1).channels() != 1) throw test_excep();
if (Mat1s(1, 1).channels() != 1) throw test_excep();
if (Mat2f(1, 1).channels() != 2) throw test_excep();
if (Mat2b(1, 1).channels() != 2) throw test_excep();
if (Mat2i(1, 1).channels() != 2) throw test_excep();
if (Mat2w(1, 1).channels() != 2) throw test_excep();
if (Mat2s(1, 1).channels() != 2) throw test_excep();
if (Mat3f(1, 1).channels() != 3) throw test_excep();
if (Mat3b(1, 1).channels() != 3) throw test_excep();
if (Mat3i(1, 1).channels() != 3) throw test_excep();
if (Mat3w(1, 1).channels() != 3) throw test_excep();
if (Mat3s(1, 1).channels() != 3) throw test_excep();
}
catch (const test_excep& e)
{
ts->printf(cvtest::TS::LOG, "%s\n", e.s.c_str());
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
return true;
}
bool CV_OperationsTest::TestMatND()
{
int sizes[] = { 3, 3, 3};
cv::MatND nd(3, sizes, CV_32F);
return true;
}
bool CV_OperationsTest::TestSparseMat()
{
try
{
int sizes[] = { 10, 10, 10};
int dims = sizeof(sizes)/sizeof(sizes[0]);
SparseMat mat(dims, sizes, CV_32FC2);
if (mat.dims() != dims) throw test_excep();
if (mat.channels() != 2) throw test_excep();
if (mat.depth() != CV_32F) throw test_excep();
SparseMat mat2 = mat.clone();
}
catch (const test_excep&)
{
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
return true;
}
bool CV_OperationsTest::operations1()
{
try
{
Point3d p1(1, 1, 1), p2(2, 2, 2), p4(4, 4, 4);
p1*=2;
if (!(p1 == p2)) throw test_excep();
if (!(p2 * 2 == p4)) throw test_excep();
if (!(p2 * 2.f == p4)) throw test_excep();
if (!(p2 * 2.f == p4)) throw test_excep();
Point2d pi1(1, 1), pi2(2, 2), pi4(4, 4);
pi1*=2;
if (!(pi1 == pi2)) throw test_excep();
if (!(pi2 * 2 == pi4)) throw test_excep();
if (!(pi2 * 2.f == pi4)) throw test_excep();
if (!(pi2 * 2.f == pi4)) throw test_excep();
Vec2d v12(1, 1), v22(2, 2);
v12*=2.0;
if (!(v12 == v22)) throw test_excep();
Vec3d v13(1, 1, 1), v23(2, 2, 2);
v13*=2.0;
if (!(v13 == v23)) throw test_excep();
Vec4d v14(1, 1, 1, 1), v24(2, 2, 2, 2);
v14*=2.0;
if (!(v14 == v24)) throw test_excep();
Size sz(10, 20);
if (sz.area() != 200) throw test_excep();
if (sz.width != 10 || sz.height != 20) throw test_excep();
if (((CvSize)sz).width != 10 || ((CvSize)sz).height != 20) throw test_excep();
Vec<double, 5> v5d(1, 1, 1, 1, 1);
Vec<double, 6> v6d(1, 1, 1, 1, 1, 1);
Vec<double, 7> v7d(1, 1, 1, 1, 1, 1, 1);
Vec<double, 8> v8d(1, 1, 1, 1, 1, 1, 1, 1);
Vec<double, 9> v9d(1, 1, 1, 1, 1, 1, 1, 1, 1);
Vec<double,10> v10d(1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
Vec<double,10> v10dzero;
for (int ii = 0; ii < 10; ++ii) {
if (!v10dzero[ii] == 0.0)
throw test_excep();
}
}
catch(const test_excep&)
{
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
return true;
}
void CV_OperationsTest::run( int /* start_from */)
{
if (!TestMat())
return;
if (!SomeMatFunctions())
return;
if (!TestTemplateMat())
return;
/* if (!TestMatND())
return;*/
if (!TestSparseMat())
return;
if (!operations1())
return;
ts->set_failed_test_info(cvtest::TS::OK);
}
TEST(Core_Array, expressions) { CV_OperationsTest test; test.safe_run(); }

View File

@@ -1,2 +1,8 @@
#include "opencv2/gtest/gtestcv.hpp"
#include "opencv2/core/core.hpp"
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/ts/ts.hpp"
#include "opencv2/core/core_c.h"
#include <iostream>
#endif

View File

@@ -0,0 +1,303 @@
#include "test_precomp.hpp"
using namespace cv;
using namespace std;
class Core_RandTest : public cvtest::BaseTest
{
public:
Core_RandTest();
protected:
void run(int);
bool check_pdf(const Mat& hist, double scale, int dist_type,
double& refval, double& realval);
};
Core_RandTest::Core_RandTest()
{
}
static double chi2_p95(int n)
{
static float chi2_tab95[] = {
3.841f, 5.991f, 7.815f, 9.488f, 11.07f, 12.59f, 14.07f, 15.51f,
16.92f, 18.31f, 19.68f, 21.03f, 21.03f, 22.36f, 23.69f, 25.00f,
26.30f, 27.59f, 28.87f, 30.14f, 31.41f, 32.67f, 33.92f, 35.17f,
36.42f, 37.65f, 38.89f, 40.11f, 41.34f, 42.56f, 43.77f };
static const double xp = 1.64;
CV_Assert(n >= 1);
if( n <= 30 )
return chi2_tab95[n-1];
return n + sqrt((double)2*n)*xp + 0.6666666666666*(xp*xp - 1);
}
bool Core_RandTest::check_pdf(const Mat& hist, double scale,
int dist_type, double& refval, double& realval)
{
Mat hist0(hist.size(), CV_32F);
const int* H = (const int*)hist.data;
float* H0 = ((float*)hist0.data);
int i, hsz = hist.cols;
double sum = 0;
for( i = 0; i < hsz; i++ )
sum += H[i];
CV_Assert( fabs(1./sum - scale) < FLT_EPSILON );
if( dist_type == CV_RAND_UNI )
{
float scale0 = (float)(1./hsz);
for( i = 0; i < hsz; i++ )
H0[i] = scale0;
}
else
{
double sum = 0, r = (hsz-1.)/2;
double alpha = 2*sqrt(2.)/r, beta = -alpha*r;
for( i = 0; i < hsz; i++ )
{
double x = i*alpha + beta;
H0[i] = (float)exp(-x*x);
sum += H0[i];
}
sum = 1./sum;
for( i = 0; i < hsz; i++ )
H0[i] = (float)(H0[i]*sum);
}
double chi2 = 0;
for( i = 0; i < hsz; i++ )
{
double a = H0[i];
double b = H[i]*scale;
if( a > DBL_EPSILON )
chi2 += (a - b)*(a - b)/(a + b);
}
realval = chi2;
double chi2_pval = chi2_p95(hsz - 1 - (dist_type == CV_RAND_NORMAL ? 2 : 0));
refval = chi2_pval*0.01;
return realval <= refval;
}
void Core_RandTest::run( int )
{
static int _ranges[][2] =
{{ 0, 256 }, { -128, 128 }, { 0, 65536 }, { -32768, 32768 },
{ -1000000, 1000000 }, { -1000, 1000 }, { -1000, 1000 }};
const int MAX_SDIM = 10;
const int N = 2000000;
const int maxSlice = 1000;
const int MAX_HIST_SIZE = 1000;
int progress = 0;
RNG& rng = ts->get_rng();
RNG tested_rng = theRNG();
test_case_count = 200;
for( int idx = 0; idx < test_case_count; idx++ )
{
progress = update_progress( progress, idx, test_case_count, 0 );
ts->update_context( this, idx, false );
int depth = cvtest::randInt(rng) % (CV_64F+1);
int c, cn = (cvtest::randInt(rng) % 4) + 1;
int type = CV_MAKETYPE(depth, cn);
int dist_type = cvtest::randInt(rng) % (CV_RAND_NORMAL+1);
int i, k, SZ = N/cn;
Scalar A, B;
bool do_sphere_test = dist_type == CV_RAND_UNI;
Mat arr[2], hist[4];
int W[] = {0,0,0,0};
arr[0].create(1, SZ, type);
arr[1].create(1, SZ, type);
bool fast_algo = dist_type == CV_RAND_UNI && depth < CV_32F;
for( c = 0; c < cn; c++ )
{
int a, b, hsz;
if( dist_type == CV_RAND_UNI )
{
a = (int)(cvtest::randInt(rng) % (_ranges[depth][1] -
_ranges[depth][0])) + _ranges[depth][0];
do
{
b = (int)(cvtest::randInt(rng) % (_ranges[depth][1] -
_ranges[depth][0])) + _ranges[depth][0];
}
while( abs(a-b) <= 1 );
if( a > b )
std::swap(a, b);
unsigned r = (unsigned)(b - a);
fast_algo = fast_algo && r <= 256 && (r & (r-1)) == 0;
hsz = min((unsigned)(b - a), (unsigned)MAX_HIST_SIZE);
do_sphere_test = do_sphere_test && b - a >= 100;
}
else
{
int vrange = _ranges[depth][1] - _ranges[depth][0];
int meanrange = vrange/16;
int mindiv = MAX(vrange/20, 5);
int maxdiv = MIN(vrange/8, 10000);
a = cvtest::randInt(rng) % meanrange - meanrange/2 +
(_ranges[depth][0] + _ranges[depth][1])/2;
b = cvtest::randInt(rng) % (maxdiv - mindiv) + mindiv;
hsz = min((unsigned)b*9, (unsigned)MAX_HIST_SIZE);
}
A[c] = a;
B[c] = b;
hist[c].create(1, hsz, CV_32S);
}
cv::RNG saved_rng = tested_rng;
int maxk = fast_algo ? 0 : 1;
for( k = 0; k <= maxk; k++ )
{
tested_rng = saved_rng;
int sz = 0, dsz = 0, slice;
for( slice = 0; slice < maxSlice; slice++, sz += dsz )
{
dsz = slice+1 < maxSlice ? cvtest::randInt(rng) % (SZ - sz + 1) : SZ - sz;
Mat aslice = arr[k].colRange(sz, sz + dsz);
tested_rng.fill(aslice, dist_type, A, B);
}
}
if( maxk >= 1 && norm(arr[0], arr[1], NORM_INF) != 0 )
{
ts->printf( cvtest::TS::LOG, "RNG output depends on the array lengths (some generated numbers get lost?)" );
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
for( c = 0; c < cn; c++ )
{
const uchar* data = arr[0].data;
int* H = hist[c].ptr<int>();
int HSZ = hist[c].cols;
double minVal = dist_type == CV_RAND_UNI ? A[c] : A[c] - B[c]*4;
double maxVal = dist_type == CV_RAND_UNI ? B[c] : A[c] + B[c]*4;
double scale = HSZ/(maxVal - minVal);
double delta = -minVal*scale;
hist[c] = Scalar::all(0);
for( i = c; i < SZ*cn; i += cn )
{
double val = depth == CV_8U ? ((const uchar*)data)[i] :
depth == CV_8S ? ((const schar*)data)[i] :
depth == CV_16U ? ((const ushort*)data)[i] :
depth == CV_16S ? ((const short*)data)[i] :
depth == CV_32S ? ((const int*)data)[i] :
depth == CV_32F ? ((const float*)data)[i] :
((const double*)data)[i];
int ival = cvFloor(val*scale + delta);
if( (unsigned)ival < (unsigned)HSZ )
{
H[ival]++;
W[c]++;
}
else if( dist_type == CV_RAND_UNI )
{
if( (minVal <= val && val < maxVal) || (depth >= CV_32F && val == maxVal) )
{
H[ival < 0 ? 0 : HSZ-1]++;
W[c]++;
}
else
{
putchar('^');
}
}
}
if( dist_type == CV_RAND_UNI && W[c] != SZ )
{
ts->printf( cvtest::TS::LOG, "Uniform RNG gave values out of the range [%g,%g) on channel %d/%d\n",
A[c], B[c], c, cn);
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
if( dist_type == CV_RAND_NORMAL && W[c] < SZ*.90)
{
ts->printf( cvtest::TS::LOG, "Normal RNG gave too many values out of the range (%g+4*%g,%g+4*%g) on channel %d/%d\n",
A[c], B[c], A[c], B[c], c, cn);
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
double refval = 0, realval = 0;
if( !check_pdf(hist[c], 1./W[c], dist_type, refval, realval) )
{
ts->printf( cvtest::TS::LOG, "RNG failed Chi-square test "
"(got %g vs probable maximum %g) on channel %d/%d\n",
realval, refval, c, cn);
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
}
// Monte-Carlo test. Compute volume of SDIM-dimensional sphere
// inscribed in [-1,1]^SDIM cube.
if( do_sphere_test )
{
int SDIM = cvtest::randInt(rng) % (MAX_SDIM-1) + 2;
int N0 = (SZ*cn/SDIM), N = 0;
double r2 = 0;
const uchar* data = arr[0].data;
double scale[4], delta[4];
for( c = 0; c < cn; c++ )
{
scale[c] = 2./(B[c] - A[c]);
delta[c] = -A[c]*scale[c] - 1;
}
for( i = k = c = 0; i <= SZ*cn - SDIM; i++, k++, c++ )
{
double val = depth == CV_8U ? ((const uchar*)data)[i] :
depth == CV_8S ? ((const schar*)data)[i] :
depth == CV_16U ? ((const ushort*)data)[i] :
depth == CV_16S ? ((const short*)data)[i] :
depth == CV_32S ? ((const int*)data)[i] :
depth == CV_32F ? ((const float*)data)[i] : ((const double*)data)[i];
c &= c < cn ? -1 : 0;
val = val*scale[c] + delta[c];
r2 += val*val;
if( k == SDIM-1 )
{
N += r2 <= 1;
r2 = 0;
k = -1;
}
}
double V = ((double)N/N0)*(1 << SDIM);
// the theoretically computed volume
int sdim = SDIM % 2;
double V0 = sdim + 1;
for( sdim += 2; sdim <= SDIM; sdim += 2 )
V0 *= 2*CV_PI/sdim;
if( fabs(V - V0) > 0.3*fabs(V0) )
{
ts->printf( cvtest::TS::LOG, "RNG failed %d-dim sphere volume test (got %g instead of %g)\n",
SDIM, V, V0);
ts->printf( cvtest::TS::LOG, "depth = %d, N0 = %d\n", depth, N0);
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
return;
}
}
}
}
TEST(Core_Rand, quality) { Core_RandTest test; test.safe_run(); }