Commit d2c2c07a authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

updated the new arithmetic tests

parent 57f917d6
#include "precomp.hpp" #include "precomp.hpp"
#include <iostream>
using namespace cv; using namespace cv;
using namespace std;
const int ARITHM_NTESTS = 1000;
const int ARITHM_RNG_SEED = -1;
const int ARITHM_MAX_NDIMS = 4;
const int ARITHM_MAX_SIZE_LOG = 10;
const int ARITHM_MAX_CHANNELS = 4;
static void getArithmValueRange(int depth, double& minval, double& maxval)
{
minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
maxval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? 1000000 : 1000.;
}
static double getArithmMaxErr(int depth)
{
return depth < CV_32F ? 0 : 4;
}
TEST(ArithmTest, add) TEST(ArithmTest, add)
{ {
typedef uchar _Tp; int testIdx = 0;
RNG rng(ARITHM_RNG_SEED);
for( testIdx = 0; testIdx < ARITHM_NTESTS; testIdx++ )
{
double minval, maxval;
vector<int> size;
cvtest::randomSize(rng, 2, ARITHM_MAX_NDIMS, ARITHM_MAX_SIZE_LOG, size);
int type = cvtest::randomType(rng, cvtest::TYPE_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
int depth = CV_MAT_DEPTH(type);
bool haveMask = rng.uniform(0, 4) == 0;
Mat A(30,30,DataType<_Tp>::type), B(A.size(), A.type()), C0, C; getArithmValueRange(depth, minval, maxval);
RNG rng(-1); Mat src1 = cvtest::randomMat(rng, size, type, minval, maxval, true);
rng.fill(A, RNG::UNIFORM, Scalar::all(0), Scalar::all(256)); Mat src2 = cvtest::randomMat(rng, size, type, minval, maxval, true);
rng.fill(B, RNG::UNIFORM, Scalar::all(0), Scalar::all(256)); Mat dst0 = cvtest::randomMat(rng, size, type, minval, maxval, false);
C0.create(A.size(), A.type()); Mat dst = cvtest::randomMat(rng, size, type, minval, maxval, true);
int i, j, cols = A.cols*A.channels(); Mat mask;
for(i = 0; i < A.rows; i++) if( haveMask )
{
mask = cvtest::randomMat(rng, size, CV_8U, 0, 2, true);
cvtest::copy(dst0, dst);
cvtest::add(src1, 1, src2, 1, Scalar::all(0), dst0, dst.type());
cvtest::copy(dst, dst0, mask, true);
add(src1, src2, dst, mask);
}
else
{ {
const _Tp* aptr = A.ptr<_Tp>(i); cvtest::add(src1, 1, src2, 1, Scalar::all(0), dst0, dst.type());
const _Tp* bptr = B.ptr<_Tp>(i); add(src1, src2, dst);
_Tp* cptr = C0.ptr<_Tp>(i); }
for(j = 0; j < cols; j++)
cptr[j] = saturate_cast<_Tp>(aptr[j] + bptr[j]); double maxErr = getArithmMaxErr(depth);
vector<int> pos;
ASSERT_TRUE(cvtest::cmpEps(dst0, dst, maxErr, &pos)) << "position: " << Mat(pos);
} }
add(A, B, C);
EXPECT_EQ(norm(C, C0, NORM_INF), 0);
} }
...@@ -28,28 +28,37 @@ enum ...@@ -28,28 +28,37 @@ enum
TYPE_MASK_ALL_BUT_8S = TYPE_MASK_ALL & ~TYPE_MASK_8S TYPE_MASK_ALL_BUT_8S = TYPE_MASK_ALL & ~TYPE_MASK_8S
}; };
CV_EXPORTS double getMinVal(int depth);
CV_EXPORTS double getMaxVal(int depth);
CV_EXPORTS Size randomSize(RNG& rng, double maxSizeLog); CV_EXPORTS Size randomSize(RNG& rng, double maxSizeLog);
CV_EXPORTS void randomSize(RNG& rng, int minDims, int maxDims, double maxSizeLog, vector<int>& sz); CV_EXPORTS void randomSize(RNG& rng, int minDims, int maxDims, double maxSizeLog, vector<int>& sz);
CV_EXPORTS int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels); CV_EXPORTS int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels);
CV_EXPORTS Mat randomMat(RNG& rng, Size size, int type, bool useRoi); CV_EXPORTS Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool useRoi);
CV_EXPORTS Mat randomMat(RNG& rng, const vector<int>& size, int type, bool useRoi); CV_EXPORTS Mat randomMat(RNG& rng, const vector<int>& size, int type, double minVal, double maxVal, bool useRoi);
CV_EXPORTS void add(const Mat& a, double alpha, const Mat& b, double beta, CV_EXPORTS void add(const Mat& a, double alpha, const Mat& b, double beta,
Scalar gamma, Mat& c, int ctype, bool calcAbs); Scalar gamma, Mat& c, int ctype, bool calcAbs=false);
CV_EXPORTS void convert(const Mat& src, Mat& dst, int dtype, double alpha, double beta); CV_EXPORTS void convert(const Mat& src, Mat& dst, int dtype, double alpha=1, double beta=0);
CV_EXPORTS void copy(const Mat& src, Mat& dst, const Mat& mask=Mat()); CV_EXPORTS void copy(const Mat& src, Mat& dst, const Mat& mask=Mat(), bool invertMask=false);
CV_EXPORTS void set(Mat& dst, const Scalar& gamma, const Mat& mask=Mat()); CV_EXPORTS void set(Mat& dst, const Scalar& gamma, const Mat& mask=Mat());
CV_EXPORTS void minMaxFilter(const Mat& a, Mat& maxresult, const Mat& minresult, const Mat& kernel, Point anchor); CV_EXPORTS void erode(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
CV_EXPORTS void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel, Point anchor, double delta, int borderType); int borderType=IPL_BORDER_CONSTANT, const Scalar& borderValue=Scalar());
CV_EXPORTS void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int borderType, Scalar borderValue); CV_EXPORTS void dilate(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
int borderType=IPL_BORDER_CONSTANT, const Scalar& borderValue=Scalar());
CV_EXPORTS void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel,
Point anchor, double delta, int borderType,
const Scalar& borderValue=Scalar());
CV_EXPORTS void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right,
int borderType, const Scalar& borderValue=Scalar());
CV_EXPORTS void minMaxLoc(const Mat& src, double* maxval, double* minval, CV_EXPORTS void minMaxLoc(const Mat& src, double* maxval, double* minval,
vector<int>* maxloc, vector<int>* minloc, const Mat& mask=Mat()); vector<int>* maxloc, vector<int>* minloc, const Mat& mask=Mat());
CV_EXPORTS double norm(const Mat& src, int normType, const Mat& mask=Mat()); CV_EXPORTS double norm(const Mat& src, int normType, const Mat& mask=Mat());
CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask=Mat()); CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask=Mat());
CV_EXPORTS bool cmpEps(const Mat& src1, const Mat& src2, double maxDiff, vector<int>* loc); CV_EXPORTS bool cmpEps(const Mat& src1, const Mat& src2, int maxDiff, vector<int>* loc);
CV_EXPORTS void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c); CV_EXPORTS void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c);
CV_EXPORTS void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c); CV_EXPORTS void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c);
CV_EXPORTS void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop); CV_EXPORTS void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop);
CV_EXPORTS void compare(const Mat& src, const Scalar& s, Mat& dst, int cmpop); CV_EXPORTS void compare(const Mat& src, double s, Mat& dst, int cmpop);
CV_EXPORTS void gemm(const Mat& src1, const Mat& src2, double alpha, CV_EXPORTS void gemm(const Mat& src1, const Mat& src2, double alpha,
const Mat& src3, double beta, Mat& dst, int flags); const Mat& src3, double beta, Mat& dst, int flags);
CV_EXPORTS void crosscorr(const Mat& src1, const Mat& src2, Mat& dst, int dtype); CV_EXPORTS void crosscorr(const Mat& src1, const Mat& src2, Mat& dst, int dtype);
......
#include "precomp.hpp" #include "precomp.hpp"
#include <float.h>
#include <limits.h>
using namespace cv; using namespace cv;
...@@ -49,14 +51,65 @@ int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels) ...@@ -49,14 +51,65 @@ int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels)
return CV_MAKETYPE(depth, channels); return CV_MAKETYPE(depth, channels);
} }
Mat randomMat(RNG& rng, Size size, int type, bool useRoi) double getMinVal(int depth)
{ {
return Mat(); double val = depth == CV_8U ? 0 : depth == CV_8S ? SCHAR_MIN : depth == CV_16U ? 0 :
depth == CV_16S ? SHRT_MIN : depth == CV_32S ? INT_MIN :
depth == CV_32F ? -FLT_MAX : depth == CV_64F ? -DBL_MAX : -1;
CV_Assert(val != -1);
return val;
} }
Mat randomMat(RNG& rng, const vector<int>& size, int type, bool useRoi) double getMaxVal(int depth)
{ {
return Mat(); double val = depth == CV_8U ? UCHAR_MAX : depth == CV_8S ? SCHAR_MAX : depth == CV_16U ? USHRT_MAX :
depth == CV_16S ? SHRT_MAX : depth == CV_32S ? INT_MAX :
depth == CV_32F ? FLT_MAX : depth == CV_64F ? DBL_MAX : -1;
CV_Assert(val != -1);
return val;
}
Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool useRoi)
{
Size size0 = size;
if( useRoi )
{
size0.width += std::max(rng.uniform(0, 10) - 5, 0);
size0.height += std::max(rng.uniform(0, 10) - 5, 0);
}
Mat m(size0, type);
rng.fill(m, RNG::UNIFORM, Scalar::all(minVal), Scalar::all(maxVal));
if( size0 == size )
return m;
return m(Rect((size0.width-size.width)/2, (size0.height-size.height)/2, size.width, size.height));
}
Mat randomMat(RNG& rng, const vector<int>& size, int type, double minVal, double maxVal, bool useRoi)
{
int i, dims = (int)size.size();
vector<int> size0(dims);
vector<Range> r(dims);
bool eqsize = true;
for( i = 0; i < dims; i++ )
{
size0[i] = size[i];
r[i] = Range::all();
if( useRoi )
{
size0[i] += std::max(rng.uniform(0, 5) - 2, 0);
r[i] = Range((size0[i] - size[i])/2, (size0[i] - size[i])/2 + size[i]);
}
eqsize = eqsize && size[i] == size0[i];
}
Mat m(dims, &size0[0], type);
rng.fill(m, RNG::UNIFORM, Scalar::all(minVal), Scalar::all(maxVal));
if( eqsize )
return m;
return m(&r[0]);
} }
void add(const Mat& _a, double alpha, const Mat& _b, double beta, void add(const Mat& _a, double alpha, const Mat& _b, double beta,
...@@ -244,7 +297,7 @@ void convert(const Mat& src, Mat& dst, int dtype, double alpha, double beta) ...@@ -244,7 +297,7 @@ void convert(const Mat& src, Mat& dst, int dtype, double alpha, double beta)
} }
void copy(const Mat& src, Mat& dst, const Mat& mask) void copy(const Mat& src, Mat& dst, const Mat& mask, bool invertMask)
{ {
dst.create(src.dims, &src.size[0], src.type()); dst.create(src.dims, &src.size[0], src.type());
...@@ -279,7 +332,7 @@ void copy(const Mat& src, Mat& dst, const Mat& mask) ...@@ -279,7 +332,7 @@ void copy(const Mat& src, Mat& dst, const Mat& mask)
for( j = 0; j < total; j++, sptr += elemSize, dptr += elemSize ) for( j = 0; j < total; j++, sptr += elemSize, dptr += elemSize )
{ {
if( mptr[j] ) if( (mptr[j] != 0) ^ invertMask )
for( k = 0; k < elemSize; k++ ) for( k = 0; k < elemSize; k++ )
dptr[k] = sptr[k]; dptr[k] = sptr[k];
} }
...@@ -347,17 +400,1044 @@ void set(Mat& dst, const Scalar& gamma, const Mat& mask) ...@@ -347,17 +400,1044 @@ void set(Mat& dst, const Scalar& gamma, const Mat& mask)
} }
/*void minMaxFilter(const Mat& a, Mat& maxresult, const Mat& minresult, const Mat& kernel, Point anchor); template<typename _Tp> static void
void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel, Point anchor, double delta, int borderType); erode_(const Mat& src, Mat& dst, const vector<int>& ofsvec)
void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int borderType, Scalar borderValue); {
void minMaxLoc(const Mat& src, double* maxval, double* minval, int width = src.cols*src.channels(), n = (int)ofsvec.size();
vector<int>* maxloc, vector<int>* minloc, const Mat& mask=Mat()); const int* ofs = &ofsvec[0];
double norm(const Mat& src, int normType, const Mat& mask=Mat());
double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask=Mat()); for( int y = 0; y < dst.rows; y++ )
bool cmpEps(const Mat& src1, const Mat& src2, int int_maxdiff, int flt_maxulp, vector<int>* loc); {
void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c); const _Tp* sptr = src.ptr<_Tp>(y);
void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c); _Tp* dptr = dst.ptr<_Tp>(y);
void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop);
void compare(const Mat& src, const Scalar& s, Mat& dst, int cmpop);*/ for( int x = 0; x < width; x++ )
{
_Tp result = sptr[x + ofs[0]];
for( int i = 1; i < n; i++ )
result = std::min(result, sptr[x + ofs[i]]);
dptr[x] = result;
}
}
}
template<typename _Tp> static void
dilate_(const Mat& src, Mat& dst, const vector<int>& ofsvec)
{
int width = src.cols*src.channels(), n = (int)ofsvec.size();
const int* ofs = &ofsvec[0];
for( int y = 0; y < dst.rows; y++ )
{
const _Tp* sptr = src.ptr<_Tp>(y);
_Tp* dptr = dst.ptr<_Tp>(y);
for( int x = 0; x < width; x++ )
{
_Tp result = sptr[x + ofs[0]];
for( int i = 1; i < n; i++ )
result = std::max(result, sptr[x + ofs[i]]);
dptr[x] = result;
}
}
}
void erode(const Mat& _src, Mat& dst, const Mat& _kernel, Point anchor,
int borderType, const Scalar& _borderValue)
{
Mat kernel = _kernel, src;
Scalar borderValue = _borderValue;
if( kernel.empty() )
kernel = Mat::ones(3, 3, CV_8U);
else
{
CV_Assert( kernel.type() == CV_8U );
}
if( anchor == Point(-1,-1) )
anchor = Point(kernel.cols/2, kernel.rows/2);
if( borderType == IPL_BORDER_CONSTANT )
borderValue = getMaxVal(src.depth());
copyMakeBorder(_src, src, anchor.y, kernel.rows - anchor.y - 1,
anchor.x, kernel.cols - anchor.y - 1,
borderType, borderValue);
dst.create( _src.size(), src.type() );
vector<int> ofs;
int step = (int)(src.step/src.elemSize1()), cn = src.channels();
for( int i = 0; i < kernel.rows; i++ )
for( int j = 0; j < kernel.cols; j++ )
if( kernel.at<uchar>(i, j) != 0 )
ofs.push_back(i*step + j*cn);
if( ofs.empty() )
ofs.push_back(anchor.y*step + anchor.x*cn);
switch( src.depth() )
{
case CV_8U:
erode_<uchar>(src, dst, ofs);
break;
case CV_8S:
erode_<schar>(src, dst, ofs);
break;
case CV_16U:
erode_<ushort>(src, dst, ofs);
break;
case CV_16S:
erode_<short>(src, dst, ofs);
break;
case CV_32S:
erode_<int>(src, dst, ofs);
break;
case CV_32F:
erode_<float>(src, dst, ofs);
break;
case CV_64F:
erode_<double>(src, dst, ofs);
break;
default:
CV_Assert(0);
}
}
void dilate(const Mat& _src, Mat& dst, const Mat& _kernel, Point anchor,
int borderType, const Scalar& _borderValue)
{
Mat kernel = _kernel, src;
Scalar borderValue = _borderValue;
if( kernel.empty() )
kernel = Mat::ones(3, 3, CV_8U);
else
{
CV_Assert( kernel.type() == CV_8U );
}
if( anchor == Point(-1,-1) )
anchor = Point(kernel.cols/2, kernel.rows/2);
if( borderType == IPL_BORDER_CONSTANT )
borderValue = getMinVal(src.depth());
copyMakeBorder(_src, src, anchor.y, kernel.rows - anchor.y - 1,
anchor.x, kernel.cols - anchor.y - 1,
borderType, borderValue);
dst.create( _src.size(), src.type() );
vector<int> ofs;
int step = (int)(src.step/src.elemSize1()), cn = src.channels();
for( int i = 0; i < kernel.rows; i++ )
for( int j = 0; j < kernel.cols; j++ )
if( kernel.at<uchar>(i, j) != 0 )
ofs.push_back(i*step + j*cn);
if( ofs.empty() )
ofs.push_back(anchor.y*step + anchor.x*cn);
switch( src.depth() )
{
case CV_8U:
dilate_<uchar>(src, dst, ofs);
break;
case CV_8S:
dilate_<schar>(src, dst, ofs);
break;
case CV_16U:
dilate_<ushort>(src, dst, ofs);
break;
case CV_16S:
dilate_<short>(src, dst, ofs);
break;
case CV_32S:
dilate_<int>(src, dst, ofs);
break;
case CV_32F:
dilate_<float>(src, dst, ofs);
break;
case CV_64F:
dilate_<double>(src, dst, ofs);
break;
default:
CV_Assert(0);
}
}
template<typename _Tp> static void
filter2D_(const Mat& src, Mat& dst, const vector<int>& ofsvec, const vector<double>& coeffvec)
{
const int* ofs = &ofsvec[0];
const double* coeff = &coeffvec[0];
int width = dst.cols*dst.channels(), ncoeffs = (int)ofsvec.size();
for( int y = 0; y < dst.rows; y++ )
{
const _Tp* sptr = src.ptr<_Tp>(y);
double* dptr = dst.ptr<double>(y);
for( int x = 0; x < width; x++ )
{
double s = 0;
for( int i = 0; i < ncoeffs; i++ )
s += sptr[ofs[i]]*coeff[i];
dptr[x] = s;
}
}
}
void filter2D(const Mat& _src, Mat& dst, int ddepth, const Mat& _kernel,
Point anchor, double delta, int borderType, const Scalar& _borderValue)
{
Mat kernel = _kernel, src, _dst;
Scalar borderValue = _borderValue;
CV_Assert( kernel.type() == CV_32F || kernel.type() == CV_64F );
if( anchor == Point(-1,-1) )
anchor = Point(kernel.cols/2, kernel.rows/2);
if( borderType == IPL_BORDER_CONSTANT )
borderValue = getMinVal(src.depth());
copyMakeBorder(_src, src, anchor.y, kernel.rows - anchor.y - 1,
anchor.x, kernel.cols - anchor.y - 1,
borderType, borderValue);
_dst.create( _src.size(), CV_MAKETYPE(CV_64F, src.channels()) );
vector<int> ofs;
vector<double> coeff(kernel.rows*kernel.cols);
Mat cmat(kernel.rows, kernel.cols, CV_64F, &coeff[0]);
convert(kernel, cmat, cmat.type());
int step = (int)(src.step/src.elemSize1()), cn = src.channels();
for( int i = 0; i < kernel.rows; i++ )
for( int j = 0; j < kernel.cols; j++ )
ofs.push_back(i*step + j*cn);
switch( src.depth() )
{
case CV_8U:
filter2D_<uchar>(src, _dst, ofs, coeff);
break;
case CV_8S:
filter2D_<schar>(src, _dst, ofs, coeff);
break;
case CV_16U:
filter2D_<ushort>(src, _dst, ofs, coeff);
break;
case CV_16S:
filter2D_<short>(src, _dst, ofs, coeff);
break;
case CV_32S:
filter2D_<int>(src, _dst, ofs, coeff);
break;
case CV_32F:
filter2D_<float>(src, _dst, ofs, coeff);
break;
case CV_64F:
filter2D_<double>(src, _dst, ofs, coeff);
break;
default:
CV_Assert(0);
}
convert(_dst, dst, ddepth, 1, delta);
}
static int borderInterpolate( int p, int len, int borderType )
{
if( (unsigned)p < (unsigned)len )
;
else if( borderType == IPL_BORDER_REPLICATE )
p = p < 0 ? 0 : len - 1;
else if( borderType == IPL_BORDER_REFLECT || borderType == IPL_BORDER_REFLECT_101 )
{
int delta = borderType == IPL_BORDER_REFLECT_101;
if( len == 1 )
return 0;
do
{
if( p < 0 )
p = -p - 1 + delta;
else
p = len - 1 - (p - len) - delta;
}
while( (unsigned)p >= (unsigned)len );
}
else if( borderType == IPL_BORDER_WRAP )
{
if( p < 0 )
p -= ((p-len+1)/len)*len;
if( p >= len )
p %= len;
}
else if( borderType == IPL_BORDER_CONSTANT )
p = -1;
else
CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
return p;
}
void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right,
int borderType, const Scalar& borderValue)
{
dst.create(src.rows + top + bottom, src.cols + left + right, src.type());
int i, j, k, esz = (int)src.elemSize();
int width = src.cols*esz, width1 = dst.cols*esz;
if( borderType == IPL_BORDER_CONSTANT )
{
vector<uchar> valvec((src.cols + left + right)*esz);
uchar* val = &valvec[0];
scalarToRawData(borderValue, val, src.type(), (src.cols + left + right)*src.channels());
left *= esz;
right *= esz;
for( i = 0; i < src.rows; i++ )
{
const uchar* sptr = src.ptr(i);
uchar* dptr = dst.ptr(i + top) + left;
for( j = 0; j < left; j++ )
dptr[j - left] = val[j];
if( dptr != sptr )
for( j = 0; j < width; j++ )
dptr[j] = sptr[j];
for( j = 0; j < right; j++ )
dptr[j + width] = val[j];
}
for( i = 0; i < top; i++ )
{
uchar* dptr = dst.ptr(i);
for( j = 0; j < width1; j++ )
dptr[j] = val[j];
}
for( i = 0; i < bottom; i++ )
{
uchar* dptr = dst.ptr(i + top + src.rows);
for( j = 0; j < width1; j++ )
dptr[j] = val[j];
}
}
else
{
vector<int> tabvec((left + right)*esz);
int* ltab = &tabvec[0];
int* rtab = &tabvec[left*esz];
for( i = 0; i < left; i++ )
{
j = borderInterpolate(i - left, src.cols, borderType)*esz;
for( k = 0; k < esz; k++ )
ltab[i*esz + k] = j + k;
}
for( i = 0; i < right; i++ )
{
j = borderInterpolate(src.cols + i, src.cols, borderType)*esz;
for( k = 0; k < esz; k++ )
rtab[i*esz + k] = j + k;
}
left *= esz;
right *= esz;
for( i = 0; i < src.rows; i++ )
{
const uchar* sptr = src.ptr(i);
uchar* dptr = dst.ptr(i + top);
for( j = 0; j < left; j++ )
dptr[j] = sptr[ltab[j]];
if( dptr + left != sptr )
{
for( j = 0; j < width; j++ )
dptr[j + left] = sptr[j];
}
for( j = 0; j < right; j++ )
dptr[j + left + width] = sptr[rtab[j]];
}
for( i = 0; i < top; i++ )
{
j = borderInterpolate(i - top, src.rows, borderType);
const uchar* sptr = dst.ptr(j + top);
uchar* dptr = dst.ptr(i);
for( k = 0; k < width1; k++ )
dptr[k] = sptr[k];
}
for( i = 0; i < bottom; i++ )
{
j = borderInterpolate(i + src.rows, src.rows, borderType);
const uchar* sptr = dst.ptr(j + top);
uchar* dptr = dst.ptr(i + top + src.rows);
for( k = 0; k < width1; k++ )
dptr[k] = sptr[k];
}
}
}
template<typename _Tp> static void
minMaxLoc_(const _Tp* src, size_t total, size_t startidx,
double* _maxval, double* _minval,
size_t* _minpos, size_t* _maxpos,
const uchar* mask)
{
_Tp maxval = saturate_cast<_Tp>(*_maxval), minval = saturate_cast<_Tp>(*_minval);
size_t minpos = *_minpos, maxpos = *_maxpos;
if( !mask )
{
for( size_t i = 0; i < total; i++ )
{
_Tp val = src[i];
if( minval > val )
{
minval = val;
minpos = startidx + i;
}
if( maxval < val )
{
maxval = val;
maxpos = startidx + i;
}
}
}
else
{
for( size_t i = 0; i < total; i++ )
{
_Tp val = src[i];
if( minval > val && mask[i] )
{
minval = val;
minpos = startidx + i;
}
if( maxval < val && mask[i] )
{
maxval = val;
maxpos = startidx + i;
}
}
}
*_maxval = maxval;
*_minval = minval;
*_maxpos = maxpos;
*_minpos = minpos;
}
static void setpos( const Mat& mtx, vector<int>& pos, size_t idx )
{
pos.resize(mtx.dims);
for( int i = mtx.dims-1; i >= 0; i-- )
{
int sz = mtx.size[i]*(i == mtx.dims-1 ? mtx.channels() : 1);
pos[i] = idx % sz;
idx /= sz;
}
}
void minMaxLoc(const Mat& src, double* _maxval, double* _minval,
vector<int>* _maxloc, vector<int>* _minloc,
const Mat& mask)
{
CV_Assert( src.channels() == 1 );
const Mat *arrays[2]={&src, &mask};
Mat planes[2];
NAryMatIterator it(arrays, planes, 2);
size_t startidx = 1, total = planes[0].total();
int i, nplanes = it.nplanes, depth = src.depth();
double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX;
double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX;
size_t maxidx = 0, minidx = 0;
for( i = 0; i < nplanes; i++, ++it, startidx += total )
{
const uchar* sptr = planes[0].data;
const uchar* mptr = planes[1].data;
switch( depth )
{
case CV_8U:
minMaxLoc_((const uchar*)sptr, total, startidx,
&maxval, &minval, &maxidx, &minidx, mptr);
break;
case CV_8S:
minMaxLoc_((const schar*)sptr, total, startidx,
&maxval, &minval, &maxidx, &minidx, mptr);
break;
case CV_16U:
minMaxLoc_((const ushort*)sptr, total, startidx,
&maxval, &minval, &maxidx, &minidx, mptr);
break;
case CV_16S:
minMaxLoc_((const short*)sptr, total, startidx,
&maxval, &minval, &maxidx, &minidx, mptr);
break;
case CV_32S:
minMaxLoc_((const int*)sptr, total, startidx,
&maxval, &minval, &maxidx, &minidx, mptr);
break;
case CV_32F:
minMaxLoc_((const float*)sptr, total, startidx,
&maxval, &minval, &maxidx, &minidx, mptr);
break;
case CV_64F:
minMaxLoc_((const double*)sptr, total, startidx,
&maxval, &minval, &maxidx, &minidx, mptr);
break;
default:
CV_Assert(0);
}
}
if( _maxval )
*_maxval = maxval;
if( _minval )
*_minval = minval;
if( _maxloc )
setpos( src, *_maxloc, maxidx );
if( _minloc )
setpos( src, *_minloc, minidx );
}
template<typename _Tp> static double
norm_(const _Tp* src, size_t total, int normType, double startval, const uchar* mask)
{
size_t i;
double result = startval;
if( normType == NORM_INF )
{
if( !mask )
for( i = 0; i < total; i++ )
result = std::max(result, (double)std::abs(src[i]));
else
for( i = 0; i < total; i++ )
if( mask[i] )
result = std::max(result, (double)std::abs(src[i]));
}
else if( normType == NORM_L1 )
{
if( !mask )
for( i = 0; i < total; i++ )
result += std::abs(src[i]);
else
for( i = 0; i < total; i++ )
if( mask[i] )
result += std::abs(src[i]);
}
else
{
if( !mask )
for( i = 0; i < total; i++ )
{
double v = src[i];
result += v*v;
}
else
for( i = 0; i < total; i++ )
if( mask[i] )
{
double v = src[i];
result += v*v;
}
}
return result;
}
template<typename _Tp> static double
norm_(const _Tp* src1, const _Tp* src2, size_t total, int normType, double startval, const uchar* mask)
{
size_t i;
double result = startval;
if( normType == NORM_INF )
{
if( !mask )
for( i = 0; i < total; i++ )
result = std::max(result, (double)std::abs(src1[i] - src2[i]));
else
for( i = 0; i < total; i++ )
if( mask[i] )
result = std::max(result, (double)std::abs(src1[i] - src2[i]));
}
else if( normType == NORM_L1 )
{
if( !mask )
for( i = 0; i < total; i++ )
result += std::abs(src1[i] - src2[i]);
else
for( i = 0; i < total; i++ )
if( mask[i] )
result += std::abs(src1[i] - src2[i]);
}
else
{
if( !mask )
for( i = 0; i < total; i++ )
{
double v = src1[i] - src2[i];
result += v*v;
}
else
for( i = 0; i < total; i++ )
if( mask[i] )
{
double v = src1[i] - src2[i];
result += v*v;
}
}
return result;
}
double norm(const Mat& src, int normType, const Mat& mask)
{
CV_Assert( mask.empty() || (src.size == mask.size && mask.type() == CV_8U) );
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
const Mat *arrays[2]={&src, &mask};
Mat planes[2];
NAryMatIterator it(arrays, planes, 2);
size_t total = planes[0].total()*planes[0].channels();
int i, nplanes = it.nplanes, depth = src.depth();
double result = 0;
for( i = 0; i < nplanes; i++, ++it )
{
const uchar* sptr = planes[0].data;
const uchar* mptr = planes[1].data;
switch( depth )
{
case CV_8U:
result = norm_((const uchar*)sptr, total, normType, result, mptr);
break;
case CV_8S:
result = norm_((const schar*)sptr, total, normType, result, mptr);
break;
case CV_16U:
result = norm_((const ushort*)sptr, total, normType, result, mptr);
break;
case CV_16S:
result = norm_((const short*)sptr, total, normType, result, mptr);
break;
case CV_32S:
result = norm_((const int*)sptr, total, normType, result, mptr);
break;
case CV_32F:
result = norm_((const float*)sptr, total, normType, result, mptr);
break;
case CV_64F:
result = norm_((const double*)sptr, total, normType, result, mptr);
break;
default:
CV_Error(CV_StsUnsupportedFormat, "");
};
}
if( normType == NORM_L2 )
result = sqrt(result);
return result;
}
double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask)
{
CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
CV_Assert( mask.empty() || (src1.size == mask.size && mask.type() == CV_8U) );
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
const Mat *arrays[3]={&src1, &src2, &mask};
Mat planes[3];
NAryMatIterator it(arrays, planes, 3);
size_t total = planes[0].total()*planes[0].channels();
int i, nplanes = it.nplanes, depth = src1.depth();
double result = 0;
for( i = 0; i < nplanes; i++, ++it )
{
const uchar* sptr1 = planes[0].data;
const uchar* sptr2 = planes[1].data;
const uchar* mptr = planes[2].data;
switch( depth )
{
case CV_8U:
result = norm_((const uchar*)sptr1, (const uchar*)sptr2, total, normType, result, mptr);
break;
case CV_8S:
result = norm_((const schar*)sptr1, (const schar*)sptr2, total, normType, result, mptr);
break;
case CV_16U:
result = norm_((const ushort*)sptr1, (const ushort*)sptr2, total, normType, result, mptr);
break;
case CV_16S:
result = norm_((const short*)sptr1, (const short*)sptr2, total, normType, result, mptr);
break;
case CV_32S:
result = norm_((const int*)sptr1, (const int*)sptr2, total, normType, result, mptr);
break;
case CV_32F:
result = norm_((const float*)sptr1, (const float*)sptr2, total, normType, result, mptr);
break;
case CV_64F:
result = norm_((const double*)sptr1, (const double*)sptr2, total, normType, result, mptr);
break;
default:
CV_Error(CV_StsUnsupportedFormat, "");
};
}
if( normType == NORM_L2 )
result = sqrt(result);
return result;
}
bool cmpEps(const Mat& src1, const Mat& src2, int int_maxdiff, int flt_maxulp, vector<int>* loc);
static void
logicOp_(const uchar* src1, const uchar* src2, uchar* dst, size_t total, char c)
{
size_t i;
if( c == '&' )
for( i = 0; i < total; i++ )
dst[i] = src1[i] & src2[i];
else if( c == '|' )
for( i = 0; i < total; i++ )
dst[i] = src1[i] | src2[i];
else
for( i = 0; i < total; i++ )
dst[i] = src1[i] ^ src2[i];
}
static void
logicOpS_(const uchar* src, const uchar* scalar, uchar* dst, size_t total, char c)
{
const size_t blockSize = 96;
size_t i, j;
if( c == '&' )
for( i = 0; i < total; i += blockSize, dst += blockSize, src += blockSize )
{
size_t sz = std::min(total - i, blockSize);
for( j = 0; j < sz; j++ )
dst[j] = src[j] & scalar[j];
}
else if( c == '|' )
for( i = 0; i < total; i += blockSize, dst += blockSize, src += blockSize )
{
size_t sz = std::min(total - i, blockSize);
for( j = 0; j < sz; j++ )
dst[j] = src[j] | scalar[j];
}
else if( c == '^' )
{
for( i = 0; i < total; i += blockSize, dst += blockSize, src += blockSize )
{
size_t sz = std::min(total - i, blockSize);
for( j = 0; j < sz; j++ )
dst[j] = src[j] ^ scalar[j];
}
}
else
for( i = 0; i < total; i++ )
dst[i] = ~src[i];
}
void logicOp( const Mat& src1, const Mat& src2, Mat& dst, char op )
{
CV_Assert( op == '&' || op == '|' || op == '^' );
CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
dst.create( src1.dims, &src1.size[0], src1.type() );
const Mat *arrays[3]={&src1, &src2, &dst};
Mat planes[3];
NAryMatIterator it(arrays, planes, 3);
size_t total = planes[0].total()*planes[0].elemSize();
int i, nplanes = it.nplanes;
for( i = 0; i < nplanes; i++, ++it )
{
const uchar* sptr1 = planes[0].data;
const uchar* sptr2 = planes[1].data;
uchar* dptr = planes[2].data;
logicOp_(sptr1, sptr2, dptr, total, op);
}
}
void logicOp(const Mat& src, const Scalar& s, Mat& dst, char op)
{
CV_Assert( op == '&' || op == '|' || op == '^' );
dst.create( src.dims, &src.size[0], src.type() );
const Mat *arrays[2]={&src, &dst};
Mat planes[2];
NAryMatIterator it(arrays, planes, 2);
size_t total = planes[0].total()*planes[0].elemSize();
int i, nplanes = it.nplanes;
double buf[12];
scalarToRawData(s, buf, src.type(), 12);
for( i = 0; i < nplanes; i++, ++it )
{
const uchar* sptr = planes[0].data;
uchar* dptr = planes[1].data;
logicOpS_(sptr, (uchar*)&buf[0], dptr, total, op);
}
}
template<typename _Tp> static void
compare_(const _Tp* src1, const _Tp* src2, uchar* dst, size_t total, int cmpop)
{
size_t i;
switch( cmpop )
{
case CMP_LT:
for( i = 0; i < total; i++ )
dst[i] = src1[i] < src2[i] ? 255 : 0;
break;
case CMP_LE:
for( i = 0; i < total; i++ )
dst[i] = src1[i] <= src2[i] ? 255 : 0;
break;
case CMP_EQ:
for( i = 0; i < total; i++ )
dst[i] = src1[i] == src2[i] ? 255 : 0;
break;
case CMP_NE:
for( i = 0; i < total; i++ )
dst[i] = src1[i] != src2[i] ? 255 : 0;
break;
case CMP_GE:
for( i = 0; i < total; i++ )
dst[i] = src1[i] >= src2[i] ? 255 : 0;
break;
case CMP_GT:
for( i = 0; i < total; i++ )
dst[i] = src1[i] > src2[i] ? 255 : 0;
break;
default:
CV_Error(CV_StsBadArg, "Unknown comparison operation");
}
}
template<typename _Tp, typename _WTp> static void
compareS_(const _Tp* src1, _WTp value, uchar* dst, size_t total, int cmpop)
{
size_t i;
switch( cmpop )
{
case CMP_LT:
for( i = 0; i < total; i++ )
dst[i] = src1[i] < value ? 255 : 0;
break;
case CMP_LE:
for( i = 0; i < total; i++ )
dst[i] = src1[i] <= value ? 255 : 0;
break;
case CMP_EQ:
for( i = 0; i < total; i++ )
dst[i] = src1[i] == value ? 255 : 0;
break;
case CMP_NE:
for( i = 0; i < total; i++ )
dst[i] = src1[i] != value ? 255 : 0;
break;
case CMP_GE:
for( i = 0; i < total; i++ )
dst[i] = src1[i] >= value ? 255 : 0;
break;
case CMP_GT:
for( i = 0; i < total; i++ )
dst[i] = src1[i] > value ? 255 : 0;
break;
default:
CV_Error(CV_StsBadArg, "Unknown comparison operation");
}
}
void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop)
{
CV_Assert( src1.type() == src2.type() && src1.channels() == 1 && src1.size == src2.size );
dst.create( src1.dims, &src1.size[0], CV_8U );
const Mat *arrays[3]={&src1, &src2, &dst};
Mat planes[3];
NAryMatIterator it(arrays, planes, 3);
size_t total = planes[0].total()*planes[0].elemSize();
int i, nplanes = it.nplanes, depth = src1.depth();
for( i = 0; i < nplanes; i++, ++it )
{
const uchar* sptr1 = planes[0].data;
const uchar* sptr2 = planes[1].data;
uchar* dptr = planes[2].data;
switch( depth )
{
case CV_8U:
compare_((const uchar*)sptr1, (const uchar*)sptr2, dptr, total, cmpop);
break;
case CV_8S:
compare_((const schar*)sptr1, (const schar*)sptr2, dptr, total, cmpop);
break;
case CV_16U:
compare_((const ushort*)sptr1, (const ushort*)sptr2, dptr, total, cmpop);
break;
case CV_16S:
compare_((const short*)sptr1, (const short*)sptr2, dptr, total, cmpop);
break;
case CV_32S:
compare_((const int*)sptr1, (const int*)sptr2, dptr, total, cmpop);
break;
case CV_32F:
compare_((const float*)sptr1, (const float*)sptr2, dptr, total, cmpop);
break;
case CV_64F:
compare_((const double*)sptr1, (const double*)sptr2, dptr, total, cmpop);
break;
default:
CV_Error(CV_StsUnsupportedFormat, "");
}
}
}
void compare(const Mat& src, double value, Mat& dst, int cmpop)
{
CV_Assert( src.channels() == 1 );
dst.create( src.dims, &src.size[0], CV_8U );
const Mat *arrays[2]={&src, &dst};
Mat planes[2];
NAryMatIterator it(arrays, planes, 2);
size_t total = planes[0].total()*planes[0].elemSize();
int i, nplanes = it.nplanes, depth = src.depth();
int ivalue = saturate_cast<int>(value);
for( i = 0; i < nplanes; i++, ++it )
{
const uchar* sptr = planes[0].data;
uchar* dptr = planes[1].data;
switch( depth )
{
case CV_8U:
compareS_((const uchar*)sptr, ivalue, dptr, total, cmpop);
break;
case CV_8S:
compareS_((const schar*)sptr, ivalue, dptr, total, cmpop);
break;
case CV_16U:
compareS_((const ushort*)sptr, ivalue, dptr, total, cmpop);
break;
case CV_16S:
compareS_((const short*)sptr, ivalue, dptr, total, cmpop);
break;
case CV_32S:
compareS_((const int*)sptr, ivalue, dptr, total, cmpop);
break;
case CV_32F:
compareS_((const float*)sptr, value, dptr, total, cmpop);
break;
case CV_64F:
compareS_((const double*)sptr, value, dptr, total, cmpop);
break;
default:
CV_Error(CV_StsUnsupportedFormat, "");
}
}
}
template<typename _Tp> static bool
cmpEpsInt_(const _Tp* src1, const _Tp* src2, int imaxdiff, size_t total, size_t startidx, size_t& idx)
{
size_t i;
for( i = 0; i < total; i++ )
if( std::abs(src1[i] - src2[i]) > imaxdiff )
{
idx = i + startidx;
return false;
}
return true;
}
template<typename _Tp> static bool
cmpEpsFlt_(const _Tp* src1, const _Tp* src2, size_t total, int imaxdiff, size_t startidx, size_t& idx)
{
const _Tp C = ((_Tp)1 << (sizeof(_Tp)*8-1)) - 1;
size_t i;
for( i = 0; i < total; i++ )
{
_Tp a = src1[i], b = src2[i];
if( a < 0 ) a ^= C; if( b < 0 ) b ^= C;
_Tp d = std::abs(a - b);
if( d > imaxdiff )
{
idx = i + startidx;
return false;
}
}
return true;
}
bool cmpEps(const Mat& src1, const Mat& src2, int imaxDiff, vector<int>* loc)
{
CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
const Mat *arrays[2]={&src1, &src2};
Mat planes[2];
NAryMatIterator it(arrays, planes, 2);
size_t total = planes[0].total()*planes[0].channels();
int i, nplanes = it.nplanes, depth = src1.depth();
size_t startidx = 0, idx = -1;
bool ok = true;
for( i = 0; i < nplanes; i++, ++it, startidx += total )
{
const uchar* sptr1 = planes[0].data;
const uchar* sptr2 = planes[1].data;
switch( depth )
{
case CV_8U:
ok = cmpEpsInt_((const uchar*)sptr1, (const uchar*)sptr2, total, imaxDiff, startidx, idx);
break;
case CV_8S:
ok = cmpEpsInt_((const schar*)sptr1, (const schar*)sptr2, total, imaxDiff, startidx, idx);
break;
case CV_16U:
ok = cmpEpsInt_((const ushort*)sptr1, (const ushort*)sptr2, total, imaxDiff, startidx, idx);
break;
case CV_16S:
ok = cmpEpsInt_((const short*)sptr1, (const short*)sptr2, total, imaxDiff, startidx, idx);
break;
case CV_32S:
ok = cmpEpsInt_((const int*)sptr1, (const int*)sptr2, total, imaxDiff, startidx, idx);
break;
case CV_32F:
ok = cmpEpsFlt_((const int*)sptr1, (const int*)sptr2, total, imaxDiff, startidx, idx);
break;
case CV_64F:
ok = cmpEpsFlt_((const int64*)sptr1, (const int64*)sptr2, total, imaxDiff, startidx, idx);
break;
default:
CV_Error(CV_StsUnsupportedFormat, "");
}
if(!ok)
break;
}
if(!ok && loc)
setpos(src1, *loc, idx);
return ok;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment