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

View File

@@ -288,14 +288,6 @@ CV_INLINE IppiSize ippiSize(int width, int height)
/* ! DO NOT make it an inline function */
#define cvStackAlloc(size) cvAlignPtr( alloca((size) + CV_MALLOC_ALIGN), CV_MALLOC_ALIGN )
#if defined _MSC_VER || defined __BORLANDC__
#define CV_BIG_INT(n) n##I64
#define CV_BIG_UINT(n) n##UI64
#else
#define CV_BIG_INT(n) n##LL
#define CV_BIG_UINT(n) n##ULL
#endif
#ifndef CV_IMPL
#define CV_IMPL CV_EXTERN_C
#endif

View File

@@ -145,9 +145,13 @@
#if defined _MSC_VER || defined __BORLANDC__
typedef __int64 int64;
typedef unsigned __int64 uint64;
#define CV_BIG_INT(n) n##I64
#define CV_BIG_UINT(n) n##UI64
#else
typedef int64_t int64;
typedef uint64_t uint64;
#define CV_BIG_INT(n) n##LL
#define CV_BIG_UINT(n) n##ULL
#endif
#ifndef HAVE_IPL

View File

@@ -1158,10 +1158,10 @@ div_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double scale )
b *= d;
a *= d;
T z0 = saturate_cast<T>(src2[i+1] * src1[i] * b);
T z1 = saturate_cast<T>(src2[i] * src1[i+1] * b);
T z2 = saturate_cast<T>(src2[i+3] * src1[i+2] * a);
T z3 = saturate_cast<T>(src2[i+2] * src1[i+3] * a);
T z0 = saturate_cast<T>(src2[i+1] * ((double)src1[i] * b));
T z1 = saturate_cast<T>(src2[i] * ((double)src1[i+1] * b));
T z2 = saturate_cast<T>(src2[i+3] * ((double)src1[i+2] * a));
T z3 = saturate_cast<T>(src2[i+2] * ((double)src1[i+3] * a));
dst[i] = z0; dst[i+1] = z1;
dst[i+2] = z2; dst[i+3] = z3;
@@ -1193,7 +1193,7 @@ void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale)
};
MulDivFunc func = tab[src1.depth()];
CV_Assert( src1.size() == src2.size() && src1.type() == src2.type() && func != 0 );
CV_Assert( src1.type() == src2.type() && func != 0 );
if( src1.dims > 2 || src2.dims > 2 )
{
@@ -1446,7 +1446,7 @@ void addWeighted( const Mat& src1, double alpha, const Mat& src2,
addWeighted_<ushort, float>,
addWeighted_<short, float>,
addWeighted_<int, double>,
addWeighted_<float, float>,
addWeighted_<float, double>,
addWeighted_<double, double>,
0
};
@@ -1952,7 +1952,7 @@ void compare( const Mat& src1, double value, Mat& dst, int cmpOp )
{
func( it.planes[0], it.planes[1], value );
if( invflag )
bitwise_not(it.planes[2], it.planes[2]);
bitwise_not(it.planes[1], it.planes[1]);
}
return;
}

View File

@@ -619,7 +619,7 @@ static const int FBITS = 15;
typedef void (*CvtFunc)( const Mat& src, Mat& dst );
typedef void (*CvtScaleFunc)( const Mat& src, Mat& dst, double scale, double shift );
void convertScaleAbs( const Mat& src, Mat& dst, double scale, double shift )
void convertScaleAbs( const Mat& src0, Mat& dst, double scale, double shift )
{
static CvtScaleFunc tab[] =
{
@@ -632,15 +632,27 @@ void convertScaleAbs( const Mat& src, Mat& dst, double scale, double shift )
cvtScale_<double, OpCvtAbs<double, uchar> >, 0
};
Mat src0 = src;
dst.create( src.size(), CV_8UC(src.channels()) );
CvtScaleFunc func = tab[src0.depth()];
Mat src = src0;
dst.create( src.dims, src.size, CV_8UC(src.channels()) );
CvtScaleFunc func = tab[src.depth()];
CV_Assert( func != 0 );
func( src0, dst, scale, shift );
if( src.dims <= 2 )
{
func( src, dst, scale, shift );
}
else
{
const Mat* arrays[] = {&src, &dst, 0};
Mat planes[2];
NAryMatIterator it(arrays, planes);
for( int i = 0; i < it.nplanes; i++, ++it )
func(it.planes[0], it.planes[1], scale, shift);
}
}
void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
{
static CvtFunc tab[8][8] =
@@ -699,7 +711,7 @@ void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
cvtScaleInt_<ushort, OpCvtFixPt<int, ushort, FBITS>, OpCvt<float, ushort>, 0>,
cvtScaleInt_<ushort, OpCvtFixPt<int, short, FBITS>, OpCvt<float, short>, 0>,
cvtScale_<ushort, OpCvt<double, int> >,
cvtScale_<ushort, OpCvt<float, float> >,
cvtScale_<ushort, OpCvt<double, float> >,
cvtScale_<ushort, OpCvt<double, double> >, 0,
},
@@ -709,7 +721,7 @@ void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
cvtScaleInt_<short, OpCvtFixPt<int, ushort, FBITS>, OpCvt<float, ushort>, 1<<15>,
cvtScaleInt_<short, OpCvtFixPt<int, short, FBITS>, OpCvt<float, short>, 1<<15>,
cvtScale_<short, OpCvt<double, int> >,
cvtScale_<short, OpCvt<float, float> >,
cvtScale_<short, OpCvt<double, float> >,
cvtScale_<short, OpCvt<double, double> >, 0,
},
@@ -719,7 +731,7 @@ void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
cvtScale_<int, OpCvt<double, ushort> >,
cvtScale_<int, OpCvt<double, short> >,
cvtScale_<int, OpCvt<double, int> >,
cvtScale_<int, OpCvt<float, float> >,
cvtScale_<int, OpCvt<double, float> >,
cvtScale_<int, OpCvt<double, double> >, 0,
},

View File

@@ -47,37 +47,17 @@ namespace cv
{
static const int MAX_BLOCK_SIZE = 1024;
typedef CvStatus (CV_STDCALL * MathFunc)(const void* src, void* dst, int len);
#define ICV_MATH_BLOCK_SIZE 256
#define _CV_SQRT_MAGIC 0xbe6f0000
#define _CV_SQRT_MAGIC_DBL CV_BIG_UINT(0xbfcd460000000000)
#define _CV_ATAN_CF0 (-15.8131890796f)
#define _CV_ATAN_CF1 (61.0941945596f)
#define _CV_ATAN_CF2 0.f /*(-0.140500406322f)*/
static const float icvAtanTab[8] = { 0.f + _CV_ATAN_CF2, 90.f - _CV_ATAN_CF2,
180.f - _CV_ATAN_CF2, 90.f + _CV_ATAN_CF2,
360.f - _CV_ATAN_CF2, 270.f + _CV_ATAN_CF2,
180.f + _CV_ATAN_CF2, 270.f - _CV_ATAN_CF2
};
static const int icvAtanSign[8] =
{ 0, 0x80000000, 0x80000000, 0, 0x80000000, 0, 0, 0x80000000 };
float fastAtan2( float y, float x )
{
double a, x2 = (double)x*x, y2 = (double)y*y;
if( y2 <= x2 )
{
a = (180./CV_PI)*x*y/(x2 + 0.28*y2 + DBL_EPSILON);
a = (180./CV_PI)*x*y*(x2 + 0.43157974*y2)/(x2*x2 + y2*(0.76443945*x2 + 0.05831938*y2) + DBL_EPSILON);
return (float)(x < 0 ? a + 180 : y >= 0 ? a : 360+a);
}
a = (180./CV_PI)*x*y/(y2 + 0.28*x2 + DBL_EPSILON);
a = (180./CV_PI)*x*y*(y2 + 0.43157974*x2)/(y2*y2 + x2*(0.76443945*y2 + 0.05831938*x2) + DBL_EPSILON);
return (float)(y >= 0 ? 90 - a : 270 - a);
}
@@ -95,15 +75,20 @@ static CvStatus CV_STDCALL FastAtan2_32f(const float *Y, const float *X, float *
Cv32suf iabsmask; iabsmask.i = 0x7fffffff;
__m128 eps = _mm_set1_ps((float)DBL_EPSILON), absmask = _mm_set1_ps(iabsmask.f);
__m128 _90 = _mm_set1_ps((float)(CV_PI*0.5)), _180 = _mm_set1_ps((float)CV_PI), _360 = _mm_set1_ps((float)(CV_PI*2));
__m128 zero = _mm_setzero_ps(), _0_28 = _mm_set1_ps(0.28f), scale4 = _mm_set1_ps(scale);
__m128 zero = _mm_setzero_ps(), scale4 = _mm_set1_ps(scale);
__m128 p0 = _mm_set1_ps(0.43157974f), q0 = _mm_set1_ps(0.76443945f), q1 = _mm_set1_ps(0.05831938f);
for( ; i <= len - 4; i += 4 )
{
__m128 x4 = _mm_loadu_ps(X + i), y4 = _mm_loadu_ps(Y + i);
__m128 xq4 = _mm_mul_ps(x4, x4), yq4 = _mm_mul_ps(y4, y4);
__m128 xly = _mm_cmplt_ps(xq4, yq4);
__m128 z4 = _mm_div_ps(_mm_mul_ps(x4, y4), _mm_add_ps(_mm_add_ps(_mm_max_ps(xq4, yq4),
_mm_mul_ps(_mm_min_ps(xq4, yq4), _0_28)), eps));
__m128 t = _mm_min_ps(xq4, yq4);
xq4 = _mm_max_ps(xq4, yq4); yq4 = t;
__m128 z4 = _mm_div_ps(_mm_mul_ps(_mm_mul_ps(x4, y4), _mm_add_ps(xq4, _mm_mul_ps(yq4, p0))),
_mm_add_ps(eps, _mm_add_ps(_mm_mul_ps(xq4, xq4),
_mm_mul_ps(yq4, _mm_add_ps(_mm_mul_ps(xq4, q0),
_mm_mul_ps(yq4, q1))))));
// a4 <- x < y ? 90 : 0;
__m128 a4 = _mm_and_ps(xly, _90);
@@ -121,15 +106,19 @@ static CvStatus CV_STDCALL FastAtan2_32f(const float *Y, const float *X, float *
}
#endif
for( ; i < len; i++ )
for( ; i < len; i++ )
{
float x = X[i], y = Y[i];
float a, x2 = x*x, y2 = y*y;
if( y2 <= x2 )
a = x*y/(x2 + 0.28f*y2 + (float)DBL_EPSILON) + (float)(x < 0 ? CV_PI : y >= 0 ? 0 : CV_PI*2);
else
a = (float)(y >= 0 ? CV_PI*0.5 : CV_PI*1.5) - x*y/(y2 + 0.28f*x2 + (float)DBL_EPSILON);
angle[i] = a*scale;
double x = X[i], y = Y[i], x2 = x*x, y2 = y*y, a;
if( y2 <= x2 )
a = (x < 0 ? CV_PI : y >= 0 ? 0 : CV_PI*2) +
x*y*(x2 + 0.43157974*y2)/(x2*x2 + y2*(0.76443945*x2 + 0.05831938*y2) + (float)DBL_EPSILON);
else
{
a = (y >= 0 ? CV_PI*0.5 : CV_PI*1.5) -
x*y*(y2 + 0.43157974*x2)/(y2*y2 + x2*(0.76443945*y2 + 0.05831938*x2) + (float)DBL_EPSILON);
}
angle[i] = a*scale;
}
return CV_OK;

View File

@@ -102,6 +102,7 @@ static inline void setSize( Mat& m, int _dims, const int* _sz,
m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0]));
m.size.p = (int*)(m.step.p + _dims) + 1;
m.size.p[-1] = _dims;
m.rows = m.cols = -1;
}
}
@@ -711,10 +712,19 @@ void insertImageCOI(const Mat& ch, CvArr* arr, int coi)
Mat Mat::reshape(int new_cn, int new_rows) const
{
CV_Assert( dims <= 2 );
Mat hdr = *this;
int cn = channels();
Mat hdr = *this;
if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
{
hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
return hdr;
}
CV_Assert( dims <= 2 );
if( new_cn == 0 )
new_cn = cn;

View File

@@ -409,7 +409,7 @@ template<> inline Vec<double, 4> SqrC4<uchar, double>::operator() (const Vec<uch
template<class SqrOp> static void
meanStdDev_( const Mat& srcmat, Scalar& _mean, Scalar& _stddev )
meanStdDev_( const Mat& srcmat, Scalar& _sum, Scalar& _sqsum )
{
SqrOp sqr;
typedef typename SqrOp::type1 T;
@@ -430,20 +430,13 @@ meanStdDev_( const Mat& srcmat, Scalar& _mean, Scalar& _stddev )
sq += sqr(v);
}
}
_mean = _stddev = Scalar();
double scale = 1./std::max(size.width*size.height, 1);
for( int i = 0; i < DataType<ST>::channels; i++ )
{
double t = ((ST1*)&s)[i]*scale;
_mean.val[i] = t;
_stddev.val[i] = std::sqrt(std::max(((ST1*)&sq)[i]*scale - t*t, 0.));
}
_sum = rawToScalar(s);
_sqsum = rawToScalar(sq);
}
template<class SqrOp> static void
meanStdDevMask_( const Mat& srcmat, const Mat& maskmat,
Scalar& _mean, Scalar& _stddev )
Scalar& _sum, Scalar& _sqsum, int& _nz )
{
SqrOp sqr;
typedef typename SqrOp::type1 T;
@@ -470,20 +463,15 @@ meanStdDevMask_( const Mat& srcmat, const Mat& maskmat,
pix++;
}
}
_mean = _stddev = Scalar();
double scale = 1./std::max(pix, 1);
for( int i = 0; i < DataType<ST>::channels; i++ )
{
double t = ((ST1*)&s)[i]*scale;
_mean.val[i] = t;
_stddev.val[i] = std::sqrt(std::max(((ST1*)&sq)[i]*scale - t*t, 0.));
}
_sum = rawToScalar(s);
_sqsum = rawToScalar(sq);
_nz = pix;
}
typedef void (*MeanStdDevFunc)(const Mat& src, Scalar& mean, Scalar& stddev);
typedef void (*MeanStdDevFunc)(const Mat& src, Scalar& s, Scalar& sq);
typedef void (*MeanStdDevMaskFunc)(const Mat& src, const Mat& mask,
Scalar& mean, Scalar& stddev);
Scalar& s, Scalar& sq, int& nz);
void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask )
{
@@ -551,55 +539,53 @@ void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask )
CV_Assert( m.channels() <= 4 && (mask.empty() || mask.type() == CV_8U) );
Scalar sum, sqsum;
int total = 0;
MeanStdDevFunc func = tab[m.type()];
MeanStdDevMaskFunc mfunc = mtab[m.type()];
CV_Assert( func != 0 || mfunc != 0 );
CV_Assert( func != 0 && mfunc != 0 );
if( m.dims > 2 )
{
Scalar s, sq;
double total = 0;
const Mat* arrays[] = {&m, &mask, 0};
Mat planes[2];
NAryMatIterator it(arrays, planes);
int k, cn = m.channels();
int nz = (int)planes[0].total();
for( int i = 0; i < it.nplanes; i++, ++it )
{
Scalar _mean, _stddev;
double nz = (double)(mask.data ? countNonZero(it.planes[1]) : it.planes[0].rows*it.planes[0].cols);
Scalar s, sq;
if( func )
func(it.planes[0], _mean, _stddev);
if( mask.empty() )
func(it.planes[0], s, sq);
else
mfunc(it.planes[0], it.planes[1], _mean, _stddev);
mfunc(it.planes[0], it.planes[1], s, sq, nz);
total += nz;
for( k = 0; k < cn; k++ )
{
s[k] += _mean[k]*nz;
sq[k] += (_stddev[k]*_stddev[k] + _mean[k]*_mean[k])*nz;
}
sum += s;
sqsum += sq;
}
mean = stddev = Scalar();
total = 1./std::max(total, 1.);
for( k = 0; k < cn; k++ )
{
mean[k] = s[k]*total;
stddev[k] = std::sqrt(std::max(sq[k]*total - mean[k]*mean[k], 0.));
}
return;
}
if( mask.data )
{
CV_Assert( mask.size() == m.size() );
mfunc( m, mask, mean, stddev );
}
else
func( m, mean, stddev );
{
if( mask.data )
{
CV_Assert( mask.size() == m.size() );
mfunc( m, mask, sum, sqsum, total );
}
else
{
func( m, sum, sqsum );
total = (int)m.total();
}
}
double scale = 1./std::max(total, 1);
for( int k = 0; k < 4; k++ )
{
mean[k] = sum[k]*scale;
stddev[k] = std::sqrt(std::max(sqsum[k]*scale - mean[k]*mean[k], 0.));
}
}
@@ -607,45 +593,46 @@ void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask )
* minMaxLoc *
\****************************************************************************************/
template<typename T> static void
minMaxIndx_( const Mat& srcmat, double* minVal, double* maxVal, int* minLoc, int* maxLoc )
template<typename T, typename WT> static void
minMaxIndx_( const Mat& srcmat, double* _minVal, double* _maxVal,
size_t startIdx, size_t* _minIdx, size_t* _maxIdx )
{
assert( DataType<T>::type == srcmat.type() );
const T* src = (const T*)srcmat.data;
size_t step = srcmat.step/sizeof(src[0]);
T min_val = src[0], max_val = min_val;
int min_loc = 0, max_loc = 0;
int x, loc = 0;
WT minVal = saturate_cast<WT>(*_minVal), maxVal = saturate_cast<WT>(*_maxVal);
size_t minIdx = *_minIdx, maxIdx = *_maxIdx;
Size size = getContinuousSize( srcmat );
for( ; size.height--; src += step, loc += size.width )
for( ; size.height--; src += step, startIdx += size.width )
{
for( x = 0; x < size.width; x++ )
for( int x = 0; x < size.width; x++ )
{
T val = src[x];
if( val < min_val )
if( val < minVal )
{
min_val = val;
min_loc = loc + x;
minVal = val;
minIdx = startIdx + x;
}
else if( val > max_val )
if( val > maxVal )
{
max_val = val;
max_loc = loc + x;
maxVal = val;
maxIdx = startIdx + x;
}
}
}
*minLoc = min_loc;
*maxLoc = max_loc;
*minVal = min_val;
*maxVal = max_val;
*_minIdx = minIdx;
*_maxIdx = maxIdx;
*_minVal = minVal;
*_maxVal = maxVal;
}
template<typename T> static void
template<typename T, typename WT> static void
minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat,
double* minVal, double* maxVal, int* minLoc, int* maxLoc )
double* _minVal, double* _maxVal,
size_t startIdx, size_t* _minIdx, size_t* _maxIdx )
{
assert( DataType<T>::type == srcmat.type() &&
CV_8U == maskmat.type() &&
@@ -654,54 +641,40 @@ minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat,
const uchar* mask = maskmat.data;
size_t step = srcmat.step/sizeof(src[0]);
size_t maskstep = maskmat.step;
T min_val = 0, max_val = 0;
int min_loc = -1, max_loc = -1;
int x = 0, y, loc = 0;
WT minVal = saturate_cast<WT>(*_minVal), maxVal = saturate_cast<WT>(*_maxVal);
size_t minIdx = *_minIdx, maxIdx = *_maxIdx;
Size size = getContinuousSize( srcmat, maskmat );
for( y = 0; y < size.height; y++, src += step, mask += maskstep, loc += size.width )
for( ; size.height--; src += step, mask += maskstep, startIdx += size.width )
{
for( x = 0; x < size.width; x++ )
if( mask[x] != 0 )
{
min_loc = max_loc = loc + x;
min_val = max_val = src[x];
break;
}
if( x < size.width )
break;
}
for( ; y < size.height; x = 0, y++, src += step, mask += maskstep, loc += size.width )
{
for( ; x < size.width; x++ )
for( int x = 0; x < size.width; x++ )
{
T val = src[x];
int m = mask[x];
if( val < min_val && m )
if( val < minVal && m )
{
min_val = val;
min_loc = loc + x;
minVal = val;
minIdx = startIdx + x;
}
else if( val > max_val && m )
if( val > maxVal && m )
{
max_val = val;
max_loc = loc + x;
maxVal = val;
maxIdx = startIdx + x;
}
}
}
*minLoc = min_loc;
*maxLoc = max_loc;
*minVal = min_val;
*maxVal = max_val;
*_minIdx = minIdx;
*_maxIdx = maxIdx;
*_minVal = minVal;
*_maxVal = maxVal;
}
typedef void (*MinMaxIndxFunc)(const Mat&, double*, double*, int*, int*);
typedef void (*MinMaxIndxFunc)(const Mat&, double*, double*, size_t, size_t*, size_t*);
typedef void (*MinMaxIndxMaskFunc)(const Mat&, const Mat&,
double*, double*, int*, int*);
typedef void (*MinMaxIndxMaskFunc)(const Mat&, const Mat&, double*, double*,
size_t, size_t*, size_t*);
void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
Point* minLoc, Point* maxLoc, const Mat& mask )
@@ -709,15 +682,20 @@ void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
CV_Assert(img.dims <= 2);
static MinMaxIndxFunc tab[] =
{minMaxIndx_<uchar>, 0, minMaxIndx_<ushort>, minMaxIndx_<short>,
minMaxIndx_<int>, minMaxIndx_<float>, minMaxIndx_<double>, 0};
{
minMaxIndx_<uchar, int>, 0, minMaxIndx_<ushort, int>, minMaxIndx_<short, int>,
minMaxIndx_<int, int>, minMaxIndx_<float, float>, minMaxIndx_<double, double>, 0
};
static MinMaxIndxMaskFunc tabm[] =
{minMaxIndxMask_<uchar>, 0, minMaxIndxMask_<ushort>, minMaxIndxMask_<short>,
minMaxIndxMask_<int>, minMaxIndxMask_<float>, minMaxIndxMask_<double>, 0};
{
minMaxIndxMask_<uchar, int>, 0, minMaxIndxMask_<ushort, int>, minMaxIndxMask_<short, int>,
minMaxIndxMask_<int, int>, minMaxIndxMask_<float, float>, minMaxIndxMask_<double, double>, 0
};
int depth = img.depth();
double minval=0, maxval=0;
int minloc=0, maxloc=0;
double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX;
double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX;
size_t minidx = 0, maxidx = 0, startidx = 1;
CV_Assert( img.channels() == 1 );
@@ -725,36 +703,41 @@ void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
{
MinMaxIndxFunc func = tab[depth];
CV_Assert( func != 0 );
func( img, &minval, &maxval, &minloc, &maxloc );
func( img, &minval, &maxval, startidx, &minidx, &maxidx );
}
else
{
CV_Assert( img.size() == mask.size() && mask.type() == CV_8U );
MinMaxIndxMaskFunc func = tabm[depth];
CV_Assert( func != 0 );
func( img, mask, &minval, &maxval, &minloc, &maxloc );
func( img, mask, &minval, &maxval, startidx, &minidx, &maxidx );
}
if( minidx == 0 )
minVal = maxVal = 0;
if( minVal )
*minVal = minval;
if( maxVal )
*maxVal = maxval;
if( minLoc )
{
if( minloc >= 0 )
if( minidx > 0 )
{
minLoc->y = minloc/img.cols;
minLoc->x = minloc - minLoc->y*img.cols;
minidx--;
minLoc->y = minidx/img.cols;
minLoc->x = minidx - minLoc->y*img.cols;
}
else
minLoc->x = minLoc->y = -1;
}
if( maxLoc )
{
if( maxloc >= 0 )
if( maxidx > 0 )
{
maxLoc->y = maxloc/img.cols;
maxLoc->x = maxloc - maxLoc->y*img.cols;
maxidx--;
maxLoc->y = maxidx/img.cols;
maxLoc->x = maxidx - maxLoc->y*img.cols;
}
else
maxLoc->x = maxLoc->y = -1;
@@ -764,10 +747,20 @@ void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
static void ofs2idx(const Mat& a, size_t ofs, int* idx)
{
int i, d = a.dims;
for( i = 0; i < d; i++ )
if( ofs > 0 )
{
idx[i] = (int)(ofs / a.step[i]);
ofs %= a.step[i];
ofs--;
for( i = d-1; i >= 0; i-- )
{
int sz = a.size[i];
idx[i] = (int)(ofs % sz);
ofs /= sz;
}
}
else
{
for( i = d-1; i >= 0; i-- )
idx[i] = -1;
}
}
@@ -780,43 +773,60 @@ void minMaxIdx(const Mat& a, double* minVal,
Point minLoc, maxLoc;
minMaxLoc(a, minVal, maxVal, &minLoc, &maxLoc, mask);
if( minIdx )
minIdx[0] = minLoc.x, minIdx[1] = minLoc.y;
minIdx[0] = minLoc.y, minIdx[1] = minLoc.x;
if( maxIdx )
maxIdx[0] = maxLoc.x, maxIdx[1] = maxLoc.y;
maxIdx[0] = maxLoc.y, maxIdx[1] = maxLoc.x;
return;
}
static MinMaxIndxFunc tab[] =
{
minMaxIndx_<uchar, int>, 0, minMaxIndx_<ushort, int>, minMaxIndx_<short, int>,
minMaxIndx_<int, int>, minMaxIndx_<float, float>, minMaxIndx_<double, double>, 0
};
static MinMaxIndxMaskFunc tabm[] =
{
minMaxIndxMask_<uchar, int>, 0, minMaxIndxMask_<ushort, int>, minMaxIndxMask_<short, int>,
minMaxIndxMask_<int, int>, minMaxIndxMask_<float, float>, minMaxIndxMask_<double, double>, 0
};
const Mat* arrays[] = {&a, &mask, 0};
Mat planes[2];
NAryMatIterator it(arrays, planes);
double minval = DBL_MAX, maxval = -DBL_MAX;
size_t minofs = 0, maxofs = 0, esz = a.elemSize();
for( int i = 0; i < it.nplanes; i++, ++it )
int depth = a.depth();
double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX;
double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX;
size_t minidx = 0, maxidx = 0;
size_t startidx = 1, planeSize = planes[0].total();
MinMaxIndxFunc func = 0;
MinMaxIndxMaskFunc mfunc = 0;
if( mask.empty() )
func = tab[depth];
else
mfunc = tabm[depth];
CV_Assert( func != 0 || mfunc != 0 );
for( int i = 0; i < it.nplanes; i++, ++it, startidx += planeSize )
{
double val0 = 0, val1 = 0;
Point pt0, pt1;
minMaxLoc( it.planes[0], &val0, &val1, &pt0, &pt1, it.planes[1] );
if( val0 < minval )
{
minval = val0;
minofs = (it.planes[0].data - a.data) + pt0.x*esz;
}
if( val1 > maxval )
{
maxval = val1;
maxofs = (it.planes[0].data - a.data) + pt1.x*esz;
}
if( func )
func( planes[0], &minval, &maxval, startidx, &minidx, &maxidx );
else
mfunc( planes[0], planes[1], &minval, &maxval, startidx, &minidx, &maxidx );
}
if( minidx == 0 )
minVal = maxVal = 0;
if( minVal )
*minVal = minval;
if( maxVal )
*maxVal = maxval;
if( minIdx )
ofs2idx(a, minofs, minIdx);
ofs2idx(a, minidx, minIdx);
if( maxIdx )
ofs2idx(a, maxofs, maxIdx);
ofs2idx(a, maxidx, maxIdx);
}
/****************************************************************************************\
@@ -922,6 +932,7 @@ static double normMaskBlock_( const Mat& srcmat, const Mat& maskmat )
ST s0 = 0;
WT s = 0;
int y, remaining = BLOCK_SIZE;
int cn = srcmat.channels();
for( y = 0; y < size.height; y++ )
{
@@ -933,21 +944,25 @@ static double normMaskBlock_( const Mat& srcmat, const Mat& maskmat )
int limit = std::min( remaining, size.width - x );
remaining -= limit;
limit += x;
for( ; x <= limit - 4; x += 4 )
int x0 = x;
for( int c = 0; c < cn; c++ )
{
if( mask[x] )
s = update(s, (WT)f(src[x]));
if( mask[x+1] )
s = update(s, (WT)f(src[x+1]));
if( mask[x+2] )
s = update(s, (WT)f(src[x+2]));
if( mask[x+3] )
s = update(s, (WT)f(src[x+3]));
}
for( ; x < limit; x++ )
{
if( mask[x] )
s = update(s, (WT)f(src[x]));
for( x = x0; x <= limit - 4; x += 4 )
{
if( mask[x] )
s = update(s, (WT)f(src[x*cn + c]));
if( mask[x+1] )
s = update(s, (WT)f(src[(x+1)*cn + c]));
if( mask[x+2] )
s = update(s, (WT)f(src[(x+2)*cn + c]));
if( mask[x+3] )
s = update(s, (WT)f(src[(x+3)*cn + c]));
}
for( ; x < limit; x++ )
{
if( mask[x] )
s = update(s, (WT)f(src[x*cn + c]));
}
}
if( remaining == 0 || (x == size.width && y == size.height-1) )
{
@@ -971,27 +986,31 @@ static double normMask_( const Mat& srcmat, const Mat& maskmat )
assert( DataType<T>::depth == srcmat.depth() );
Size size = getContinuousSize( srcmat, maskmat );
ST s = 0;
int cn = srcmat.channels();
for( int y = 0; y < size.height; y++ )
{
const T* src = (const T*)(srcmat.data + srcmat.step*y);
const uchar* mask = maskmat.data + maskmat.step*y;
int x = 0;
for( ; x <= size.width - 4; x += 4 )
for( int c = 0; c < cn; c++ )
{
if( mask[x] )
s = update(s, (ST)f(src[x]));
if( mask[x+1] )
s = update(s, (ST)f(src[x+1]));
if( mask[x+2] )
s = update(s, (ST)f(src[x+2]));
if( mask[x+3] )
s = update(s, (ST)f(src[x+3]));
}
for( ; x < size.width; x++ )
{
if( mask[x] )
s = update(s, (ST)f(src[x]));
int x = 0;
for( ; x <= size.width - 4; x += 4 )
{
if( mask[x] )
s = update(s, (ST)f(src[x*cn + c]));
if( mask[x+1] )
s = update(s, (ST)f(src[(x+1)*cn + c]));
if( mask[x+2] )
s = update(s, (ST)f(src[(x+2)*cn + c]));
if( mask[x+3] )
s = update(s, (ST)f(src[(x+3)*cn + c]));
}
for( ; x < size.width; x++ )
{
if( mask[x] )
s = update(s, (ST)f(src[x*cn + c]));
}
}
}
return s;
@@ -1085,6 +1104,7 @@ static double normDiffMaskBlock_( const Mat& srcmat1, const Mat& srcmat2, const
ST s0 = 0;
WT s = 0;
int y, remaining = BLOCK_SIZE;
int cn = srcmat1.channels();
for( y = 0; y < size.height; y++ )
{
@@ -1097,20 +1117,24 @@ static double normDiffMaskBlock_( const Mat& srcmat1, const Mat& srcmat2, const
int limit = std::min( remaining, size.width - x );
remaining -= limit;
limit += x;
for( ; x <= limit - 4; x += 4 )
int x0 = x;
for( int c = 0; c < cn; c++ )
{
if( mask[x] )
s = update(s, (WT)f(src1[x] - src2[x]));
if( mask[x+1] )
s = update(s, (WT)f(src1[x+1] - src2[x+1]));
if( mask[x+2] )
s = update(s, (WT)f(src1[x+2] - src2[x+2]));
if( mask[x+3] )
s = update(s, (WT)f(src1[x+3] - src2[x+3]));
for( x = x0; x <= limit - 4; x += 4 )
{
if( mask[x] )
s = update(s, (WT)f(src1[x*cn + c] - src2[x*cn + c]));
if( mask[x+1] )
s = update(s, (WT)f(src1[(x+1)*cn + c] - src2[(x+1)*cn + c]));
if( mask[x+2] )
s = update(s, (WT)f(src1[(x+2)*cn + c] - src2[(x+2)*cn + c]));
if( mask[x+3] )
s = update(s, (WT)f(src1[(x+3)*cn + c] - src2[(x+3)*cn + c]));
}
for( ; x < limit; x++ )
if( mask[x] )
s = update(s, (WT)f(src1[x*cn + c] - src2[x*cn + c]));
}
for( ; x < limit; x++ )
if( mask[x] )
s = update(s, (WT)f(src1[x] - src2[x]));
if( remaining == 0 || (x == size.width && y == size.height-1) )
{
s0 = globUpdate(s0, (ST)s);
@@ -1132,28 +1156,31 @@ static double normDiffMask_( const Mat& srcmat1, const Mat& srcmat2, const Mat&
assert( DataType<T>::depth == srcmat1.depth() );
Size size = getContinuousSize( srcmat1, srcmat2, maskmat );
ST s = 0;
int cn = srcmat1.channels();
for( int y = 0; y < size.height; y++ )
{
const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y);
const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y);
const uchar* mask = maskmat.data + maskmat.step*y;
int x = 0;
for( ; x <= size.width - 4; x += 4 )
for( int c = 0; c < cn; c++ )
{
if( mask[x] )
s = update(s, (ST)f(src1[x] - src2[x]));
if( mask[x+1] )
s = update(s, (ST)f(src1[x+1] - src2[x+1]));
if( mask[x+2] )
s = update(s, (ST)f(src1[x+2] - src2[x+2]));
if( mask[x+3] )
s = update(s, (ST)f(src1[x+3] - src2[x+3]));
int x = 0;
for( ; x <= size.width - 4; x += 4 )
{
if( mask[x] )
s = update(s, (ST)f(src1[x*cn + c] - src2[x*cn + c]));
if( mask[x+1] )
s = update(s, (ST)f(src1[(x+1)*cn + c] - src2[(x+1)*cn + c]));
if( mask[x+2] )
s = update(s, (ST)f(src1[(x+2)*cn + c] - src2[(x+2)*cn + c]));
if( mask[x+3] )
s = update(s, (ST)f(src1[(x+3)*cn + c] - src2[(x+3)*cn + c]));
}
for( ; x < size.width; x++ )
if( mask[x] )
s = update(s, (ST)f(src1[x*cn + c] - src2[x*cn + c]));
}
for( ; x < size.width; x++ )
if( mask[x] )
s = update(s, (ST)f(src1[x] - src2[x]));
}
return s;
}
@@ -1265,8 +1292,7 @@ double norm( const Mat& a, int normType, const Mat& mask )
return norm(a, normType);
normType &= 7;
CV_Assert((normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) &&
mask.type() == CV_8U && a.channels() == 1);
CV_Assert((normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) && mask.type() == CV_8U);
NormMaskFunc func = tab[normType >> 1][a.depth()];
CV_Assert(func != 0);
@@ -1405,7 +1431,7 @@ double norm( const Mat& a, const Mat& b, int normType, const Mat& mask )
if( !mask.data )
return norm(a, b, normType);
CV_Assert( a.type() == b.type() && mask.type() == CV_8U && a.channels() == 1);
CV_Assert( a.type() == b.type() && mask.type() == CV_8U);
bool isRelative = (normType & NORM_RELATIVE) != 0;
normType &= 7;
CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2);

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(); }