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

@@ -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);