1 #include "test_precomp.hpp"
9 const int ARITHM_NTESTS = 1000;
10 const int ARITHM_RNG_SEED = -1;
11 const int ARITHM_MAX_CHANNELS = 4;
12 const int ARITHM_MAX_NDIMS = 4;
13 const int ARITHM_MAX_SIZE_LOG = 10;
17 enum { FIX_ALPHA=1, FIX_BETA=2, FIX_GAMMA=4, REAL_GAMMA=8, SUPPORT_MASK=16, SCALAR_OUTPUT=32 };
18 BaseElemWiseOp(int _ninputs, int _flags, double _alpha, double _beta,
19 Scalar _gamma=Scalar::all(0), int _context=1)
20 : ninputs(_ninputs), flags(_flags), alpha(_alpha), beta(_beta), gamma(_gamma), context(_context) {}
21 BaseElemWiseOp() { flags = 0; alpha = beta = 0; gamma = Scalar::all(0); ninputs = 0; context = 1; }
22 virtual ~BaseElemWiseOp() {}
23 virtual void op(const vector<Mat>&, Mat&, const Mat&) {}
24 virtual void refop(const vector<Mat>&, Mat&, const Mat&) {}
25 virtual void getValueRange(int depth, double& minval, double& maxval)
27 minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
28 maxval = depth < CV_32S ? cvtest::getMaxVal(depth) : depth == CV_32S ? 1000000 : 1000.;
31 virtual void getRandomSize(RNG& rng, vector<int>& size)
33 cvtest::randomSize(rng, 2, ARITHM_MAX_NDIMS, cvtest::ARITHM_MAX_SIZE_LOG, size);
36 virtual int getRandomType(RNG& rng)
38 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1,
39 ninputs > 1 ? ARITHM_MAX_CHANNELS : 4);
42 virtual double getMaxErr(int depth) { return depth < CV_32F ? 1 : depth == CV_32F ? 1e-5 : 1e-12; }
43 virtual void generateScalars(int depth, RNG& rng)
47 if( !(flags & FIX_ALPHA) )
49 alpha = exp(rng.uniform(-0.5, 0.1)*m*2*CV_LOG2);
50 alpha *= rng.uniform(0, 2) ? 1 : -1;
52 if( !(flags & FIX_BETA) )
54 beta = exp(rng.uniform(-0.5, 0.1)*m*2*CV_LOG2);
55 beta *= rng.uniform(0, 2) ? 1 : -1;
58 if( !(flags & FIX_GAMMA) )
60 for( int i = 0; i < 4; i++ )
62 gamma[i] = exp(rng.uniform(-1, 6)*m*CV_LOG2);
63 gamma[i] *= rng.uniform(0, 2) ? 1 : -1;
65 if( flags & REAL_GAMMA )
66 gamma = Scalar::all(gamma[0]);
73 db = Mat(1, 1, CV_64F, &alpha);
74 db.convertTo(fl, CV_32F);
75 fl.convertTo(db, CV_64F);
77 db = Mat(1, 1, CV_64F, &beta);
78 db.convertTo(fl, CV_32F);
79 fl.convertTo(db, CV_64F);
81 db = Mat(1, 4, CV_64F, &gamma[0]);
82 db.convertTo(fl, CV_32F);
83 fl.convertTo(db, CV_64F);
96 struct BaseAddOp : public BaseElemWiseOp
98 BaseAddOp(int _ninputs, int _flags, double _alpha, double _beta, Scalar _gamma=Scalar::all(0))
99 : BaseElemWiseOp(_ninputs, _flags, _alpha, _beta, _gamma) {}
101 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
106 cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, temp, src[0].type());
107 cvtest::copy(temp, dst, mask);
110 cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, dst, src[0].type());
115 struct AddOp : public BaseAddOp
117 AddOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {}
118 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
121 add(src[0], src[1], dst);
123 add(src[0], src[1], dst, mask);
128 struct SubOp : public BaseAddOp
130 SubOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, -1, Scalar::all(0)) {}
131 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
134 subtract(src[0], src[1], dst);
136 subtract(src[0], src[1], dst, mask);
141 struct AddSOp : public BaseAddOp
143 AddSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 0, Scalar::all(0)) {}
144 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
147 add(src[0], gamma, dst);
149 add(src[0], gamma, dst, mask);
154 struct SubRSOp : public BaseAddOp
156 SubRSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, -1, 0, Scalar::all(0)) {}
157 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
160 subtract(gamma, src[0], dst);
162 subtract(gamma, src[0], dst, mask);
167 struct ScaleAddOp : public BaseAddOp
169 ScaleAddOp() : BaseAddOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
170 void op(const vector<Mat>& src, Mat& dst, const Mat&)
172 scaleAdd(src[0], alpha, src[1], dst);
174 double getMaxErr(int depth)
176 return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-4 : 1e-12;
181 struct AddWeightedOp : public BaseAddOp
183 AddWeightedOp() : BaseAddOp(2, REAL_GAMMA, 1, 1, Scalar::all(0)) {}
184 void op(const vector<Mat>& src, Mat& dst, const Mat&)
186 addWeighted(src[0], alpha, src[1], beta, gamma[0], dst);
188 double getMaxErr(int depth)
190 return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-10;
194 struct MulOp : public BaseElemWiseOp
196 MulOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
197 void getValueRange(int depth, double& minval, double& maxval)
199 minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
200 maxval = depth < CV_32S ? cvtest::getMaxVal(depth) : depth == CV_32S ? 1000000 : 1000.;
201 minval = std::max(minval, -30000.);
202 maxval = std::min(maxval, 30000.);
204 void op(const vector<Mat>& src, Mat& dst, const Mat&)
206 cv::multiply(src[0], src[1], dst, alpha);
208 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
210 cvtest::multiply(src[0], src[1], dst, alpha);
212 double getMaxErr(int depth)
214 return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
218 struct DivOp : public BaseElemWiseOp
220 DivOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
221 void op(const vector<Mat>& src, Mat& dst, const Mat&)
223 cv::divide(src[0], src[1], dst, alpha);
225 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
227 cvtest::divide(src[0], src[1], dst, alpha);
229 double getMaxErr(int depth)
231 return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
235 struct RecipOp : public BaseElemWiseOp
237 RecipOp() : BaseElemWiseOp(1, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
238 void op(const vector<Mat>& src, Mat& dst, const Mat&)
240 cv::divide(alpha, src[0], dst);
242 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
244 cvtest::divide(Mat(), src[0], dst, alpha);
246 double getMaxErr(int depth)
248 return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
252 struct AbsDiffOp : public BaseAddOp
254 AbsDiffOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, -1, Scalar::all(0)) {}
255 void op(const vector<Mat>& src, Mat& dst, const Mat&)
257 absdiff(src[0], src[1], dst);
259 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
261 cvtest::add(src[0], 1, src[1], -1, Scalar::all(0), dst, src[0].type(), true);
265 struct AbsDiffSOp : public BaseAddOp
267 AbsDiffSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA, 1, 0, Scalar::all(0)) {}
268 void op(const vector<Mat>& src, Mat& dst, const Mat&)
270 absdiff(src[0], gamma, dst);
272 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
274 cvtest::add(src[0], 1, Mat(), 0, -gamma, dst, src[0].type(), true);
278 struct LogicOp : public BaseElemWiseOp
280 LogicOp(char _opcode) : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)), opcode(_opcode) {}
281 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
284 bitwise_and(src[0], src[1], dst, mask);
285 else if( opcode == '|' )
286 bitwise_or(src[0], src[1], dst, mask);
288 bitwise_xor(src[0], src[1], dst, mask);
290 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
295 cvtest::logicOp(src[0], src[1], temp, opcode);
296 cvtest::copy(temp, dst, mask);
299 cvtest::logicOp(src[0], src[1], dst, opcode);
301 double getMaxErr(int)
308 struct LogicSOp : public BaseElemWiseOp
310 LogicSOp(char _opcode)
311 : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+(_opcode != '~' ? SUPPORT_MASK : 0), 1, 1, Scalar::all(0)), opcode(_opcode) {}
312 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
315 bitwise_and(src[0], gamma, dst, mask);
316 else if( opcode == '|' )
317 bitwise_or(src[0], gamma, dst, mask);
318 else if( opcode == '^' )
319 bitwise_xor(src[0], gamma, dst, mask);
321 bitwise_not(src[0], dst);
323 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
328 cvtest::logicOp(src[0], gamma, temp, opcode);
329 cvtest::copy(temp, dst, mask);
332 cvtest::logicOp(src[0], gamma, dst, opcode);
334 double getMaxErr(int)
341 struct MinOp : public BaseElemWiseOp
343 MinOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
344 void op(const vector<Mat>& src, Mat& dst, const Mat&)
346 cv::min(src[0], src[1], dst);
348 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
350 cvtest::min(src[0], src[1], dst);
352 double getMaxErr(int)
358 struct MaxOp : public BaseElemWiseOp
360 MaxOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
361 void op(const vector<Mat>& src, Mat& dst, const Mat&)
363 cv::max(src[0], src[1], dst);
365 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
367 cvtest::max(src[0], src[1], dst);
369 double getMaxErr(int)
375 struct MinSOp : public BaseElemWiseOp
377 MinSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}
378 void op(const vector<Mat>& src, Mat& dst, const Mat&)
380 cv::min(src[0], gamma[0], dst);
382 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
384 cvtest::min(src[0], gamma[0], dst);
386 double getMaxErr(int)
392 struct MaxSOp : public BaseElemWiseOp
394 MaxSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}
395 void op(const vector<Mat>& src, Mat& dst, const Mat&)
397 cv::max(src[0], gamma[0], dst);
399 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
401 cvtest::max(src[0], gamma[0], dst);
403 double getMaxErr(int)
409 struct CmpOp : public BaseElemWiseOp
411 CmpOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) { cmpop = 0; }
412 void generateScalars(int depth, RNG& rng)
414 BaseElemWiseOp::generateScalars(depth, rng);
415 cmpop = rng.uniform(0, 6);
417 void op(const vector<Mat>& src, Mat& dst, const Mat&)
419 cv::compare(src[0], src[1], dst, cmpop);
421 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
423 cvtest::compare(src[0], src[1], dst, cmpop);
425 int getRandomType(RNG& rng)
427 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1);
430 double getMaxErr(int)
437 struct CmpSOp : public BaseElemWiseOp
439 CmpSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) { cmpop = 0; }
440 void generateScalars(int depth, RNG& rng)
442 BaseElemWiseOp::generateScalars(depth, rng);
443 cmpop = rng.uniform(0, 6);
445 gamma[0] = cvRound(gamma[0]);
447 void op(const vector<Mat>& src, Mat& dst, const Mat&)
449 cv::compare(src[0], gamma[0], dst, cmpop);
451 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
453 cvtest::compare(src[0], gamma[0], dst, cmpop);
455 int getRandomType(RNG& rng)
457 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1);
459 double getMaxErr(int)
467 struct CopyOp : public BaseElemWiseOp
469 CopyOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) { }
470 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
472 src[0].copyTo(dst, mask);
474 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
476 cvtest::copy(src[0], dst, mask);
478 int getRandomType(RNG& rng)
480 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
482 double getMaxErr(int)
489 struct SetOp : public BaseElemWiseOp
491 SetOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {}
492 void op(const vector<Mat>&, Mat& dst, const Mat& mask)
494 dst.setTo(gamma, mask);
496 void refop(const vector<Mat>&, Mat& dst, const Mat& mask)
498 cvtest::set(dst, gamma, mask);
500 int getRandomType(RNG& rng)
502 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
504 double getMaxErr(int)
510 template<typename _Tp, typename _WTp> static void
511 inRangeS_(const _Tp* src, const _WTp* a, const _WTp* b, uchar* dst, size_t total, int cn)
515 for( i = 0; i < total; i++ )
518 dst[i] = (a[0] <= val && val <= b[0]) ? uchar(255) : 0;
520 for( c = 1; c < cn; c++ )
522 for( i = 0; i < total; i++ )
524 _Tp val = src[i*cn + c];
525 dst[i] = a[c] <= val && val <= b[c] ? dst[i] : 0;
530 template<typename _Tp> static void inRange_(const _Tp* src, const _Tp* a, const _Tp* b, uchar* dst, size_t total, int cn)
534 for( i = 0; i < total; i++ )
537 dst[i] = a[i*cn] <= val && val <= b[i*cn] ? 255 : 0;
539 for( c = 1; c < cn; c++ )
541 for( i = 0; i < total; i++ )
543 _Tp val = src[i*cn + c];
544 dst[i] = a[i*cn + c] <= val && val <= b[i*cn + c] ? dst[i] : 0;
550 static void inRange(const Mat& src, const Mat& lb, const Mat& rb, Mat& dst)
552 CV_Assert( src.type() == lb.type() && src.type() == rb.type() &&
553 src.size == lb.size && src.size == rb.size );
554 dst.create( src.dims, &src.size[0], CV_8U );
555 const Mat *arrays[]={&src, &lb, &rb, &dst, 0};
558 NAryMatIterator it(arrays, planes);
559 size_t total = planes[0].total();
560 size_t i, nplanes = it.nplanes;
561 int depth = src.depth(), cn = src.channels();
563 for( i = 0; i < nplanes; i++, ++it )
565 const uchar* sptr = planes[0].ptr();
566 const uchar* aptr = planes[1].ptr();
567 const uchar* bptr = planes[2].ptr();
568 uchar* dptr = planes[3].ptr();
573 inRange_((const uchar*)sptr, (const uchar*)aptr, (const uchar*)bptr, dptr, total, cn);
576 inRange_((const schar*)sptr, (const schar*)aptr, (const schar*)bptr, dptr, total, cn);
579 inRange_((const ushort*)sptr, (const ushort*)aptr, (const ushort*)bptr, dptr, total, cn);
582 inRange_((const short*)sptr, (const short*)aptr, (const short*)bptr, dptr, total, cn);
585 inRange_((const int*)sptr, (const int*)aptr, (const int*)bptr, dptr, total, cn);
588 inRange_((const float*)sptr, (const float*)aptr, (const float*)bptr, dptr, total, cn);
591 inRange_((const double*)sptr, (const double*)aptr, (const double*)bptr, dptr, total, cn);
594 CV_Error(CV_StsUnsupportedFormat, "");
600 static void inRangeS(const Mat& src, const Scalar& lb, const Scalar& rb, Mat& dst)
602 dst.create( src.dims, &src.size[0], CV_8U );
603 const Mat *arrays[]={&src, &dst, 0};
606 NAryMatIterator it(arrays, planes);
607 size_t total = planes[0].total();
608 size_t i, nplanes = it.nplanes;
609 int depth = src.depth(), cn = src.channels();
610 union { double d[4]; float f[4]; int i[4];} lbuf, rbuf;
611 int wtype = CV_MAKETYPE(depth <= CV_32S ? CV_32S : depth, cn);
612 scalarToRawData(lb, lbuf.d, wtype, cn);
613 scalarToRawData(rb, rbuf.d, wtype, cn);
615 for( i = 0; i < nplanes; i++, ++it )
617 const uchar* sptr = planes[0].ptr();
618 uchar* dptr = planes[1].ptr();
623 inRangeS_((const uchar*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
626 inRangeS_((const schar*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
629 inRangeS_((const ushort*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
632 inRangeS_((const short*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
635 inRangeS_((const int*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
638 inRangeS_((const float*)sptr, lbuf.f, rbuf.f, dptr, total, cn);
641 inRangeS_((const double*)sptr, lbuf.d, rbuf.d, dptr, total, cn);
644 CV_Error(CV_StsUnsupportedFormat, "");
650 struct InRangeSOp : public BaseElemWiseOp
652 InRangeSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {}
653 void op(const vector<Mat>& src, Mat& dst, const Mat&)
655 cv::inRange(src[0], gamma, gamma1, dst);
657 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
659 cvtest::inRangeS(src[0], gamma, gamma1, dst);
661 double getMaxErr(int)
665 void generateScalars(int depth, RNG& rng)
667 BaseElemWiseOp::generateScalars(depth, rng);
669 BaseElemWiseOp::generateScalars(depth, rng);
670 for( int i = 0; i < 4; i++ )
672 gamma1[i] = std::max(gamma[i], temp[i]);
673 gamma[i] = std::min(gamma[i], temp[i]);
680 struct InRangeOp : public BaseElemWiseOp
682 InRangeOp() : BaseElemWiseOp(3, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
683 void op(const vector<Mat>& src, Mat& dst, const Mat&)
686 cvtest::min(src[1], src[2], lb);
687 cvtest::max(src[1], src[2], rb);
689 cv::inRange(src[0], lb, rb, dst);
691 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
694 cvtest::min(src[1], src[2], lb);
695 cvtest::max(src[1], src[2], rb);
697 cvtest::inRange(src[0], lb, rb, dst);
699 double getMaxErr(int)
706 struct ConvertScaleOp : public BaseElemWiseOp
708 ConvertScaleOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), ddepth(0) { }
709 void op(const vector<Mat>& src, Mat& dst, const Mat&)
711 src[0].convertTo(dst, ddepth, alpha, gamma[0]);
713 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
715 cvtest::convert(src[0], dst, CV_MAKETYPE(ddepth, src[0].channels()), alpha, gamma[0]);
717 int getRandomType(RNG& rng)
719 int srctype = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
720 ddepth = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, 1);
723 double getMaxErr(int)
725 return ddepth <= CV_32S ? 2 : ddepth < CV_64F ? 1e-3 : 1e-12;
727 void generateScalars(int depth, RNG& rng)
729 if( rng.uniform(0, 2) )
730 BaseElemWiseOp::generateScalars(depth, rng);
734 gamma = Scalar::all(0);
741 struct ConvertScaleAbsOp : public BaseElemWiseOp
743 ConvertScaleAbsOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}
744 void op(const vector<Mat>& src, Mat& dst, const Mat&)
746 cv::convertScaleAbs(src[0], dst, alpha, gamma[0]);
748 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
750 cvtest::add(src[0], alpha, Mat(), 0, Scalar::all(gamma[0]), dst, CV_8UC(src[0].channels()), true);
752 double getMaxErr(int)
756 void generateScalars(int depth, RNG& rng)
758 if( rng.uniform(0, 2) )
759 BaseElemWiseOp::generateScalars(depth, rng);
763 gamma = Scalar::all(0);
769 static void flip(const Mat& src, Mat& dst, int flipcode)
771 CV_Assert(src.dims == 2);
772 dst.create(src.size(), src.type());
773 int i, j, k, esz = (int)src.elemSize(), width = src.cols*esz;
775 for( i = 0; i < dst.rows; i++ )
777 const uchar* sptr = src.ptr(flipcode == 1 ? i : dst.rows - i - 1);
778 uchar* dptr = dst.ptr(i);
780 memcpy(dptr, sptr, width);
783 for( j = 0; j < width; j += esz )
784 for( k = 0; k < esz; k++ )
785 dptr[j + k] = sptr[width - j - esz + k];
791 static void setIdentity(Mat& dst, const Scalar& s)
793 CV_Assert( dst.dims == 2 && dst.channels() <= 4 );
795 scalarToRawData(s, buf, dst.type(), 0);
796 int i, k, esz = (int)dst.elemSize(), width = dst.cols*esz;
798 for( i = 0; i < dst.rows; i++ )
800 uchar* dptr = dst.ptr(i);
801 memset( dptr, 0, width );
803 for( k = 0; k < esz; k++ )
804 dptr[i*esz + k] = ((uchar*)buf)[k];
809 struct FlipOp : public BaseElemWiseOp
811 FlipOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) { flipcode = 0; }
812 void getRandomSize(RNG& rng, vector<int>& size)
814 cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size);
816 void op(const vector<Mat>& src, Mat& dst, const Mat&)
818 cv::flip(src[0], dst, flipcode);
820 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
822 cvtest::flip(src[0], dst, flipcode);
824 void generateScalars(int, RNG& rng)
826 flipcode = rng.uniform(0, 3) - 1;
828 double getMaxErr(int)
835 struct TransposeOp : public BaseElemWiseOp
837 TransposeOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
838 void getRandomSize(RNG& rng, vector<int>& size)
840 cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size);
842 void op(const vector<Mat>& src, Mat& dst, const Mat&)
844 cv::transpose(src[0], dst);
846 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
848 cvtest::transpose(src[0], dst);
850 double getMaxErr(int)
856 struct SetIdentityOp : public BaseElemWiseOp
858 SetIdentityOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {}
859 void getRandomSize(RNG& rng, vector<int>& size)
861 cvtest::randomSize(rng, 2, 2, cvtest::ARITHM_MAX_SIZE_LOG, size);
863 void op(const vector<Mat>&, Mat& dst, const Mat&)
865 cv::setIdentity(dst, gamma);
867 void refop(const vector<Mat>&, Mat& dst, const Mat&)
869 cvtest::setIdentity(dst, gamma);
871 double getMaxErr(int)
877 struct SetZeroOp : public BaseElemWiseOp
879 SetZeroOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
880 void op(const vector<Mat>&, Mat& dst, const Mat&)
882 dst = Scalar::all(0);
884 void refop(const vector<Mat>&, Mat& dst, const Mat&)
886 cvtest::set(dst, Scalar::all(0));
888 double getMaxErr(int)
895 static void exp(const Mat& src, Mat& dst)
897 dst.create( src.dims, &src.size[0], src.type() );
898 const Mat *arrays[]={&src, &dst, 0};
901 NAryMatIterator it(arrays, planes);
902 size_t j, total = planes[0].total()*src.channels();
903 size_t i, nplanes = it.nplanes;
904 int depth = src.depth();
906 for( i = 0; i < nplanes; i++, ++it )
908 const uchar* sptr = planes[0].ptr();
909 uchar* dptr = planes[1].ptr();
911 if( depth == CV_32F )
913 for( j = 0; j < total; j++ )
914 ((float*)dptr)[j] = std::exp(((const float*)sptr)[j]);
916 else if( depth == CV_64F )
918 for( j = 0; j < total; j++ )
919 ((double*)dptr)[j] = std::exp(((const double*)sptr)[j]);
924 static void log(const Mat& src, Mat& dst)
926 dst.create( src.dims, &src.size[0], src.type() );
927 const Mat *arrays[]={&src, &dst, 0};
930 NAryMatIterator it(arrays, planes);
931 size_t j, total = planes[0].total()*src.channels();
932 size_t i, nplanes = it.nplanes;
933 int depth = src.depth();
935 for( i = 0; i < nplanes; i++, ++it )
937 const uchar* sptr = planes[0].ptr();
938 uchar* dptr = planes[1].ptr();
940 if( depth == CV_32F )
942 for( j = 0; j < total; j++ )
943 ((float*)dptr)[j] = (float)std::log(fabs(((const float*)sptr)[j]));
945 else if( depth == CV_64F )
947 for( j = 0; j < total; j++ )
948 ((double*)dptr)[j] = std::log(fabs(((const double*)sptr)[j]));
953 struct ExpOp : public BaseElemWiseOp
955 ExpOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
956 int getRandomType(RNG& rng)
958 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS);
960 void getValueRange(int depth, double& minval, double& maxval)
962 maxval = depth == CV_32F ? 50 : 100;
965 void op(const vector<Mat>& src, Mat& dst, const Mat&)
967 cv::exp(src[0], dst);
969 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
971 cvtest::exp(src[0], dst);
973 double getMaxErr(int depth)
975 return depth == CV_32F ? 1e-5 : 1e-12;
980 struct LogOp : public BaseElemWiseOp
982 LogOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
983 int getRandomType(RNG& rng)
985 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS);
987 void getValueRange(int depth, double& minval, double& maxval)
989 maxval = depth == CV_32F ? 50 : 100;
992 void op(const vector<Mat>& src, Mat& dst, const Mat&)
995 cvtest::exp(src[0], temp);
998 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1001 cvtest::exp(src[0], temp);
1002 cvtest::log(temp, dst);
1004 double getMaxErr(int depth)
1006 return depth == CV_32F ? 1e-5 : 1e-12;
1011 static void cartToPolar(const Mat& mx, const Mat& my, Mat& mmag, Mat& mangle, bool angleInDegrees)
1013 CV_Assert( (mx.type() == CV_32F || mx.type() == CV_64F) &&
1014 mx.type() == my.type() && mx.size == my.size );
1015 mmag.create( mx.dims, &mx.size[0], mx.type() );
1016 mangle.create( mx.dims, &mx.size[0], mx.type() );
1017 const Mat *arrays[]={&mx, &my, &mmag, &mangle, 0};
1020 NAryMatIterator it(arrays, planes);
1021 size_t j, total = planes[0].total();
1022 size_t i, nplanes = it.nplanes;
1023 int depth = mx.depth();
1024 double scale = angleInDegrees ? 180/CV_PI : 1;
1026 for( i = 0; i < nplanes; i++, ++it )
1028 if( depth == CV_32F )
1030 const float* xptr = planes[0].ptr<float>();
1031 const float* yptr = planes[1].ptr<float>();
1032 float* mptr = planes[2].ptr<float>();
1033 float* aptr = planes[3].ptr<float>();
1035 for( j = 0; j < total; j++ )
1037 mptr[j] = std::sqrt(xptr[j]*xptr[j] + yptr[j]*yptr[j]);
1038 double a = atan2((double)yptr[j], (double)xptr[j]);
1039 if( a < 0 ) a += CV_PI*2;
1040 aptr[j] = (float)(a*scale);
1045 const double* xptr = planes[0].ptr<double>();
1046 const double* yptr = planes[1].ptr<double>();
1047 double* mptr = planes[2].ptr<double>();
1048 double* aptr = planes[3].ptr<double>();
1050 for( j = 0; j < total; j++ )
1052 mptr[j] = std::sqrt(xptr[j]*xptr[j] + yptr[j]*yptr[j]);
1053 double a = atan2(yptr[j], xptr[j]);
1054 if( a < 0 ) a += CV_PI*2;
1062 struct CartToPolarToCartOp : public BaseElemWiseOp
1064 CartToPolarToCartOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0))
1067 angleInDegrees = true;
1069 int getRandomType(RNG& rng)
1071 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, 1);
1073 void op(const vector<Mat>& src, Mat& dst, const Mat&)
1075 Mat mag, angle, x, y;
1077 cv::cartToPolar(src[0], src[1], mag, angle, angleInDegrees);
1078 cv::polarToCart(mag, angle, x, y, angleInDegrees);
1080 Mat msrc[] = {mag, angle, x, y};
1081 int pairs[] = {0, 0, 1, 1, 2, 2, 3, 3};
1082 dst.create(src[0].dims, src[0].size, CV_MAKETYPE(src[0].depth(), 4));
1083 cv::mixChannels(msrc, 4, &dst, 1, pairs, 4);
1085 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1088 cvtest::cartToPolar(src[0], src[1], mag, angle, angleInDegrees);
1089 Mat msrc[] = {mag, angle, src[0], src[1]};
1090 int pairs[] = {0, 0, 1, 1, 2, 2, 3, 3};
1091 dst.create(src[0].dims, src[0].size, CV_MAKETYPE(src[0].depth(), 4));
1092 cv::mixChannels(msrc, 4, &dst, 1, pairs, 4);
1094 void generateScalars(int, RNG& rng)
1096 angleInDegrees = rng.uniform(0, 2) != 0;
1098 double getMaxErr(int)
1102 bool angleInDegrees;
1106 struct MeanOp : public BaseElemWiseOp
1108 MeanOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1112 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1114 dst.create(1, 1, CV_64FC4);
1115 dst.at<Scalar>(0,0) = cv::mean(src[0], mask);
1117 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1119 dst.create(1, 1, CV_64FC4);
1120 dst.at<Scalar>(0,0) = cvtest::mean(src[0], mask);
1122 double getMaxErr(int)
1129 struct SumOp : public BaseElemWiseOp
1131 SumOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1135 void op(const vector<Mat>& src, Mat& dst, const Mat&)
1137 dst.create(1, 1, CV_64FC4);
1138 dst.at<Scalar>(0,0) = cv::sum(src[0]);
1140 void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1142 dst.create(1, 1, CV_64FC4);
1143 dst.at<Scalar>(0,0) = cvtest::mean(src[0])*(double)src[0].total();
1145 double getMaxErr(int)
1152 struct CountNonZeroOp : public BaseElemWiseOp
1154 CountNonZeroOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SCALAR_OUTPUT+SUPPORT_MASK, 1, 1, Scalar::all(0))
1156 int getRandomType(RNG& rng)
1158 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, 1);
1160 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1163 src[0].copyTo(temp);
1165 temp.setTo(Scalar::all(0), mask);
1166 dst.create(1, 1, CV_32S);
1167 dst.at<int>(0,0) = cv::countNonZero(temp);
1169 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1172 cvtest::compare(src[0], 0, temp, CMP_NE);
1174 cvtest::set(temp, Scalar::all(0), mask);
1175 dst.create(1, 1, CV_32S);
1176 dst.at<int>(0,0) = saturate_cast<int>(cvtest::mean(temp)[0]/255*temp.total());
1178 double getMaxErr(int)
1185 struct MeanStdDevOp : public BaseElemWiseOp
1190 MeanStdDevOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1195 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1197 dst.create(1, 2, CV_64FC4);
1198 cv::meanStdDev(src[0], dst.at<Scalar>(0,0), dst.at<Scalar>(0,1), mask);
1200 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1203 cvtest::convert(src[0], temp, CV_64F);
1204 cvtest::multiply(temp, temp, temp);
1205 Scalar mean = cvtest::mean(src[0], mask);
1206 Scalar sqmean = cvtest::mean(temp, mask);
1209 cn = temp.channels();
1211 for( int c = 0; c < 4; c++ )
1212 sqmean[c] = std::sqrt(std::max(sqmean[c] - mean[c]*mean[c], 0.));
1214 dst.create(1, 2, CV_64FC4);
1215 dst.at<Scalar>(0,0) = mean;
1216 dst.at<Scalar>(0,1) = sqmean;
1218 double getMaxErr(int)
1221 double err = sqmeanRef[0];
1222 for(int i = 1; i < cn; ++i)
1223 err = std::max(err, sqmeanRef[i]);
1229 struct NormOp : public BaseElemWiseOp
1231 NormOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1236 int getRandomType(RNG& rng)
1238 int type = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 4);
1241 normType = rng.uniform(1, 8);
1242 if( normType == NORM_INF || normType == NORM_L1 ||
1243 normType == NORM_L2 || normType == NORM_L2SQR ||
1244 normType == NORM_HAMMING || normType == NORM_HAMMING2 )
1247 if( normType == NORM_HAMMING || normType == NORM_HAMMING2 )
1253 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1255 dst.create(1, 2, CV_64FC1);
1256 dst.at<double>(0,0) = cv::norm(src[0], normType, mask);
1257 dst.at<double>(0,1) = cv::norm(src[0], src[1], normType, mask);
1259 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1261 dst.create(1, 2, CV_64FC1);
1262 dst.at<double>(0,0) = cvtest::norm(src[0], normType, mask);
1263 dst.at<double>(0,1) = cvtest::norm(src[0], src[1], normType, mask);
1265 void generateScalars(int, RNG& /*rng*/)
1268 double getMaxErr(int)
1276 struct MinMaxLocOp : public BaseElemWiseOp
1278 MinMaxLocOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1280 context = ARITHM_MAX_NDIMS*2 + 2;
1282 int getRandomType(RNG& rng)
1284 return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1);
1286 void saveOutput(const vector<int>& minidx, const vector<int>& maxidx,
1287 double minval, double maxval, Mat& dst)
1289 int i, ndims = (int)minidx.size();
1290 dst.create(1, ndims*2 + 2, CV_64FC1);
1292 for( i = 0; i < ndims; i++ )
1294 dst.at<double>(0,i) = minidx[i];
1295 dst.at<double>(0,i+ndims) = maxidx[i];
1297 dst.at<double>(0,ndims*2) = minval;
1298 dst.at<double>(0,ndims*2+1) = maxval;
1300 void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1302 int ndims = src[0].dims;
1303 vector<int> minidx(ndims), maxidx(ndims);
1304 double minval=0, maxval=0;
1305 cv::minMaxIdx(src[0], &minval, &maxval, &minidx[0], &maxidx[0], mask);
1306 saveOutput(minidx, maxidx, minval, maxval, dst);
1308 void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1310 int ndims=src[0].dims;
1311 vector<int> minidx(ndims), maxidx(ndims);
1312 double minval=0, maxval=0;
1313 cvtest::minMaxLoc(src[0], &minval, &maxval, &minidx, &maxidx, mask);
1314 saveOutput(minidx, maxidx, minval, maxval, dst);
1316 double getMaxErr(int)
1325 typedef Ptr<cvtest::BaseElemWiseOp> ElemWiseOpPtr;
1326 class ElemWiseTest : public ::testing::TestWithParam<ElemWiseOpPtr> {};
1328 TEST_P(ElemWiseTest, accuracy)
1330 ElemWiseOpPtr op = GetParam();
1333 RNG rng((uint64)cvtest::ARITHM_RNG_SEED);
1334 for( testIdx = 0; testIdx < cvtest::ARITHM_NTESTS; testIdx++ )
1337 op->getRandomSize(rng, size);
1338 int type = op->getRandomType(rng);
1339 int depth = CV_MAT_DEPTH(type);
1340 bool haveMask = (op->flags & cvtest::BaseElemWiseOp::SUPPORT_MASK) != 0 && rng.uniform(0, 4) == 0;
1342 double minval=0, maxval=0;
1343 op->getValueRange(depth, minval, maxval);
1344 int i, ninputs = op->ninputs;
1345 vector<Mat> src(ninputs);
1346 for( i = 0; i < ninputs; i++ )
1347 src[i] = cvtest::randomMat(rng, size, type, minval, maxval, true);
1348 Mat dst0, dst, mask;
1350 mask = cvtest::randomMat(rng, size, CV_8U, 0, 2, true);
1352 if( (haveMask || ninputs == 0) && !(op->flags & cvtest::BaseElemWiseOp::SCALAR_OUTPUT))
1354 dst0 = cvtest::randomMat(rng, size, type, minval, maxval, false);
1355 dst = cvtest::randomMat(rng, size, type, minval, maxval, true);
1356 cvtest::copy(dst, dst0);
1358 op->generateScalars(depth, rng);
1360 op->refop(src, dst0, mask);
1361 op->op(src, dst, mask);
1363 double maxErr = op->getMaxErr(depth);
1364 ASSERT_PRED_FORMAT2(cvtest::MatComparator(maxErr, op->context), dst0, dst) << "\nsrc[0] ~ " <<
1365 cvtest::MatInfo(!src.empty() ? src[0] : Mat()) << "\ntestCase #" << testIdx << "\n";
1370 INSTANTIATE_TEST_CASE_P(Core_Copy, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CopyOp)));
1371 INSTANTIATE_TEST_CASE_P(Core_Set, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetOp)));
1372 INSTANTIATE_TEST_CASE_P(Core_SetZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetZeroOp)));
1373 INSTANTIATE_TEST_CASE_P(Core_ConvertScale, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleOp)));
1374 INSTANTIATE_TEST_CASE_P(Core_ConvertScaleAbs, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ConvertScaleAbsOp)));
1376 INSTANTIATE_TEST_CASE_P(Core_Add, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddOp)));
1377 INSTANTIATE_TEST_CASE_P(Core_Sub, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SubOp)));
1378 INSTANTIATE_TEST_CASE_P(Core_AddS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddSOp)));
1379 INSTANTIATE_TEST_CASE_P(Core_SubRS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SubRSOp)));
1380 INSTANTIATE_TEST_CASE_P(Core_ScaleAdd, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ScaleAddOp)));
1381 INSTANTIATE_TEST_CASE_P(Core_AddWeighted, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddWeightedOp)));
1382 INSTANTIATE_TEST_CASE_P(Core_AbsDiff, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AbsDiffOp)));
1385 INSTANTIATE_TEST_CASE_P(Core_AbsDiffS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AbsDiffSOp)));
1387 INSTANTIATE_TEST_CASE_P(Core_And, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicOp('&'))));
1388 INSTANTIATE_TEST_CASE_P(Core_AndS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('&'))));
1389 INSTANTIATE_TEST_CASE_P(Core_Or, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicOp('|'))));
1390 INSTANTIATE_TEST_CASE_P(Core_OrS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('|'))));
1391 INSTANTIATE_TEST_CASE_P(Core_Xor, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicOp('^'))));
1392 INSTANTIATE_TEST_CASE_P(Core_XorS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('^'))));
1393 INSTANTIATE_TEST_CASE_P(Core_Not, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicSOp('~'))));
1395 INSTANTIATE_TEST_CASE_P(Core_Max, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MaxOp)));
1396 INSTANTIATE_TEST_CASE_P(Core_MaxS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MaxSOp)));
1397 INSTANTIATE_TEST_CASE_P(Core_Min, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MinOp)));
1398 INSTANTIATE_TEST_CASE_P(Core_MinS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MinSOp)));
1400 INSTANTIATE_TEST_CASE_P(Core_Mul, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MulOp)));
1401 INSTANTIATE_TEST_CASE_P(Core_Div, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::DivOp)));
1402 INSTANTIATE_TEST_CASE_P(Core_Recip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::RecipOp)));
1404 INSTANTIATE_TEST_CASE_P(Core_Cmp, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CmpOp)));
1405 INSTANTIATE_TEST_CASE_P(Core_CmpS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CmpSOp)));
1407 INSTANTIATE_TEST_CASE_P(Core_InRangeS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::InRangeSOp)));
1408 INSTANTIATE_TEST_CASE_P(Core_InRange, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::InRangeOp)));
1410 INSTANTIATE_TEST_CASE_P(Core_Flip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::FlipOp)));
1411 INSTANTIATE_TEST_CASE_P(Core_Transpose, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::TransposeOp)));
1412 INSTANTIATE_TEST_CASE_P(Core_SetIdentity, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SetIdentityOp)));
1414 INSTANTIATE_TEST_CASE_P(Core_Exp, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ExpOp)));
1415 INSTANTIATE_TEST_CASE_P(Core_Log, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogOp)));
1417 INSTANTIATE_TEST_CASE_P(Core_CountNonZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CountNonZeroOp)));
1418 INSTANTIATE_TEST_CASE_P(Core_Mean, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MeanOp)));
1419 INSTANTIATE_TEST_CASE_P(Core_MeanStdDev, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MeanStdDevOp)));
1420 INSTANTIATE_TEST_CASE_P(Core_Sum, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::SumOp)));
1421 INSTANTIATE_TEST_CASE_P(Core_Norm, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::NormOp)));
1422 INSTANTIATE_TEST_CASE_P(Core_MinMaxLoc, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MinMaxLocOp)));
1423 INSTANTIATE_TEST_CASE_P(Core_CartToPolarToCart, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CartToPolarToCartOp)));
1426 class CV_ArithmMaskTest : public cvtest::BaseTest
1429 CV_ArithmMaskTest() {}
1430 ~CV_ArithmMaskTest() {}
1436 RNG& rng = theRNG();
1437 const int MAX_DIM=3;
1439 for( int iter = 0; iter < 100; iter++ )
1441 //ts->printf(cvtest::TS::LOG, ".");
1443 ts->update_context(this, iter, true);
1444 int k, dims = rng.uniform(1, MAX_DIM+1), p = 1;
1445 int depth = rng.uniform(CV_8U, CV_64F+1);
1446 int cn = rng.uniform(1, 6);
1447 int type = CV_MAKETYPE(depth, cn);
1448 int op = rng.uniform(0, 5);
1449 int depth1 = op <= 1 ? CV_64F : depth;
1450 for( k = 0; k < dims; k++ )
1452 sizes[k] = rng.uniform(1, 30);
1455 Mat a(dims, sizes, type), a1;
1456 Mat b(dims, sizes, type), b1;
1457 Mat mask(dims, sizes, CV_8U);
1461 rng.fill(a, RNG::UNIFORM, 0, 100);
1462 rng.fill(b, RNG::UNIFORM, 0, 100);
1464 // [-2,2) range means that the each generated random number
1465 // will be one of -2, -1, 0, 1. Saturated to [0,255], it will become
1466 // 0, 0, 0, 1 => the mask will be filled by ~25%.
1467 rng.fill(mask, RNG::UNIFORM, -2, 2);
1469 a.convertTo(a1, depth1);
1470 b.convertTo(b1, depth1);
1472 compare(mask, 0, mask1, CMP_EQ);
1483 subtract(a, b, c, mask);
1484 subtract(a1, b1, d);
1488 bitwise_and(a, b, c, mask);
1489 bitwise_and(a1, b1, d);
1493 bitwise_or(a, b, c, mask);
1494 bitwise_or(a1, b1, d);
1498 bitwise_xor(a, b, c, mask);
1499 bitwise_xor(a1, b1, d);
1502 d.convertTo(d1, depth);
1503 CV_Assert( cvtest::norm(c, d1, CV_C) <= DBL_EPSILON );
1506 Mat_<uchar> tmpSrc(100,100);
1508 Mat_<uchar> tmpMask(100,100);
1510 Mat_<uchar> tmpDst(100,100);
1512 tmpSrc.copyTo(tmpDst,tmpMask);
1516 ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
1521 TEST(Core_ArithmMask, uninitialized) { CV_ArithmMaskTest test; test.safe_run(); }
1523 TEST(Multiply, FloatingPointRounding)
1525 cv::Mat src(1, 1, CV_8UC1, cv::Scalar::all(110)), dst;
1526 cv::Scalar s(147.286359696927, 1, 1 ,1);
1528 cv::multiply(src, s, dst, 1, CV_16U);
1529 // with CV_32F this produce result 16202
1530 ASSERT_EQ(dst.at<ushort>(0,0), 16201);
1533 TEST(Core_Add, AddToColumnWhen3Rows)
1535 cv::Mat m1 = (cv::Mat_<double>(3, 2) << 1, 2, 3, 4, 5, 6);
1538 cv::Mat m2 = (cv::Mat_<double>(3, 2) << 1, 12, 3, 14, 5, 16);
1540 ASSERT_EQ(0, countNonZero(m1 - m2));
1543 TEST(Core_Add, AddToColumnWhen4Rows)
1545 cv::Mat m1 = (cv::Mat_<double>(4, 2) << 1, 2, 3, 4, 5, 6, 7, 8);
1548 cv::Mat m2 = (cv::Mat_<double>(4, 2) << 1, 12, 3, 14, 5, 16, 7, 18);
1550 ASSERT_EQ(0, countNonZero(m1 - m2));
1553 TEST(Core_round, CvRound)
1555 ASSERT_EQ(2, cvRound(2.0));
1556 ASSERT_EQ(2, cvRound(2.1));
1557 ASSERT_EQ(-2, cvRound(-2.1));
1558 ASSERT_EQ(3, cvRound(2.8));
1559 ASSERT_EQ(-3, cvRound(-2.8));
1560 ASSERT_EQ(2, cvRound(2.5));
1561 ASSERT_EQ(4, cvRound(3.5));
1562 ASSERT_EQ(-2, cvRound(-2.5));
1563 ASSERT_EQ(-4, cvRound(-3.5));
1567 typedef testing::TestWithParam<Size> Mul1;
1571 Size size = GetParam();
1572 cv::Mat src(size, CV_32FC1, cv::Scalar::all(2)), dst,
1573 ref_dst(size, CV_32FC1, cv::Scalar::all(6));
1575 cv::multiply(3, src, dst);
1577 ASSERT_EQ(0, cvtest::norm(dst, ref_dst, cv::NORM_INF));
1580 INSTANTIATE_TEST_CASE_P(Arithm, Mul1, testing::Values(Size(2, 2), Size(1, 1)));
1582 class SubtractOutputMatNotEmpty : public testing::TestWithParam< std::tr1::tuple<cv::Size, perf::MatType, perf::MatDepth, bool> >
1592 size = std::tr1::get<0>(GetParam());
1593 src_type = std::tr1::get<1>(GetParam());
1594 dst_depth = std::tr1::get<2>(GetParam());
1595 fixed = std::tr1::get<3>(GetParam());
1599 TEST_P(SubtractOutputMatNotEmpty, Mat_Mat)
1601 cv::Mat src1(size, src_type, cv::Scalar::all(16));
1602 cv::Mat src2(size, src_type, cv::Scalar::all(16));
1608 cv::subtract(src1, src2, dst, cv::noArray(), dst_depth);
1612 const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src1.channels()));
1613 cv::subtract(src1, src2, fixed_dst, cv::noArray(), dst_depth);
1615 dst_depth = fixed_dst.depth();
1618 ASSERT_FALSE(dst.empty());
1619 ASSERT_EQ(src1.size(), dst.size());
1620 ASSERT_EQ(dst_depth > 0 ? dst_depth : src1.depth(), dst.depth());
1621 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1624 TEST_P(SubtractOutputMatNotEmpty, Mat_Mat_WithMask)
1626 cv::Mat src1(size, src_type, cv::Scalar::all(16));
1627 cv::Mat src2(size, src_type, cv::Scalar::all(16));
1628 cv::Mat mask(size, CV_8UC1, cv::Scalar::all(255));
1634 cv::subtract(src1, src2, dst, mask, dst_depth);
1638 const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src1.channels()));
1639 cv::subtract(src1, src2, fixed_dst, mask, dst_depth);
1641 dst_depth = fixed_dst.depth();
1644 ASSERT_FALSE(dst.empty());
1645 ASSERT_EQ(src1.size(), dst.size());
1646 ASSERT_EQ(dst_depth > 0 ? dst_depth : src1.depth(), dst.depth());
1647 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1650 TEST_P(SubtractOutputMatNotEmpty, Mat_Mat_Expr)
1652 cv::Mat src1(size, src_type, cv::Scalar::all(16));
1653 cv::Mat src2(size, src_type, cv::Scalar::all(16));
1655 cv::Mat dst = src1 - src2;
1657 ASSERT_FALSE(dst.empty());
1658 ASSERT_EQ(src1.size(), dst.size());
1659 ASSERT_EQ(src1.depth(), dst.depth());
1660 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1663 TEST_P(SubtractOutputMatNotEmpty, Mat_Scalar)
1665 cv::Mat src(size, src_type, cv::Scalar::all(16));
1671 cv::subtract(src, cv::Scalar::all(16), dst, cv::noArray(), dst_depth);
1675 const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1676 cv::subtract(src, cv::Scalar::all(16), fixed_dst, cv::noArray(), dst_depth);
1678 dst_depth = fixed_dst.depth();
1681 ASSERT_FALSE(dst.empty());
1682 ASSERT_EQ(src.size(), dst.size());
1683 ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1684 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1687 TEST_P(SubtractOutputMatNotEmpty, Mat_Scalar_WithMask)
1689 cv::Mat src(size, src_type, cv::Scalar::all(16));
1690 cv::Mat mask(size, CV_8UC1, cv::Scalar::all(255));
1696 cv::subtract(src, cv::Scalar::all(16), dst, mask, dst_depth);
1700 const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1701 cv::subtract(src, cv::Scalar::all(16), fixed_dst, mask, dst_depth);
1703 dst_depth = fixed_dst.depth();
1706 ASSERT_FALSE(dst.empty());
1707 ASSERT_EQ(src.size(), dst.size());
1708 ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1709 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1712 TEST_P(SubtractOutputMatNotEmpty, Scalar_Mat)
1714 cv::Mat src(size, src_type, cv::Scalar::all(16));
1720 cv::subtract(cv::Scalar::all(16), src, dst, cv::noArray(), dst_depth);
1724 const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1725 cv::subtract(cv::Scalar::all(16), src, fixed_dst, cv::noArray(), dst_depth);
1727 dst_depth = fixed_dst.depth();
1730 ASSERT_FALSE(dst.empty());
1731 ASSERT_EQ(src.size(), dst.size());
1732 ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1733 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1736 TEST_P(SubtractOutputMatNotEmpty, Scalar_Mat_WithMask)
1738 cv::Mat src(size, src_type, cv::Scalar::all(16));
1739 cv::Mat mask(size, CV_8UC1, cv::Scalar::all(255));
1745 cv::subtract(cv::Scalar::all(16), src, dst, mask, dst_depth);
1749 const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1750 cv::subtract(cv::Scalar::all(16), src, fixed_dst, mask, dst_depth);
1752 dst_depth = fixed_dst.depth();
1755 ASSERT_FALSE(dst.empty());
1756 ASSERT_EQ(src.size(), dst.size());
1757 ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1758 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1761 TEST_P(SubtractOutputMatNotEmpty, Mat_Mat_3d)
1763 int dims[] = {5, size.height, size.width};
1765 cv::Mat src1(3, dims, src_type, cv::Scalar::all(16));
1766 cv::Mat src2(3, dims, src_type, cv::Scalar::all(16));
1772 cv::subtract(src1, src2, dst, cv::noArray(), dst_depth);
1776 const cv::Mat fixed_dst(3, dims, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src1.channels()));
1777 cv::subtract(src1, src2, fixed_dst, cv::noArray(), dst_depth);
1779 dst_depth = fixed_dst.depth();
1782 ASSERT_FALSE(dst.empty());
1783 ASSERT_EQ(src1.dims, dst.dims);
1784 ASSERT_EQ(src1.size, dst.size);
1785 ASSERT_EQ(dst_depth > 0 ? dst_depth : src1.depth(), dst.depth());
1786 ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1789 INSTANTIATE_TEST_CASE_P(Arithm, SubtractOutputMatNotEmpty, testing::Combine(
1790 testing::Values(cv::Size(16, 16), cv::Size(13, 13), cv::Size(16, 13), cv::Size(13, 16)),
1791 testing::Values(perf::MatType(CV_8UC1), CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3),
1792 testing::Values(-1, CV_16S, CV_32S, CV_32F),