Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/core/test/test_arithm.cpp
16337 views
1
// This file is part of OpenCV project.
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
// of this distribution and at http://opencv.org/license.html.
4
#include "test_precomp.hpp"
5
6
namespace opencv_test { namespace {
7
8
const int ARITHM_NTESTS = 1000;
9
const int ARITHM_RNG_SEED = -1;
10
const int ARITHM_MAX_CHANNELS = 4;
11
const int ARITHM_MAX_NDIMS = 4;
12
const int ARITHM_MAX_SIZE_LOG = 10;
13
14
struct BaseElemWiseOp
15
{
16
enum { FIX_ALPHA=1, FIX_BETA=2, FIX_GAMMA=4, REAL_GAMMA=8, SUPPORT_MASK=16, SCALAR_OUTPUT=32, SUPPORT_MULTICHANNELMASK=64 };
17
BaseElemWiseOp(int _ninputs, int _flags, double _alpha, double _beta,
18
Scalar _gamma=Scalar::all(0), int _context=1)
19
: ninputs(_ninputs), flags(_flags), alpha(_alpha), beta(_beta), gamma(_gamma), context(_context) {}
20
BaseElemWiseOp() { flags = 0; alpha = beta = 0; gamma = Scalar::all(0); ninputs = 0; context = 1; }
21
virtual ~BaseElemWiseOp() {}
22
virtual void op(const vector<Mat>&, Mat&, const Mat&) {}
23
virtual void refop(const vector<Mat>&, Mat&, const Mat&) {}
24
virtual void getValueRange(int depth, double& minval, double& maxval)
25
{
26
minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
27
maxval = depth < CV_32S ? cvtest::getMaxVal(depth) : depth == CV_32S ? 1000000 : 1000.;
28
}
29
30
virtual void getRandomSize(RNG& rng, vector<int>& size)
31
{
32
cvtest::randomSize(rng, 2, ARITHM_MAX_NDIMS, ARITHM_MAX_SIZE_LOG, size);
33
}
34
35
virtual int getRandomType(RNG& rng)
36
{
37
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1,
38
ninputs > 1 ? ARITHM_MAX_CHANNELS : 4);
39
}
40
41
virtual double getMaxErr(int depth) { return depth < CV_32F ? 1 : depth == CV_32F ? 1e-5 : 1e-12; }
42
virtual void generateScalars(int depth, RNG& rng)
43
{
44
const double m = 3.;
45
46
if( !(flags & FIX_ALPHA) )
47
{
48
alpha = exp(rng.uniform(-0.5, 0.1)*m*2*CV_LOG2);
49
alpha *= rng.uniform(0, 2) ? 1 : -1;
50
}
51
if( !(flags & FIX_BETA) )
52
{
53
beta = exp(rng.uniform(-0.5, 0.1)*m*2*CV_LOG2);
54
beta *= rng.uniform(0, 2) ? 1 : -1;
55
}
56
57
if( !(flags & FIX_GAMMA) )
58
{
59
for( int i = 0; i < 4; i++ )
60
{
61
gamma[i] = exp(rng.uniform(-1, 6)*m*CV_LOG2);
62
gamma[i] *= rng.uniform(0, 2) ? 1 : -1;
63
}
64
if( flags & REAL_GAMMA )
65
gamma = Scalar::all(gamma[0]);
66
}
67
68
if( depth == CV_32F )
69
{
70
Mat fl, db;
71
72
db = Mat(1, 1, CV_64F, &alpha);
73
db.convertTo(fl, CV_32F);
74
fl.convertTo(db, CV_64F);
75
76
db = Mat(1, 1, CV_64F, &beta);
77
db.convertTo(fl, CV_32F);
78
fl.convertTo(db, CV_64F);
79
80
db = Mat(1, 4, CV_64F, &gamma[0]);
81
db.convertTo(fl, CV_32F);
82
fl.convertTo(db, CV_64F);
83
}
84
}
85
86
int ninputs;
87
int flags;
88
double alpha;
89
double beta;
90
Scalar gamma;
91
int context;
92
};
93
94
95
struct BaseAddOp : public BaseElemWiseOp
96
{
97
BaseAddOp(int _ninputs, int _flags, double _alpha, double _beta, Scalar _gamma=Scalar::all(0))
98
: BaseElemWiseOp(_ninputs, _flags, _alpha, _beta, _gamma) {}
99
100
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
101
{
102
Mat temp;
103
if( !mask.empty() )
104
{
105
cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, temp, src[0].type());
106
cvtest::copy(temp, dst, mask);
107
}
108
else
109
cvtest::add(src[0], alpha, src.size() > 1 ? src[1] : Mat(), beta, gamma, dst, src[0].type());
110
}
111
};
112
113
114
struct AddOp : public BaseAddOp
115
{
116
AddOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)) {}
117
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
118
{
119
if( mask.empty() )
120
cv::add(src[0], src[1], dst);
121
else
122
cv::add(src[0], src[1], dst, mask);
123
}
124
};
125
126
127
struct SubOp : public BaseAddOp
128
{
129
SubOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, -1, Scalar::all(0)) {}
130
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
131
{
132
if( mask.empty() )
133
cv::subtract(src[0], src[1], dst);
134
else
135
cv::subtract(src[0], src[1], dst, mask);
136
}
137
};
138
139
140
struct AddSOp : public BaseAddOp
141
{
142
AddSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, 1, 0, Scalar::all(0)) {}
143
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
144
{
145
if( mask.empty() )
146
cv::add(src[0], gamma, dst);
147
else
148
cv::add(src[0], gamma, dst, mask);
149
}
150
};
151
152
153
struct SubRSOp : public BaseAddOp
154
{
155
SubRSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA+SUPPORT_MASK, -1, 0, Scalar::all(0)) {}
156
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
157
{
158
if( mask.empty() )
159
cv::subtract(gamma, src[0], dst);
160
else
161
cv::subtract(gamma, src[0], dst, mask);
162
}
163
};
164
165
166
struct ScaleAddOp : public BaseAddOp
167
{
168
ScaleAddOp() : BaseAddOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
169
void op(const vector<Mat>& src, Mat& dst, const Mat&)
170
{
171
cv::scaleAdd(src[0], alpha, src[1], dst);
172
}
173
double getMaxErr(int depth)
174
{
175
return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-4 : 1e-12;
176
}
177
};
178
179
180
struct AddWeightedOp : public BaseAddOp
181
{
182
AddWeightedOp() : BaseAddOp(2, REAL_GAMMA, 1, 1, Scalar::all(0)) {}
183
void op(const vector<Mat>& src, Mat& dst, const Mat&)
184
{
185
cv::addWeighted(src[0], alpha, src[1], beta, gamma[0], dst);
186
}
187
double getMaxErr(int depth)
188
{
189
return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-10;
190
}
191
};
192
193
struct MulOp : public BaseElemWiseOp
194
{
195
MulOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
196
void getValueRange(int depth, double& minval, double& maxval)
197
{
198
minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
199
maxval = depth < CV_32S ? cvtest::getMaxVal(depth) : depth == CV_32S ? 1000000 : 1000.;
200
minval = std::max(minval, -30000.);
201
maxval = std::min(maxval, 30000.);
202
}
203
void op(const vector<Mat>& src, Mat& dst, const Mat&)
204
{
205
cv::multiply(src[0], src[1], dst, alpha);
206
}
207
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
208
{
209
cvtest::multiply(src[0], src[1], dst, alpha);
210
}
211
double getMaxErr(int depth)
212
{
213
return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
214
}
215
};
216
217
struct DivOp : public BaseElemWiseOp
218
{
219
DivOp() : BaseElemWiseOp(2, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
220
void op(const vector<Mat>& src, Mat& dst, const Mat&)
221
{
222
cv::divide(src[0], src[1], dst, alpha);
223
}
224
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
225
{
226
cvtest::divide(src[0], src[1], dst, alpha);
227
}
228
double getMaxErr(int depth)
229
{
230
return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
231
}
232
};
233
234
struct RecipOp : public BaseElemWiseOp
235
{
236
RecipOp() : BaseElemWiseOp(1, FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
237
void op(const vector<Mat>& src, Mat& dst, const Mat&)
238
{
239
cv::divide(alpha, src[0], dst);
240
}
241
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
242
{
243
cvtest::divide(Mat(), src[0], dst, alpha);
244
}
245
double getMaxErr(int depth)
246
{
247
return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-5 : 1e-12;
248
}
249
};
250
251
struct AbsDiffOp : public BaseAddOp
252
{
253
AbsDiffOp() : BaseAddOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, -1, Scalar::all(0)) {}
254
void op(const vector<Mat>& src, Mat& dst, const Mat&)
255
{
256
absdiff(src[0], src[1], dst);
257
}
258
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
259
{
260
cvtest::add(src[0], 1, src[1], -1, Scalar::all(0), dst, src[0].type(), true);
261
}
262
};
263
264
struct AbsDiffSOp : public BaseAddOp
265
{
266
AbsDiffSOp() : BaseAddOp(1, FIX_ALPHA+FIX_BETA, 1, 0, Scalar::all(0)) {}
267
void op(const vector<Mat>& src, Mat& dst, const Mat&)
268
{
269
absdiff(src[0], gamma, dst);
270
}
271
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
272
{
273
cvtest::add(src[0], 1, Mat(), 0, -gamma, dst, src[0].type(), true);
274
}
275
};
276
277
struct LogicOp : public BaseElemWiseOp
278
{
279
LogicOp(char _opcode) : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK, 1, 1, Scalar::all(0)), opcode(_opcode) {}
280
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
281
{
282
if( opcode == '&' )
283
cv::bitwise_and(src[0], src[1], dst, mask);
284
else if( opcode == '|' )
285
cv::bitwise_or(src[0], src[1], dst, mask);
286
else
287
cv::bitwise_xor(src[0], src[1], dst, mask);
288
}
289
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
290
{
291
Mat temp;
292
if( !mask.empty() )
293
{
294
cvtest::logicOp(src[0], src[1], temp, opcode);
295
cvtest::copy(temp, dst, mask);
296
}
297
else
298
cvtest::logicOp(src[0], src[1], dst, opcode);
299
}
300
double getMaxErr(int)
301
{
302
return 0;
303
}
304
char opcode;
305
};
306
307
struct LogicSOp : public BaseElemWiseOp
308
{
309
LogicSOp(char _opcode)
310
: BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+(_opcode != '~' ? SUPPORT_MASK : 0), 1, 1, Scalar::all(0)), opcode(_opcode) {}
311
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
312
{
313
if( opcode == '&' )
314
cv::bitwise_and(src[0], gamma, dst, mask);
315
else if( opcode == '|' )
316
cv::bitwise_or(src[0], gamma, dst, mask);
317
else if( opcode == '^' )
318
cv::bitwise_xor(src[0], gamma, dst, mask);
319
else
320
cv::bitwise_not(src[0], dst);
321
}
322
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
323
{
324
Mat temp;
325
if( !mask.empty() )
326
{
327
cvtest::logicOp(src[0], gamma, temp, opcode);
328
cvtest::copy(temp, dst, mask);
329
}
330
else
331
cvtest::logicOp(src[0], gamma, dst, opcode);
332
}
333
double getMaxErr(int)
334
{
335
return 0;
336
}
337
char opcode;
338
};
339
340
struct MinOp : public BaseElemWiseOp
341
{
342
MinOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
343
void op(const vector<Mat>& src, Mat& dst, const Mat&)
344
{
345
cv::min(src[0], src[1], dst);
346
}
347
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
348
{
349
cvtest::min(src[0], src[1], dst);
350
}
351
double getMaxErr(int)
352
{
353
return 0;
354
}
355
};
356
357
struct MaxOp : public BaseElemWiseOp
358
{
359
MaxOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
360
void op(const vector<Mat>& src, Mat& dst, const Mat&)
361
{
362
cv::max(src[0], src[1], dst);
363
}
364
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
365
{
366
cvtest::max(src[0], src[1], dst);
367
}
368
double getMaxErr(int)
369
{
370
return 0;
371
}
372
};
373
374
struct MinSOp : public BaseElemWiseOp
375
{
376
MinSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}
377
void op(const vector<Mat>& src, Mat& dst, const Mat&)
378
{
379
cv::min(src[0], gamma[0], dst);
380
}
381
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
382
{
383
cvtest::min(src[0], gamma[0], dst);
384
}
385
double getMaxErr(int)
386
{
387
return 0;
388
}
389
};
390
391
struct MaxSOp : public BaseElemWiseOp
392
{
393
MaxSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}
394
void op(const vector<Mat>& src, Mat& dst, const Mat&)
395
{
396
cv::max(src[0], gamma[0], dst);
397
}
398
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
399
{
400
cvtest::max(src[0], gamma[0], dst);
401
}
402
double getMaxErr(int)
403
{
404
return 0;
405
}
406
};
407
408
struct CmpOp : public BaseElemWiseOp
409
{
410
CmpOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) { cmpop = 0; }
411
void generateScalars(int depth, RNG& rng)
412
{
413
BaseElemWiseOp::generateScalars(depth, rng);
414
cmpop = rng.uniform(0, 6);
415
}
416
void op(const vector<Mat>& src, Mat& dst, const Mat&)
417
{
418
cv::compare(src[0], src[1], dst, cmpop);
419
}
420
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
421
{
422
cvtest::compare(src[0], src[1], dst, cmpop);
423
}
424
int getRandomType(RNG& rng)
425
{
426
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1);
427
}
428
429
double getMaxErr(int)
430
{
431
return 0;
432
}
433
int cmpop;
434
};
435
436
struct CmpSOp : public BaseElemWiseOp
437
{
438
CmpSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) { cmpop = 0; }
439
void generateScalars(int depth, RNG& rng)
440
{
441
BaseElemWiseOp::generateScalars(depth, rng);
442
cmpop = rng.uniform(0, 6);
443
if( depth < CV_32F )
444
gamma[0] = cvRound(gamma[0]);
445
}
446
void op(const vector<Mat>& src, Mat& dst, const Mat&)
447
{
448
cv::compare(src[0], gamma[0], dst, cmpop);
449
}
450
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
451
{
452
cvtest::compare(src[0], gamma[0], dst, cmpop);
453
}
454
int getRandomType(RNG& rng)
455
{
456
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1);
457
}
458
double getMaxErr(int)
459
{
460
return 0;
461
}
462
int cmpop;
463
};
464
465
466
struct CopyOp : public BaseElemWiseOp
467
{
468
CopyOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SUPPORT_MULTICHANNELMASK, 1, 1, Scalar::all(0)) { }
469
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
470
{
471
src[0].copyTo(dst, mask);
472
}
473
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
474
{
475
cvtest::copy(src[0], dst, mask);
476
}
477
int getRandomType(RNG& rng)
478
{
479
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_16F, 1, ARITHM_MAX_CHANNELS);
480
}
481
double getMaxErr(int)
482
{
483
return 0;
484
}
485
};
486
487
488
struct SetOp : public BaseElemWiseOp
489
{
490
SetOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+SUPPORT_MASK+SUPPORT_MULTICHANNELMASK, 1, 1, Scalar::all(0)) {}
491
void op(const vector<Mat>&, Mat& dst, const Mat& mask)
492
{
493
dst.setTo(gamma, mask);
494
}
495
void refop(const vector<Mat>&, Mat& dst, const Mat& mask)
496
{
497
cvtest::set(dst, gamma, mask);
498
}
499
int getRandomType(RNG& rng)
500
{
501
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_16F, 1, ARITHM_MAX_CHANNELS);
502
}
503
double getMaxErr(int)
504
{
505
return 0;
506
}
507
};
508
509
template<typename _Tp, typename _WTp> static void
510
inRangeS_(const _Tp* src, const _WTp* a, const _WTp* b, uchar* dst, size_t total, int cn)
511
{
512
size_t i;
513
int c;
514
for( i = 0; i < total; i++ )
515
{
516
_Tp val = src[i*cn];
517
dst[i] = (a[0] <= val && val <= b[0]) ? uchar(255) : 0;
518
}
519
for( c = 1; c < cn; c++ )
520
{
521
for( i = 0; i < total; i++ )
522
{
523
_Tp val = src[i*cn + c];
524
dst[i] = a[c] <= val && val <= b[c] ? dst[i] : 0;
525
}
526
}
527
}
528
529
template<typename _Tp> static void inRange_(const _Tp* src, const _Tp* a, const _Tp* b, uchar* dst, size_t total, int cn)
530
{
531
size_t i;
532
int c;
533
for( i = 0; i < total; i++ )
534
{
535
_Tp val = src[i*cn];
536
dst[i] = a[i*cn] <= val && val <= b[i*cn] ? 255 : 0;
537
}
538
for( c = 1; c < cn; c++ )
539
{
540
for( i = 0; i < total; i++ )
541
{
542
_Tp val = src[i*cn + c];
543
dst[i] = a[i*cn + c] <= val && val <= b[i*cn + c] ? dst[i] : 0;
544
}
545
}
546
}
547
548
namespace reference {
549
550
static void inRange(const Mat& src, const Mat& lb, const Mat& rb, Mat& dst)
551
{
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};
556
Mat planes[4];
557
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();
562
563
for( i = 0; i < nplanes; i++, ++it )
564
{
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();
569
570
switch( depth )
571
{
572
case CV_8U:
573
inRange_((const uchar*)sptr, (const uchar*)aptr, (const uchar*)bptr, dptr, total, cn);
574
break;
575
case CV_8S:
576
inRange_((const schar*)sptr, (const schar*)aptr, (const schar*)bptr, dptr, total, cn);
577
break;
578
case CV_16U:
579
inRange_((const ushort*)sptr, (const ushort*)aptr, (const ushort*)bptr, dptr, total, cn);
580
break;
581
case CV_16S:
582
inRange_((const short*)sptr, (const short*)aptr, (const short*)bptr, dptr, total, cn);
583
break;
584
case CV_32S:
585
inRange_((const int*)sptr, (const int*)aptr, (const int*)bptr, dptr, total, cn);
586
break;
587
case CV_32F:
588
inRange_((const float*)sptr, (const float*)aptr, (const float*)bptr, dptr, total, cn);
589
break;
590
case CV_64F:
591
inRange_((const double*)sptr, (const double*)aptr, (const double*)bptr, dptr, total, cn);
592
break;
593
default:
594
CV_Error(CV_StsUnsupportedFormat, "");
595
}
596
}
597
}
598
599
static void inRangeS(const Mat& src, const Scalar& lb, const Scalar& rb, Mat& dst)
600
{
601
dst.create( src.dims, &src.size[0], CV_8U );
602
const Mat *arrays[]={&src, &dst, 0};
603
Mat planes[2];
604
605
NAryMatIterator it(arrays, planes);
606
size_t total = planes[0].total();
607
size_t i, nplanes = it.nplanes;
608
int depth = src.depth(), cn = src.channels();
609
union { double d[4]; float f[4]; int i[4];} lbuf, rbuf;
610
int wtype = CV_MAKETYPE(depth <= CV_32S ? CV_32S : depth, cn);
611
scalarToRawData(lb, lbuf.d, wtype, cn);
612
scalarToRawData(rb, rbuf.d, wtype, cn);
613
614
for( i = 0; i < nplanes; i++, ++it )
615
{
616
const uchar* sptr = planes[0].ptr();
617
uchar* dptr = planes[1].ptr();
618
619
switch( depth )
620
{
621
case CV_8U:
622
inRangeS_((const uchar*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
623
break;
624
case CV_8S:
625
inRangeS_((const schar*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
626
break;
627
case CV_16U:
628
inRangeS_((const ushort*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
629
break;
630
case CV_16S:
631
inRangeS_((const short*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
632
break;
633
case CV_32S:
634
inRangeS_((const int*)sptr, lbuf.i, rbuf.i, dptr, total, cn);
635
break;
636
case CV_32F:
637
inRangeS_((const float*)sptr, lbuf.f, rbuf.f, dptr, total, cn);
638
break;
639
case CV_64F:
640
inRangeS_((const double*)sptr, lbuf.d, rbuf.d, dptr, total, cn);
641
break;
642
default:
643
CV_Error(CV_StsUnsupportedFormat, "");
644
}
645
}
646
}
647
648
} // namespace
649
CVTEST_GUARD_SYMBOL(inRange);
650
651
struct InRangeSOp : public BaseElemWiseOp
652
{
653
InRangeSOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {}
654
void op(const vector<Mat>& src, Mat& dst, const Mat&)
655
{
656
cv::inRange(src[0], gamma, gamma1, dst);
657
}
658
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
659
{
660
reference::inRangeS(src[0], gamma, gamma1, dst);
661
}
662
double getMaxErr(int)
663
{
664
return 0;
665
}
666
void generateScalars(int depth, RNG& rng)
667
{
668
BaseElemWiseOp::generateScalars(depth, rng);
669
Scalar temp = gamma;
670
BaseElemWiseOp::generateScalars(depth, rng);
671
for( int i = 0; i < 4; i++ )
672
{
673
gamma1[i] = std::max(gamma[i], temp[i]);
674
gamma[i] = std::min(gamma[i], temp[i]);
675
}
676
}
677
Scalar gamma1;
678
};
679
680
681
struct InRangeOp : public BaseElemWiseOp
682
{
683
InRangeOp() : BaseElemWiseOp(3, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
684
void op(const vector<Mat>& src, Mat& dst, const Mat&)
685
{
686
Mat lb, rb;
687
cvtest::min(src[1], src[2], lb);
688
cvtest::max(src[1], src[2], rb);
689
690
cv::inRange(src[0], lb, rb, dst);
691
}
692
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
693
{
694
Mat lb, rb;
695
cvtest::min(src[1], src[2], lb);
696
cvtest::max(src[1], src[2], rb);
697
698
reference::inRange(src[0], lb, rb, dst);
699
}
700
double getMaxErr(int)
701
{
702
return 0;
703
}
704
};
705
706
707
struct ConvertScaleOp : public BaseElemWiseOp
708
{
709
ConvertScaleOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), ddepth(0) { }
710
void op(const vector<Mat>& src, Mat& dst, const Mat&)
711
{
712
src[0].convertTo(dst, ddepth, alpha, gamma[0]);
713
}
714
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
715
{
716
cvtest::convert(src[0], dst, CV_MAKETYPE(ddepth, src[0].channels()), alpha, gamma[0]);
717
}
718
int getRandomType(RNG& rng)
719
{
720
int srctype = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
721
ddepth = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, 1);
722
return srctype;
723
}
724
double getMaxErr(int)
725
{
726
return ddepth <= CV_32S ? 2 : ddepth < CV_64F ? 1e-3 : 1e-12;
727
}
728
void generateScalars(int depth, RNG& rng)
729
{
730
if( rng.uniform(0, 2) )
731
BaseElemWiseOp::generateScalars(depth, rng);
732
else
733
{
734
alpha = 1;
735
gamma = Scalar::all(0);
736
}
737
}
738
int ddepth;
739
};
740
741
struct ConvertScaleFp16Op : public BaseElemWiseOp
742
{
743
ConvertScaleFp16Op() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)), nextRange(0) { }
744
void op(const vector<Mat>& src, Mat& dst, const Mat&)
745
{
746
Mat m;
747
convertFp16(src[0], m);
748
convertFp16(m, dst);
749
}
750
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
751
{
752
cvtest::copy(src[0], dst);
753
}
754
int getRandomType(RNG&)
755
{
756
// 0: FP32 -> FP16 -> FP32
757
// 1: FP16 -> FP32 -> FP16
758
int srctype = (nextRange & 1) == 0 ? CV_32F : CV_16S;
759
return srctype;
760
}
761
void getValueRange(int, double& minval, double& maxval)
762
{
763
// 0: FP32 -> FP16 -> FP32
764
// 1: FP16 -> FP32 -> FP16
765
if( (nextRange & 1) == 0 )
766
{
767
// largest integer number that fp16 can express exactly
768
maxval = 2048.f;
769
minval = -maxval;
770
}
771
else
772
{
773
// 0: positive number range
774
// 1: negative number range
775
if( (nextRange & 2) == 0 )
776
{
777
minval = 0; // 0x0000 +0
778
maxval = 31744; // 0x7C00 +Inf
779
}
780
else
781
{
782
minval = -32768; // 0x8000 -0
783
maxval = -1024; // 0xFC00 -Inf
784
}
785
}
786
}
787
double getMaxErr(int)
788
{
789
return 0.5f;
790
}
791
void generateScalars(int, RNG& rng)
792
{
793
nextRange = rng.next();
794
}
795
int nextRange;
796
};
797
798
struct ConvertScaleAbsOp : public BaseElemWiseOp
799
{
800
ConvertScaleAbsOp() : BaseElemWiseOp(1, FIX_BETA+REAL_GAMMA, 1, 1, Scalar::all(0)) {}
801
void op(const vector<Mat>& src, Mat& dst, const Mat&)
802
{
803
cv::convertScaleAbs(src[0], dst, alpha, gamma[0]);
804
}
805
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
806
{
807
cvtest::add(src[0], alpha, Mat(), 0, Scalar::all(gamma[0]), dst, CV_8UC(src[0].channels()), true);
808
}
809
int getRandomType(RNG& rng)
810
{
811
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1,
812
ninputs > 1 ? ARITHM_MAX_CHANNELS : 4);
813
}
814
double getMaxErr(int)
815
{
816
return 1;
817
}
818
void generateScalars(int depth, RNG& rng)
819
{
820
if( rng.uniform(0, 2) )
821
BaseElemWiseOp::generateScalars(depth, rng);
822
else
823
{
824
alpha = 1;
825
gamma = Scalar::all(0);
826
}
827
}
828
};
829
830
namespace reference {
831
832
static void flip(const Mat& src, Mat& dst, int flipcode)
833
{
834
CV_Assert(src.dims == 2);
835
dst.create(src.size(), src.type());
836
int i, j, k, esz = (int)src.elemSize(), width = src.cols*esz;
837
838
for( i = 0; i < dst.rows; i++ )
839
{
840
const uchar* sptr = src.ptr(flipcode == 1 ? i : dst.rows - i - 1);
841
uchar* dptr = dst.ptr(i);
842
if( flipcode == 0 )
843
memcpy(dptr, sptr, width);
844
else
845
{
846
for( j = 0; j < width; j += esz )
847
for( k = 0; k < esz; k++ )
848
dptr[j + k] = sptr[width - j - esz + k];
849
}
850
}
851
}
852
853
854
static void setIdentity(Mat& dst, const Scalar& s)
855
{
856
CV_Assert( dst.dims == 2 && dst.channels() <= 4 );
857
double buf[4];
858
scalarToRawData(s, buf, dst.type(), 0);
859
int i, k, esz = (int)dst.elemSize(), width = dst.cols*esz;
860
861
for( i = 0; i < dst.rows; i++ )
862
{
863
uchar* dptr = dst.ptr(i);
864
memset( dptr, 0, width );
865
if( i < dst.cols )
866
for( k = 0; k < esz; k++ )
867
dptr[i*esz + k] = ((uchar*)buf)[k];
868
}
869
}
870
871
} // namespace
872
873
struct FlipOp : public BaseElemWiseOp
874
{
875
FlipOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) { flipcode = 0; }
876
void getRandomSize(RNG& rng, vector<int>& size)
877
{
878
cvtest::randomSize(rng, 2, 2, ARITHM_MAX_SIZE_LOG, size);
879
}
880
void op(const vector<Mat>& src, Mat& dst, const Mat&)
881
{
882
cv::flip(src[0], dst, flipcode);
883
}
884
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
885
{
886
reference::flip(src[0], dst, flipcode);
887
}
888
void generateScalars(int, RNG& rng)
889
{
890
flipcode = rng.uniform(0, 3) - 1;
891
}
892
double getMaxErr(int)
893
{
894
return 0;
895
}
896
int flipcode;
897
};
898
899
struct TransposeOp : public BaseElemWiseOp
900
{
901
TransposeOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
902
void getRandomSize(RNG& rng, vector<int>& size)
903
{
904
cvtest::randomSize(rng, 2, 2, ARITHM_MAX_SIZE_LOG, size);
905
}
906
void op(const vector<Mat>& src, Mat& dst, const Mat&)
907
{
908
cv::transpose(src[0], dst);
909
}
910
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
911
{
912
cvtest::transpose(src[0], dst);
913
}
914
double getMaxErr(int)
915
{
916
return 0;
917
}
918
};
919
920
struct SetIdentityOp : public BaseElemWiseOp
921
{
922
SetIdentityOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA, 1, 1, Scalar::all(0)) {}
923
void getRandomSize(RNG& rng, vector<int>& size)
924
{
925
cvtest::randomSize(rng, 2, 2, ARITHM_MAX_SIZE_LOG, size);
926
}
927
void op(const vector<Mat>&, Mat& dst, const Mat&)
928
{
929
cv::setIdentity(dst, gamma);
930
}
931
void refop(const vector<Mat>&, Mat& dst, const Mat&)
932
{
933
reference::setIdentity(dst, gamma);
934
}
935
double getMaxErr(int)
936
{
937
return 0;
938
}
939
};
940
941
struct SetZeroOp : public BaseElemWiseOp
942
{
943
SetZeroOp() : BaseElemWiseOp(0, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
944
void op(const vector<Mat>&, Mat& dst, const Mat&)
945
{
946
dst = Scalar::all(0);
947
}
948
void refop(const vector<Mat>&, Mat& dst, const Mat&)
949
{
950
cvtest::set(dst, Scalar::all(0));
951
}
952
double getMaxErr(int)
953
{
954
return 0;
955
}
956
};
957
958
namespace reference {
959
static void exp(const Mat& src, Mat& dst)
960
{
961
dst.create( src.dims, &src.size[0], src.type() );
962
const Mat *arrays[]={&src, &dst, 0};
963
Mat planes[2];
964
965
NAryMatIterator it(arrays, planes);
966
size_t j, total = planes[0].total()*src.channels();
967
size_t i, nplanes = it.nplanes;
968
int depth = src.depth();
969
970
for( i = 0; i < nplanes; i++, ++it )
971
{
972
const uchar* sptr = planes[0].ptr();
973
uchar* dptr = planes[1].ptr();
974
975
if( depth == CV_32F )
976
{
977
for( j = 0; j < total; j++ )
978
((float*)dptr)[j] = std::exp(((const float*)sptr)[j]);
979
}
980
else if( depth == CV_64F )
981
{
982
for( j = 0; j < total; j++ )
983
((double*)dptr)[j] = std::exp(((const double*)sptr)[j]);
984
}
985
}
986
}
987
988
static void log(const Mat& src, Mat& dst)
989
{
990
dst.create( src.dims, &src.size[0], src.type() );
991
const Mat *arrays[]={&src, &dst, 0};
992
Mat planes[2];
993
994
NAryMatIterator it(arrays, planes);
995
size_t j, total = planes[0].total()*src.channels();
996
size_t i, nplanes = it.nplanes;
997
int depth = src.depth();
998
999
for( i = 0; i < nplanes; i++, ++it )
1000
{
1001
const uchar* sptr = planes[0].ptr();
1002
uchar* dptr = planes[1].ptr();
1003
1004
if( depth == CV_32F )
1005
{
1006
for( j = 0; j < total; j++ )
1007
((float*)dptr)[j] = (float)std::log(fabs(((const float*)sptr)[j]));
1008
}
1009
else if( depth == CV_64F )
1010
{
1011
for( j = 0; j < total; j++ )
1012
((double*)dptr)[j] = std::log(fabs(((const double*)sptr)[j]));
1013
}
1014
}
1015
}
1016
1017
} // namespace
1018
1019
struct ExpOp : public BaseElemWiseOp
1020
{
1021
ExpOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
1022
int getRandomType(RNG& rng)
1023
{
1024
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS);
1025
}
1026
void getValueRange(int depth, double& minval, double& maxval)
1027
{
1028
maxval = depth == CV_32F ? 50 : 100;
1029
minval = -maxval;
1030
}
1031
void op(const vector<Mat>& src, Mat& dst, const Mat&)
1032
{
1033
cv::exp(src[0], dst);
1034
}
1035
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1036
{
1037
reference::exp(src[0], dst);
1038
}
1039
double getMaxErr(int depth)
1040
{
1041
return depth == CV_32F ? 1e-5 : 1e-12;
1042
}
1043
};
1044
1045
1046
struct LogOp : public BaseElemWiseOp
1047
{
1048
LogOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}
1049
int getRandomType(RNG& rng)
1050
{
1051
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS);
1052
}
1053
void getValueRange(int depth, double& minval, double& maxval)
1054
{
1055
maxval = depth == CV_32F ? 50 : 100;
1056
minval = -maxval;
1057
}
1058
void op(const vector<Mat>& src, Mat& dst, const Mat&)
1059
{
1060
Mat temp;
1061
reference::exp(src[0], temp);
1062
cv::log(temp, dst);
1063
}
1064
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1065
{
1066
Mat temp;
1067
reference::exp(src[0], temp);
1068
reference::log(temp, dst);
1069
}
1070
double getMaxErr(int depth)
1071
{
1072
return depth == CV_32F ? 1e-5 : 1e-12;
1073
}
1074
};
1075
1076
1077
namespace reference {
1078
static void cartToPolar(const Mat& mx, const Mat& my, Mat& mmag, Mat& mangle, bool angleInDegrees)
1079
{
1080
CV_Assert( (mx.type() == CV_32F || mx.type() == CV_64F) &&
1081
mx.type() == my.type() && mx.size == my.size );
1082
mmag.create( mx.dims, &mx.size[0], mx.type() );
1083
mangle.create( mx.dims, &mx.size[0], mx.type() );
1084
const Mat *arrays[]={&mx, &my, &mmag, &mangle, 0};
1085
Mat planes[4];
1086
1087
NAryMatIterator it(arrays, planes);
1088
size_t j, total = planes[0].total();
1089
size_t i, nplanes = it.nplanes;
1090
int depth = mx.depth();
1091
double scale = angleInDegrees ? 180/CV_PI : 1;
1092
1093
for( i = 0; i < nplanes; i++, ++it )
1094
{
1095
if( depth == CV_32F )
1096
{
1097
const float* xptr = planes[0].ptr<float>();
1098
const float* yptr = planes[1].ptr<float>();
1099
float* mptr = planes[2].ptr<float>();
1100
float* aptr = planes[3].ptr<float>();
1101
1102
for( j = 0; j < total; j++ )
1103
{
1104
mptr[j] = std::sqrt(xptr[j]*xptr[j] + yptr[j]*yptr[j]);
1105
double a = atan2((double)yptr[j], (double)xptr[j]);
1106
if( a < 0 ) a += CV_PI*2;
1107
aptr[j] = (float)(a*scale);
1108
}
1109
}
1110
else
1111
{
1112
const double* xptr = planes[0].ptr<double>();
1113
const double* yptr = planes[1].ptr<double>();
1114
double* mptr = planes[2].ptr<double>();
1115
double* aptr = planes[3].ptr<double>();
1116
1117
for( j = 0; j < total; j++ )
1118
{
1119
mptr[j] = std::sqrt(xptr[j]*xptr[j] + yptr[j]*yptr[j]);
1120
double a = atan2(yptr[j], xptr[j]);
1121
if( a < 0 ) a += CV_PI*2;
1122
aptr[j] = a*scale;
1123
}
1124
}
1125
}
1126
}
1127
1128
} // namespace
1129
1130
struct CartToPolarToCartOp : public BaseElemWiseOp
1131
{
1132
CartToPolarToCartOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0))
1133
{
1134
context = 3;
1135
angleInDegrees = true;
1136
}
1137
int getRandomType(RNG& rng)
1138
{
1139
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_FLT, 1, 1);
1140
}
1141
void op(const vector<Mat>& src, Mat& dst, const Mat&)
1142
{
1143
Mat mag, angle, x, y;
1144
1145
cv::cartToPolar(src[0], src[1], mag, angle, angleInDegrees);
1146
cv::polarToCart(mag, angle, x, y, angleInDegrees);
1147
1148
Mat msrc[] = {mag, angle, x, y};
1149
int pairs[] = {0, 0, 1, 1, 2, 2, 3, 3};
1150
dst.create(src[0].dims, src[0].size, CV_MAKETYPE(src[0].depth(), 4));
1151
cv::mixChannels(msrc, 4, &dst, 1, pairs, 4);
1152
}
1153
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1154
{
1155
Mat mag, angle;
1156
reference::cartToPolar(src[0], src[1], mag, angle, angleInDegrees);
1157
Mat msrc[] = {mag, angle, src[0], src[1]};
1158
int pairs[] = {0, 0, 1, 1, 2, 2, 3, 3};
1159
dst.create(src[0].dims, src[0].size, CV_MAKETYPE(src[0].depth(), 4));
1160
cv::mixChannels(msrc, 4, &dst, 1, pairs, 4);
1161
}
1162
void generateScalars(int, RNG& rng)
1163
{
1164
angleInDegrees = rng.uniform(0, 2) != 0;
1165
}
1166
double getMaxErr(int)
1167
{
1168
return 1e-3;
1169
}
1170
bool angleInDegrees;
1171
};
1172
1173
1174
struct MeanOp : public BaseElemWiseOp
1175
{
1176
MeanOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1177
{
1178
context = 3;
1179
};
1180
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1181
{
1182
dst.create(1, 1, CV_64FC4);
1183
dst.at<Scalar>(0,0) = cv::mean(src[0], mask);
1184
}
1185
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1186
{
1187
dst.create(1, 1, CV_64FC4);
1188
dst.at<Scalar>(0,0) = cvtest::mean(src[0], mask);
1189
}
1190
double getMaxErr(int)
1191
{
1192
return 1e-5;
1193
}
1194
};
1195
1196
1197
struct SumOp : public BaseElemWiseOp
1198
{
1199
SumOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1200
{
1201
context = 3;
1202
};
1203
void op(const vector<Mat>& src, Mat& dst, const Mat&)
1204
{
1205
dst.create(1, 1, CV_64FC4);
1206
dst.at<Scalar>(0,0) = cv::sum(src[0]);
1207
}
1208
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
1209
{
1210
dst.create(1, 1, CV_64FC4);
1211
dst.at<Scalar>(0,0) = cvtest::mean(src[0])*(double)src[0].total();
1212
}
1213
double getMaxErr(int)
1214
{
1215
return 1e-5;
1216
}
1217
};
1218
1219
1220
struct CountNonZeroOp : public BaseElemWiseOp
1221
{
1222
CountNonZeroOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SCALAR_OUTPUT+SUPPORT_MASK, 1, 1, Scalar::all(0))
1223
{}
1224
int getRandomType(RNG& rng)
1225
{
1226
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL, 1, 1);
1227
}
1228
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1229
{
1230
Mat temp;
1231
src[0].copyTo(temp);
1232
if( !mask.empty() )
1233
temp.setTo(Scalar::all(0), mask);
1234
dst.create(1, 1, CV_32S);
1235
dst.at<int>(0,0) = cv::countNonZero(temp);
1236
}
1237
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1238
{
1239
Mat temp;
1240
cvtest::compare(src[0], 0, temp, CMP_NE);
1241
if( !mask.empty() )
1242
cvtest::set(temp, Scalar::all(0), mask);
1243
dst.create(1, 1, CV_32S);
1244
dst.at<int>(0,0) = saturate_cast<int>(cvtest::mean(temp)[0]/255*temp.total());
1245
}
1246
double getMaxErr(int)
1247
{
1248
return 0;
1249
}
1250
};
1251
1252
1253
struct MeanStdDevOp : public BaseElemWiseOp
1254
{
1255
Scalar sqmeanRef;
1256
int cn;
1257
1258
MeanStdDevOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1259
{
1260
cn = 0;
1261
context = 7;
1262
};
1263
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1264
{
1265
dst.create(1, 2, CV_64FC4);
1266
cv::meanStdDev(src[0], dst.at<Scalar>(0,0), dst.at<Scalar>(0,1), mask);
1267
}
1268
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1269
{
1270
Mat temp;
1271
cvtest::convert(src[0], temp, CV_64F);
1272
cvtest::multiply(temp, temp, temp);
1273
Scalar mean = cvtest::mean(src[0], mask);
1274
Scalar sqmean = cvtest::mean(temp, mask);
1275
1276
sqmeanRef = sqmean;
1277
cn = temp.channels();
1278
1279
for( int c = 0; c < 4; c++ )
1280
sqmean[c] = std::sqrt(std::max(sqmean[c] - mean[c]*mean[c], 0.));
1281
1282
dst.create(1, 2, CV_64FC4);
1283
dst.at<Scalar>(0,0) = mean;
1284
dst.at<Scalar>(0,1) = sqmean;
1285
}
1286
double getMaxErr(int)
1287
{
1288
CV_Assert(cn > 0);
1289
double err = sqmeanRef[0];
1290
for(int i = 1; i < cn; ++i)
1291
err = std::max(err, sqmeanRef[i]);
1292
return 3e-7 * err;
1293
}
1294
};
1295
1296
1297
struct NormOp : public BaseElemWiseOp
1298
{
1299
NormOp() : BaseElemWiseOp(2, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1300
{
1301
context = 1;
1302
normType = 0;
1303
};
1304
int getRandomType(RNG& rng)
1305
{
1306
int type = cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 4);
1307
for(;;)
1308
{
1309
normType = rng.uniform(1, 8);
1310
if( normType == NORM_INF || normType == NORM_L1 ||
1311
normType == NORM_L2 || normType == NORM_L2SQR ||
1312
normType == NORM_HAMMING || normType == NORM_HAMMING2 )
1313
break;
1314
}
1315
if( normType == NORM_HAMMING || normType == NORM_HAMMING2 )
1316
{
1317
type = CV_8U;
1318
}
1319
return type;
1320
}
1321
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1322
{
1323
dst.create(1, 2, CV_64FC1);
1324
dst.at<double>(0,0) = cv::norm(src[0], normType, mask);
1325
dst.at<double>(0,1) = cv::norm(src[0], src[1], normType, mask);
1326
}
1327
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1328
{
1329
dst.create(1, 2, CV_64FC1);
1330
dst.at<double>(0,0) = cvtest::norm(src[0], normType, mask);
1331
dst.at<double>(0,1) = cvtest::norm(src[0], src[1], normType, mask);
1332
}
1333
void generateScalars(int, RNG& /*rng*/)
1334
{
1335
}
1336
double getMaxErr(int)
1337
{
1338
return 1e-6;
1339
}
1340
int normType;
1341
};
1342
1343
1344
struct MinMaxLocOp : public BaseElemWiseOp
1345
{
1346
MinMaxLocOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA+SUPPORT_MASK+SCALAR_OUTPUT, 1, 1, Scalar::all(0))
1347
{
1348
context = ARITHM_MAX_NDIMS*2 + 2;
1349
};
1350
int getRandomType(RNG& rng)
1351
{
1352
return cvtest::randomType(rng, _OutputArray::DEPTH_MASK_ALL_BUT_8S, 1, 1);
1353
}
1354
void saveOutput(const vector<int>& minidx, const vector<int>& maxidx,
1355
double minval, double maxval, Mat& dst)
1356
{
1357
int i, ndims = (int)minidx.size();
1358
dst.create(1, ndims*2 + 2, CV_64FC1);
1359
1360
for( i = 0; i < ndims; i++ )
1361
{
1362
dst.at<double>(0,i) = minidx[i];
1363
dst.at<double>(0,i+ndims) = maxidx[i];
1364
}
1365
dst.at<double>(0,ndims*2) = minval;
1366
dst.at<double>(0,ndims*2+1) = maxval;
1367
}
1368
void op(const vector<Mat>& src, Mat& dst, const Mat& mask)
1369
{
1370
int ndims = src[0].dims;
1371
vector<int> minidx(ndims), maxidx(ndims);
1372
double minval=0, maxval=0;
1373
cv::minMaxIdx(src[0], &minval, &maxval, &minidx[0], &maxidx[0], mask);
1374
saveOutput(minidx, maxidx, minval, maxval, dst);
1375
}
1376
void refop(const vector<Mat>& src, Mat& dst, const Mat& mask)
1377
{
1378
int ndims=src[0].dims;
1379
vector<int> minidx(ndims), maxidx(ndims);
1380
double minval=0, maxval=0;
1381
cvtest::minMaxLoc(src[0], &minval, &maxval, &minidx, &maxidx, mask);
1382
saveOutput(minidx, maxidx, minval, maxval, dst);
1383
}
1384
double getMaxErr(int)
1385
{
1386
return 0;
1387
}
1388
};
1389
1390
1391
typedef Ptr<BaseElemWiseOp> ElemWiseOpPtr;
1392
class ElemWiseTest : public ::testing::TestWithParam<ElemWiseOpPtr> {};
1393
1394
TEST_P(ElemWiseTest, accuracy)
1395
{
1396
ElemWiseOpPtr op = GetParam();
1397
1398
int testIdx = 0;
1399
RNG rng((uint64)ARITHM_RNG_SEED);
1400
for( testIdx = 0; testIdx < ARITHM_NTESTS; testIdx++ )
1401
{
1402
vector<int> size;
1403
op->getRandomSize(rng, size);
1404
int type = op->getRandomType(rng);
1405
int depth = CV_MAT_DEPTH(type);
1406
bool haveMask = ((op->flags & BaseElemWiseOp::SUPPORT_MASK) != 0
1407
|| (op->flags & BaseElemWiseOp::SUPPORT_MULTICHANNELMASK) != 0) && rng.uniform(0, 4) == 0;
1408
1409
double minval=0, maxval=0;
1410
op->getValueRange(depth, minval, maxval);
1411
int i, ninputs = op->ninputs;
1412
vector<Mat> src(ninputs);
1413
for( i = 0; i < ninputs; i++ )
1414
src[i] = cvtest::randomMat(rng, size, type, minval, maxval, true);
1415
Mat dst0, dst, mask;
1416
if( haveMask ) {
1417
bool multiChannelMask = (op->flags & BaseElemWiseOp::SUPPORT_MULTICHANNELMASK) != 0
1418
&& rng.uniform(0, 2) == 0;
1419
int masktype = CV_8UC(multiChannelMask ? CV_MAT_CN(type) : 1);
1420
mask = cvtest::randomMat(rng, size, masktype, 0, 2, true);
1421
}
1422
1423
if( (haveMask || ninputs == 0) && !(op->flags & BaseElemWiseOp::SCALAR_OUTPUT))
1424
{
1425
dst0 = cvtest::randomMat(rng, size, type, minval, maxval, false);
1426
dst = cvtest::randomMat(rng, size, type, minval, maxval, true);
1427
cvtest::copy(dst, dst0);
1428
}
1429
op->generateScalars(depth, rng);
1430
1431
op->refop(src, dst0, mask);
1432
op->op(src, dst, mask);
1433
1434
double maxErr = op->getMaxErr(depth);
1435
ASSERT_PRED_FORMAT2(cvtest::MatComparator(maxErr, op->context), dst0, dst) << "\nsrc[0] ~ " <<
1436
cvtest::MatInfo(!src.empty() ? src[0] : Mat()) << "\ntestCase #" << testIdx << "\n";
1437
}
1438
}
1439
1440
1441
INSTANTIATE_TEST_CASE_P(Core_Copy, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new CopyOp)));
1442
INSTANTIATE_TEST_CASE_P(Core_Set, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SetOp)));
1443
INSTANTIATE_TEST_CASE_P(Core_SetZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SetZeroOp)));
1444
INSTANTIATE_TEST_CASE_P(Core_ConvertScale, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new ConvertScaleOp)));
1445
INSTANTIATE_TEST_CASE_P(Core_ConvertScaleFp16, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new ConvertScaleFp16Op)));
1446
INSTANTIATE_TEST_CASE_P(Core_ConvertScaleAbs, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new ConvertScaleAbsOp)));
1447
1448
INSTANTIATE_TEST_CASE_P(Core_Add, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new AddOp)));
1449
INSTANTIATE_TEST_CASE_P(Core_Sub, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SubOp)));
1450
INSTANTIATE_TEST_CASE_P(Core_AddS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new AddSOp)));
1451
INSTANTIATE_TEST_CASE_P(Core_SubRS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SubRSOp)));
1452
INSTANTIATE_TEST_CASE_P(Core_ScaleAdd, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new ScaleAddOp)));
1453
INSTANTIATE_TEST_CASE_P(Core_AddWeighted, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new AddWeightedOp)));
1454
INSTANTIATE_TEST_CASE_P(Core_AbsDiff, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new AbsDiffOp)));
1455
1456
1457
INSTANTIATE_TEST_CASE_P(Core_AbsDiffS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new AbsDiffSOp)));
1458
1459
INSTANTIATE_TEST_CASE_P(Core_And, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogicOp('&'))));
1460
INSTANTIATE_TEST_CASE_P(Core_AndS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogicSOp('&'))));
1461
INSTANTIATE_TEST_CASE_P(Core_Or, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogicOp('|'))));
1462
INSTANTIATE_TEST_CASE_P(Core_OrS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogicSOp('|'))));
1463
INSTANTIATE_TEST_CASE_P(Core_Xor, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogicOp('^'))));
1464
INSTANTIATE_TEST_CASE_P(Core_XorS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogicSOp('^'))));
1465
INSTANTIATE_TEST_CASE_P(Core_Not, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogicSOp('~'))));
1466
1467
INSTANTIATE_TEST_CASE_P(Core_Max, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MaxOp)));
1468
INSTANTIATE_TEST_CASE_P(Core_MaxS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MaxSOp)));
1469
INSTANTIATE_TEST_CASE_P(Core_Min, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MinOp)));
1470
INSTANTIATE_TEST_CASE_P(Core_MinS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MinSOp)));
1471
1472
INSTANTIATE_TEST_CASE_P(Core_Mul, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MulOp)));
1473
INSTANTIATE_TEST_CASE_P(Core_Div, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new DivOp)));
1474
INSTANTIATE_TEST_CASE_P(Core_Recip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new RecipOp)));
1475
1476
INSTANTIATE_TEST_CASE_P(Core_Cmp, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new CmpOp)));
1477
INSTANTIATE_TEST_CASE_P(Core_CmpS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new CmpSOp)));
1478
1479
INSTANTIATE_TEST_CASE_P(Core_InRangeS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new InRangeSOp)));
1480
INSTANTIATE_TEST_CASE_P(Core_InRange, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new InRangeOp)));
1481
1482
INSTANTIATE_TEST_CASE_P(Core_Flip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new FlipOp)));
1483
INSTANTIATE_TEST_CASE_P(Core_Transpose, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new TransposeOp)));
1484
INSTANTIATE_TEST_CASE_P(Core_SetIdentity, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SetIdentityOp)));
1485
1486
INSTANTIATE_TEST_CASE_P(Core_Exp, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new ExpOp)));
1487
INSTANTIATE_TEST_CASE_P(Core_Log, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new LogOp)));
1488
1489
INSTANTIATE_TEST_CASE_P(Core_CountNonZero, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new CountNonZeroOp)));
1490
INSTANTIATE_TEST_CASE_P(Core_Mean, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MeanOp)));
1491
INSTANTIATE_TEST_CASE_P(Core_MeanStdDev, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MeanStdDevOp)));
1492
INSTANTIATE_TEST_CASE_P(Core_Sum, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SumOp)));
1493
INSTANTIATE_TEST_CASE_P(Core_Norm, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new NormOp)));
1494
INSTANTIATE_TEST_CASE_P(Core_MinMaxLoc, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new MinMaxLocOp)));
1495
INSTANTIATE_TEST_CASE_P(Core_CartToPolarToCart, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new CartToPolarToCartOp)));
1496
1497
1498
TEST(Core_ArithmMask, uninitialized)
1499
{
1500
RNG& rng = theRNG();
1501
const int MAX_DIM=3;
1502
int sizes[MAX_DIM];
1503
for( int iter = 0; iter < 100; iter++ )
1504
{
1505
int dims = rng.uniform(1, MAX_DIM+1);
1506
int depth = rng.uniform(CV_8U, CV_64F+1);
1507
int cn = rng.uniform(1, 6);
1508
int type = CV_MAKETYPE(depth, cn);
1509
int op = rng.uniform(0, depth < CV_32F ? 5 : 2); // don't run binary operations between floating-point values
1510
int depth1 = op <= 1 ? CV_64F : depth;
1511
for (int k = 0; k < MAX_DIM; k++)
1512
{
1513
sizes[k] = k < dims ? rng.uniform(1, 30) : 0;
1514
}
1515
SCOPED_TRACE(cv::format("iter=%d dims=%d depth=%d cn=%d type=%d op=%d depth1=%d dims=[%d; %d; %d]",
1516
iter, dims, depth, cn, type, op, depth1, sizes[0], sizes[1], sizes[2]));
1517
1518
Mat a(dims, sizes, type), a1;
1519
Mat b(dims, sizes, type), b1;
1520
Mat mask(dims, sizes, CV_8U);
1521
Mat mask1;
1522
Mat c, d;
1523
1524
rng.fill(a, RNG::UNIFORM, 0, 100);
1525
rng.fill(b, RNG::UNIFORM, 0, 100);
1526
1527
// [-2,2) range means that the each generated random number
1528
// will be one of -2, -1, 0, 1. Saturated to [0,255], it will become
1529
// 0, 0, 0, 1 => the mask will be filled by ~25%.
1530
rng.fill(mask, RNG::UNIFORM, -2, 2);
1531
1532
a.convertTo(a1, depth1);
1533
b.convertTo(b1, depth1);
1534
// invert the mask
1535
cv::compare(mask, 0, mask1, CMP_EQ);
1536
a1.setTo(0, mask1);
1537
b1.setTo(0, mask1);
1538
1539
if( op == 0 )
1540
{
1541
cv::add(a, b, c, mask);
1542
cv::add(a1, b1, d);
1543
}
1544
else if( op == 1 )
1545
{
1546
cv::subtract(a, b, c, mask);
1547
cv::subtract(a1, b1, d);
1548
}
1549
else if( op == 2 )
1550
{
1551
cv::bitwise_and(a, b, c, mask);
1552
cv::bitwise_and(a1, b1, d);
1553
}
1554
else if( op == 3 )
1555
{
1556
cv::bitwise_or(a, b, c, mask);
1557
cv::bitwise_or(a1, b1, d);
1558
}
1559
else if( op == 4 )
1560
{
1561
cv::bitwise_xor(a, b, c, mask);
1562
cv::bitwise_xor(a1, b1, d);
1563
}
1564
Mat d1;
1565
d.convertTo(d1, depth);
1566
EXPECT_LE(cvtest::norm(c, d1, CV_C), DBL_EPSILON);
1567
}
1568
1569
Mat_<uchar> tmpSrc(100,100);
1570
tmpSrc = 124;
1571
Mat_<uchar> tmpMask(100,100);
1572
tmpMask = 255;
1573
Mat_<uchar> tmpDst(100,100);
1574
tmpDst = 2;
1575
tmpSrc.copyTo(tmpDst,tmpMask);
1576
}
1577
1578
TEST(Multiply, FloatingPointRounding)
1579
{
1580
cv::Mat src(1, 1, CV_8UC1, cv::Scalar::all(110)), dst;
1581
cv::Scalar s(147.286359696927, 1, 1 ,1);
1582
1583
cv::multiply(src, s, dst, 1, CV_16U);
1584
// with CV_32F this produce result 16202
1585
ASSERT_EQ(dst.at<ushort>(0,0), 16201);
1586
}
1587
1588
TEST(Core_Add, AddToColumnWhen3Rows)
1589
{
1590
cv::Mat m1 = (cv::Mat_<double>(3, 2) << 1, 2, 3, 4, 5, 6);
1591
m1.col(1) += 10;
1592
1593
cv::Mat m2 = (cv::Mat_<double>(3, 2) << 1, 12, 3, 14, 5, 16);
1594
1595
ASSERT_EQ(0, countNonZero(m1 - m2));
1596
}
1597
1598
TEST(Core_Add, AddToColumnWhen4Rows)
1599
{
1600
cv::Mat m1 = (cv::Mat_<double>(4, 2) << 1, 2, 3, 4, 5, 6, 7, 8);
1601
m1.col(1) += 10;
1602
1603
cv::Mat m2 = (cv::Mat_<double>(4, 2) << 1, 12, 3, 14, 5, 16, 7, 18);
1604
1605
ASSERT_EQ(0, countNonZero(m1 - m2));
1606
}
1607
1608
TEST(Core_round, CvRound)
1609
{
1610
ASSERT_EQ(2, cvRound(2.0));
1611
ASSERT_EQ(2, cvRound(2.1));
1612
ASSERT_EQ(-2, cvRound(-2.1));
1613
ASSERT_EQ(3, cvRound(2.8));
1614
ASSERT_EQ(-3, cvRound(-2.8));
1615
ASSERT_EQ(2, cvRound(2.5));
1616
ASSERT_EQ(4, cvRound(3.5));
1617
ASSERT_EQ(-2, cvRound(-2.5));
1618
ASSERT_EQ(-4, cvRound(-3.5));
1619
}
1620
1621
1622
typedef testing::TestWithParam<Size> Mul1;
1623
1624
TEST_P(Mul1, One)
1625
{
1626
Size size = GetParam();
1627
cv::Mat src(size, CV_32FC1, cv::Scalar::all(2)), dst,
1628
ref_dst(size, CV_32FC1, cv::Scalar::all(6));
1629
1630
cv::multiply(3, src, dst);
1631
1632
ASSERT_EQ(0, cvtest::norm(dst, ref_dst, cv::NORM_INF));
1633
}
1634
1635
INSTANTIATE_TEST_CASE_P(Arithm, Mul1, testing::Values(Size(2, 2), Size(1, 1)));
1636
1637
class SubtractOutputMatNotEmpty : public testing::TestWithParam< tuple<cv::Size, perf::MatType, perf::MatDepth, bool> >
1638
{
1639
public:
1640
cv::Size size;
1641
int src_type;
1642
int dst_depth;
1643
bool fixed;
1644
1645
void SetUp()
1646
{
1647
size = get<0>(GetParam());
1648
src_type = get<1>(GetParam());
1649
dst_depth = get<2>(GetParam());
1650
fixed = get<3>(GetParam());
1651
}
1652
};
1653
1654
TEST_P(SubtractOutputMatNotEmpty, Mat_Mat)
1655
{
1656
cv::Mat src1(size, src_type, cv::Scalar::all(16));
1657
cv::Mat src2(size, src_type, cv::Scalar::all(16));
1658
1659
cv::Mat dst;
1660
1661
if (!fixed)
1662
{
1663
cv::subtract(src1, src2, dst, cv::noArray(), dst_depth);
1664
}
1665
else
1666
{
1667
const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src1.channels()));
1668
cv::subtract(src1, src2, fixed_dst, cv::noArray(), dst_depth);
1669
dst = fixed_dst;
1670
dst_depth = fixed_dst.depth();
1671
}
1672
1673
ASSERT_FALSE(dst.empty());
1674
ASSERT_EQ(src1.size(), dst.size());
1675
ASSERT_EQ(dst_depth > 0 ? dst_depth : src1.depth(), dst.depth());
1676
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1677
}
1678
1679
TEST_P(SubtractOutputMatNotEmpty, Mat_Mat_WithMask)
1680
{
1681
cv::Mat src1(size, src_type, cv::Scalar::all(16));
1682
cv::Mat src2(size, src_type, cv::Scalar::all(16));
1683
cv::Mat mask(size, CV_8UC1, cv::Scalar::all(255));
1684
1685
cv::Mat dst;
1686
1687
if (!fixed)
1688
{
1689
cv::subtract(src1, src2, dst, mask, dst_depth);
1690
}
1691
else
1692
{
1693
const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src1.channels()));
1694
cv::subtract(src1, src2, fixed_dst, mask, dst_depth);
1695
dst = fixed_dst;
1696
dst_depth = fixed_dst.depth();
1697
}
1698
1699
ASSERT_FALSE(dst.empty());
1700
ASSERT_EQ(src1.size(), dst.size());
1701
ASSERT_EQ(dst_depth > 0 ? dst_depth : src1.depth(), dst.depth());
1702
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1703
}
1704
1705
TEST_P(SubtractOutputMatNotEmpty, Mat_Mat_Expr)
1706
{
1707
cv::Mat src1(size, src_type, cv::Scalar::all(16));
1708
cv::Mat src2(size, src_type, cv::Scalar::all(16));
1709
1710
cv::Mat dst = src1 - src2;
1711
1712
ASSERT_FALSE(dst.empty());
1713
ASSERT_EQ(src1.size(), dst.size());
1714
ASSERT_EQ(src1.depth(), dst.depth());
1715
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1716
}
1717
1718
TEST_P(SubtractOutputMatNotEmpty, Mat_Scalar)
1719
{
1720
cv::Mat src(size, src_type, cv::Scalar::all(16));
1721
1722
cv::Mat dst;
1723
1724
if (!fixed)
1725
{
1726
cv::subtract(src, cv::Scalar::all(16), dst, cv::noArray(), dst_depth);
1727
}
1728
else
1729
{
1730
const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1731
cv::subtract(src, cv::Scalar::all(16), fixed_dst, cv::noArray(), dst_depth);
1732
dst = fixed_dst;
1733
dst_depth = fixed_dst.depth();
1734
}
1735
1736
ASSERT_FALSE(dst.empty());
1737
ASSERT_EQ(src.size(), dst.size());
1738
ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1739
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1740
}
1741
1742
TEST_P(SubtractOutputMatNotEmpty, Mat_Scalar_WithMask)
1743
{
1744
cv::Mat src(size, src_type, cv::Scalar::all(16));
1745
cv::Mat mask(size, CV_8UC1, cv::Scalar::all(255));
1746
1747
cv::Mat dst;
1748
1749
if (!fixed)
1750
{
1751
cv::subtract(src, cv::Scalar::all(16), dst, mask, dst_depth);
1752
}
1753
else
1754
{
1755
const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1756
cv::subtract(src, cv::Scalar::all(16), fixed_dst, mask, dst_depth);
1757
dst = fixed_dst;
1758
dst_depth = fixed_dst.depth();
1759
}
1760
1761
ASSERT_FALSE(dst.empty());
1762
ASSERT_EQ(src.size(), dst.size());
1763
ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1764
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1765
}
1766
1767
TEST_P(SubtractOutputMatNotEmpty, Scalar_Mat)
1768
{
1769
cv::Mat src(size, src_type, cv::Scalar::all(16));
1770
1771
cv::Mat dst;
1772
1773
if (!fixed)
1774
{
1775
cv::subtract(cv::Scalar::all(16), src, dst, cv::noArray(), dst_depth);
1776
}
1777
else
1778
{
1779
const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1780
cv::subtract(cv::Scalar::all(16), src, fixed_dst, cv::noArray(), dst_depth);
1781
dst = fixed_dst;
1782
dst_depth = fixed_dst.depth();
1783
}
1784
1785
ASSERT_FALSE(dst.empty());
1786
ASSERT_EQ(src.size(), dst.size());
1787
ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1788
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1789
}
1790
1791
TEST_P(SubtractOutputMatNotEmpty, Scalar_Mat_WithMask)
1792
{
1793
cv::Mat src(size, src_type, cv::Scalar::all(16));
1794
cv::Mat mask(size, CV_8UC1, cv::Scalar::all(255));
1795
1796
cv::Mat dst;
1797
1798
if (!fixed)
1799
{
1800
cv::subtract(cv::Scalar::all(16), src, dst, mask, dst_depth);
1801
}
1802
else
1803
{
1804
const cv::Mat fixed_dst(size, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src.channels()));
1805
cv::subtract(cv::Scalar::all(16), src, fixed_dst, mask, dst_depth);
1806
dst = fixed_dst;
1807
dst_depth = fixed_dst.depth();
1808
}
1809
1810
ASSERT_FALSE(dst.empty());
1811
ASSERT_EQ(src.size(), dst.size());
1812
ASSERT_EQ(dst_depth > 0 ? dst_depth : src.depth(), dst.depth());
1813
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1814
}
1815
1816
TEST_P(SubtractOutputMatNotEmpty, Mat_Mat_3d)
1817
{
1818
int dims[] = {5, size.height, size.width};
1819
1820
cv::Mat src1(3, dims, src_type, cv::Scalar::all(16));
1821
cv::Mat src2(3, dims, src_type, cv::Scalar::all(16));
1822
1823
cv::Mat dst;
1824
1825
if (!fixed)
1826
{
1827
cv::subtract(src1, src2, dst, cv::noArray(), dst_depth);
1828
}
1829
else
1830
{
1831
const cv::Mat fixed_dst(3, dims, CV_MAKE_TYPE((dst_depth > 0 ? dst_depth : CV_16S), src1.channels()));
1832
cv::subtract(src1, src2, fixed_dst, cv::noArray(), dst_depth);
1833
dst = fixed_dst;
1834
dst_depth = fixed_dst.depth();
1835
}
1836
1837
ASSERT_FALSE(dst.empty());
1838
ASSERT_EQ(src1.dims, dst.dims);
1839
ASSERT_EQ(src1.size, dst.size);
1840
ASSERT_EQ(dst_depth > 0 ? dst_depth : src1.depth(), dst.depth());
1841
ASSERT_EQ(0, cv::countNonZero(dst.reshape(1)));
1842
}
1843
1844
INSTANTIATE_TEST_CASE_P(Arithm, SubtractOutputMatNotEmpty, testing::Combine(
1845
testing::Values(cv::Size(16, 16), cv::Size(13, 13), cv::Size(16, 13), cv::Size(13, 16)),
1846
testing::Values(perf::MatType(CV_8UC1), CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3),
1847
testing::Values(-1, CV_16S, CV_32S, CV_32F),
1848
testing::Bool()));
1849
1850
TEST(Core_FindNonZero, regression)
1851
{
1852
Mat img(10, 10, CV_8U, Scalar::all(0));
1853
vector<Point> pts, pts2(5);
1854
findNonZero(img, pts);
1855
findNonZero(img, pts2);
1856
ASSERT_TRUE(pts.empty() && pts2.empty());
1857
1858
RNG rng((uint64)-1);
1859
size_t nz = 0;
1860
for( int i = 0; i < 10; i++ )
1861
{
1862
int idx = rng.uniform(0, img.rows*img.cols);
1863
if( !img.data[idx] ) nz++;
1864
img.data[idx] = (uchar)rng.uniform(1, 256);
1865
}
1866
findNonZero(img, pts);
1867
ASSERT_TRUE(pts.size() == nz);
1868
1869
img.convertTo( img, CV_8S );
1870
pts.clear();
1871
findNonZero(img, pts);
1872
ASSERT_TRUE(pts.size() == nz);
1873
1874
img.convertTo( img, CV_16U );
1875
pts.resize(pts.size()*2);
1876
findNonZero(img, pts);
1877
ASSERT_TRUE(pts.size() == nz);
1878
1879
img.convertTo( img, CV_16S );
1880
pts.resize(pts.size()*3);
1881
findNonZero(img, pts);
1882
ASSERT_TRUE(pts.size() == nz);
1883
1884
img.convertTo( img, CV_32S );
1885
pts.resize(pts.size()*4);
1886
findNonZero(img, pts);
1887
ASSERT_TRUE(pts.size() == nz);
1888
1889
img.convertTo( img, CV_32F );
1890
pts.resize(pts.size()*5);
1891
findNonZero(img, pts);
1892
ASSERT_TRUE(pts.size() == nz);
1893
1894
img.convertTo( img, CV_64F );
1895
pts.clear();
1896
findNonZero(img, pts);
1897
ASSERT_TRUE(pts.size() == nz);
1898
}
1899
1900
TEST(Core_BoolVector, support)
1901
{
1902
std::vector<bool> test;
1903
int i, n = 205;
1904
int nz = 0;
1905
test.resize(n);
1906
for( i = 0; i < n; i++ )
1907
{
1908
test[i] = theRNG().uniform(0, 2) != 0;
1909
nz += (int)test[i];
1910
}
1911
ASSERT_EQ( nz, countNonZero(test) );
1912
ASSERT_FLOAT_EQ((float)nz/n, (float)(cv::mean(test)[0]));
1913
}
1914
1915
TEST(MinMaxLoc, Mat_UcharMax_Without_Loc)
1916
{
1917
Mat_<uchar> mat(50, 50);
1918
uchar iMaxVal = std::numeric_limits<uchar>::max();
1919
mat.setTo(iMaxVal);
1920
1921
double min, max;
1922
Point minLoc, maxLoc;
1923
1924
minMaxLoc(mat, &min, &max, &minLoc, &maxLoc, Mat());
1925
1926
ASSERT_EQ(iMaxVal, min);
1927
ASSERT_EQ(iMaxVal, max);
1928
1929
ASSERT_EQ(Point(0, 0), minLoc);
1930
ASSERT_EQ(Point(0, 0), maxLoc);
1931
}
1932
1933
TEST(MinMaxLoc, Mat_IntMax_Without_Mask)
1934
{
1935
Mat_<int> mat(50, 50);
1936
int iMaxVal = std::numeric_limits<int>::max();
1937
mat.setTo(iMaxVal);
1938
1939
double min, max;
1940
Point minLoc, maxLoc;
1941
1942
minMaxLoc(mat, &min, &max, &minLoc, &maxLoc, Mat());
1943
1944
ASSERT_EQ(iMaxVal, min);
1945
ASSERT_EQ(iMaxVal, max);
1946
1947
ASSERT_EQ(Point(0, 0), minLoc);
1948
ASSERT_EQ(Point(0, 0), maxLoc);
1949
}
1950
1951
TEST(Normalize, regression_5876_inplace_change_type)
1952
{
1953
double initial_values[] = {1, 2, 5, 4, 3};
1954
float result_values[] = {0, 0.25, 1, 0.75, 0.5};
1955
Mat m(Size(5, 1), CV_64FC1, initial_values);
1956
Mat result(Size(5, 1), CV_32FC1, result_values);
1957
1958
normalize(m, m, 1, 0, NORM_MINMAX, CV_32F);
1959
EXPECT_EQ(0, cvtest::norm(m, result, NORM_INF));
1960
}
1961
1962
TEST(Normalize, regression_6125)
1963
{
1964
float initial_values[] = {
1965
1888, 1692, 369, 263, 199,
1966
280, 326, 129, 143, 126,
1967
233, 221, 130, 126, 150,
1968
249, 575, 574, 63, 12
1969
};
1970
1971
Mat src(Size(20, 1), CV_32F, initial_values);
1972
float min = 0., max = 400.;
1973
normalize(src, src, 0, 400, NORM_MINMAX, CV_32F);
1974
for(int i = 0; i < 20; i++)
1975
{
1976
EXPECT_GE(src.at<float>(i), min) << "Value should be >= 0";
1977
EXPECT_LE(src.at<float>(i), max) << "Value should be <= 400";
1978
}
1979
}
1980
1981
TEST(MinMaxLoc, regression_4955_nans)
1982
{
1983
cv::Mat one_mat(2, 2, CV_32F, cv::Scalar(1));
1984
cv::minMaxLoc(one_mat, NULL, NULL, NULL, NULL);
1985
1986
cv::Mat nan_mat(2, 2, CV_32F, cv::Scalar(std::numeric_limits<float>::quiet_NaN()));
1987
cv::minMaxLoc(nan_mat, NULL, NULL, NULL, NULL);
1988
}
1989
1990
TEST(Subtract, scalarc1_matc3)
1991
{
1992
int scalar = 255;
1993
cv::Mat srcImage(5, 5, CV_8UC3, cv::Scalar::all(5)), destImage;
1994
cv::subtract(scalar, srcImage, destImage);
1995
1996
ASSERT_EQ(0, cv::norm(cv::Mat(5, 5, CV_8UC3, cv::Scalar::all(250)), destImage, cv::NORM_INF));
1997
}
1998
1999
TEST(Subtract, scalarc4_matc4)
2000
{
2001
cv::Scalar sc(255, 255, 255, 255);
2002
cv::Mat srcImage(5, 5, CV_8UC4, cv::Scalar::all(5)), destImage;
2003
cv::subtract(sc, srcImage, destImage);
2004
2005
ASSERT_EQ(0, cv::norm(cv::Mat(5, 5, CV_8UC4, cv::Scalar::all(250)), destImage, cv::NORM_INF));
2006
}
2007
2008
TEST(Compare, empty)
2009
{
2010
cv::Mat temp, dst1, dst2;
2011
EXPECT_NO_THROW(cv::compare(temp, temp, dst1, cv::CMP_EQ));
2012
EXPECT_TRUE(dst1.empty());
2013
EXPECT_THROW(dst2 = temp > 5, cv::Exception);
2014
}
2015
2016
TEST(Compare, regression_8999)
2017
{
2018
Mat_<double> A(4,1); A << 1, 3, 2, 4;
2019
Mat_<double> B(1,1); B << 2;
2020
Mat C;
2021
EXPECT_THROW(cv::compare(A, B, C, CMP_LT), cv::Exception);
2022
}
2023
2024
2025
TEST(Core_minMaxIdx, regression_9207_1)
2026
{
2027
const int rows = 4;
2028
const int cols = 3;
2029
uchar mask_[rows*cols] = {
2030
255, 255, 255,
2031
255, 0, 255,
2032
0, 255, 255,
2033
0, 0, 255
2034
};
2035
uchar src_[rows*cols] = {
2036
1, 1, 1,
2037
1, 1, 1,
2038
2, 1, 1,
2039
2, 2, 1
2040
};
2041
Mat mask(Size(cols, rows), CV_8UC1, mask_);
2042
Mat src(Size(cols, rows), CV_8UC1, src_);
2043
double minVal = -0.0, maxVal = -0.0;
2044
int minIdx[2] = { -2, -2 }, maxIdx[2] = { -2, -2 };
2045
cv::minMaxIdx(src, &minVal, &maxVal, minIdx, maxIdx, mask);
2046
EXPECT_EQ(0, minIdx[0]);
2047
EXPECT_EQ(0, minIdx[1]);
2048
EXPECT_EQ(0, maxIdx[0]);
2049
EXPECT_EQ(0, maxIdx[1]);
2050
}
2051
2052
2053
TEST(Core_minMaxIdx, regression_9207_2)
2054
{
2055
const int rows = 13;
2056
const int cols = 15;
2057
uchar mask_[rows*cols] = {
2058
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
2059
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
2060
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
2061
0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
2062
255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255,
2063
255, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 255,
2064
255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 255, 0,
2065
255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255, 0,
2066
255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 255, 255, 0,
2067
255, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0,
2068
255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2069
0, 255, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2070
0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2071
};
2072
uchar src_[15*13] = {
2073
5, 5, 5, 5, 5, 6, 5, 2, 0, 4, 6, 6, 4, 1, 0,
2074
6, 5, 4, 4, 5, 6, 6, 5, 2, 0, 4, 6, 5, 2, 0,
2075
3, 2, 1, 1, 2, 4, 6, 6, 4, 2, 3, 4, 4, 2, 0,
2076
1, 0, 0, 0, 0, 1, 4, 5, 4, 4, 4, 4, 3, 2, 0,
2077
0, 0, 0, 0, 0, 0, 2, 3, 4, 4, 4, 3, 2, 1, 0,
2078
0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 3, 2, 1, 0, 0,
2079
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1,
2080
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
2081
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1,
2082
0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 3, 3, 1, 0, 1,
2083
0, 0, 0, 0, 0, 0, 1, 4, 5, 6, 5, 4, 3, 2, 0,
2084
1, 0, 0, 0, 0, 0, 3, 5, 5, 4, 3, 4, 4, 3, 0,
2085
2, 0, 0, 0, 0, 2, 5, 6, 5, 2, 2, 5, 4, 3, 0
2086
};
2087
Mat mask(Size(cols, rows), CV_8UC1, mask_);
2088
Mat src(Size(cols, rows), CV_8UC1, src_);
2089
double minVal = -0.0, maxVal = -0.0;
2090
int minIdx[2] = { -2, -2 }, maxIdx[2] = { -2, -2 };
2091
cv::minMaxIdx(src, &minVal, &maxVal, minIdx, maxIdx, mask);
2092
EXPECT_EQ(0, minIdx[0]);
2093
EXPECT_EQ(14, minIdx[1]);
2094
EXPECT_EQ(0, maxIdx[0]);
2095
EXPECT_EQ(14, maxIdx[1]);
2096
}
2097
2098
TEST(Core_Set, regression_11044)
2099
{
2100
Mat testFloat(Size(3, 3), CV_32FC1);
2101
Mat testDouble(Size(3, 3), CV_64FC1);
2102
2103
testFloat.setTo(1);
2104
EXPECT_EQ(1, testFloat.at<float>(0,0));
2105
testFloat.setTo(std::numeric_limits<float>::infinity());
2106
EXPECT_EQ(std::numeric_limits<float>::infinity(), testFloat.at<float>(0, 0));
2107
testFloat.setTo(1);
2108
EXPECT_EQ(1, testFloat.at<float>(0, 0));
2109
testFloat.setTo(std::numeric_limits<double>::infinity());
2110
EXPECT_EQ(std::numeric_limits<float>::infinity(), testFloat.at<float>(0, 0));
2111
2112
testDouble.setTo(1);
2113
EXPECT_EQ(1, testDouble.at<double>(0, 0));
2114
testDouble.setTo(std::numeric_limits<float>::infinity());
2115
EXPECT_EQ(std::numeric_limits<double>::infinity(), testDouble.at<double>(0, 0));
2116
testDouble.setTo(1);
2117
EXPECT_EQ(1, testDouble.at<double>(0, 0));
2118
testDouble.setTo(std::numeric_limits<double>::infinity());
2119
EXPECT_EQ(std::numeric_limits<double>::infinity(), testDouble.at<double>(0, 0));
2120
2121
Mat testMask(Size(3, 3), CV_8UC1, Scalar(1));
2122
2123
testFloat.setTo(1);
2124
EXPECT_EQ(1, testFloat.at<float>(0, 0));
2125
testFloat.setTo(std::numeric_limits<float>::infinity(), testMask);
2126
EXPECT_EQ(std::numeric_limits<float>::infinity(), testFloat.at<float>(0, 0));
2127
testFloat.setTo(1);
2128
EXPECT_EQ(1, testFloat.at<float>(0, 0));
2129
testFloat.setTo(std::numeric_limits<double>::infinity(), testMask);
2130
EXPECT_EQ(std::numeric_limits<float>::infinity(), testFloat.at<float>(0, 0));
2131
2132
2133
testDouble.setTo(1);
2134
EXPECT_EQ(1, testDouble.at<double>(0, 0));
2135
testDouble.setTo(std::numeric_limits<float>::infinity(), testMask);
2136
EXPECT_EQ(std::numeric_limits<double>::infinity(), testDouble.at<double>(0, 0));
2137
testDouble.setTo(1);
2138
EXPECT_EQ(1, testDouble.at<double>(0, 0));
2139
testDouble.setTo(std::numeric_limits<double>::infinity(), testMask);
2140
EXPECT_EQ(std::numeric_limits<double>::infinity(), testDouble.at<double>(0, 0));
2141
}
2142
2143
TEST(Core_Norm, IPP_regression_NORM_L1_16UC3_small)
2144
{
2145
int cn = 3;
2146
Size sz(9, 4); // width < 16
2147
Mat a(sz, CV_MAKE_TYPE(CV_16U, cn), Scalar::all(1));
2148
Mat b(sz, CV_MAKE_TYPE(CV_16U, cn), Scalar::all(2));
2149
uchar mask_[9*4] = {
2150
255, 255, 255, 0, 255, 255, 0, 255, 0,
2151
0, 255, 0, 0, 255, 255, 255, 255, 0,
2152
0, 0, 0, 255, 0, 255, 0, 255, 255,
2153
0, 0, 255, 0, 255, 255, 255, 0, 255
2154
};
2155
Mat mask(sz, CV_8UC1, mask_);
2156
2157
EXPECT_EQ((double)9*4*cn, cv::norm(a, b, NORM_L1)); // without mask, IPP works well
2158
EXPECT_EQ((double)20*cn, cv::norm(a, b, NORM_L1, mask));
2159
}
2160
2161
2162
TEST(Core_ConvertTo, regression_12121)
2163
{
2164
{
2165
Mat src(4, 64, CV_32SC1, Scalar(-1));
2166
Mat dst;
2167
src.convertTo(dst, CV_8U);
2168
EXPECT_EQ(0, dst.at<uchar>(0, 0)) << "src=" << src.at<int>(0, 0);
2169
}
2170
2171
{
2172
Mat src(4, 64, CV_32SC1, Scalar(INT_MIN));
2173
Mat dst;
2174
src.convertTo(dst, CV_8U);
2175
EXPECT_EQ(0, dst.at<uchar>(0, 0)) << "src=" << src.at<int>(0, 0);
2176
}
2177
2178
{
2179
Mat src(4, 64, CV_32SC1, Scalar(INT_MIN + 32767));
2180
Mat dst;
2181
src.convertTo(dst, CV_8U);
2182
EXPECT_EQ(0, dst.at<uchar>(0, 0)) << "src=" << src.at<int>(0, 0);
2183
}
2184
2185
{
2186
Mat src(4, 64, CV_32SC1, Scalar(INT_MIN + 32768));
2187
Mat dst;
2188
src.convertTo(dst, CV_8U);
2189
EXPECT_EQ(0, dst.at<uchar>(0, 0)) << "src=" << src.at<int>(0, 0);
2190
}
2191
2192
{
2193
Mat src(4, 64, CV_32SC1, Scalar(32768));
2194
Mat dst;
2195
src.convertTo(dst, CV_8U);
2196
EXPECT_EQ(255, dst.at<uchar>(0, 0)) << "src=" << src.at<int>(0, 0);
2197
}
2198
2199
{
2200
Mat src(4, 64, CV_32SC1, Scalar(INT_MIN));
2201
Mat dst;
2202
src.convertTo(dst, CV_16U);
2203
EXPECT_EQ(0, dst.at<ushort>(0, 0)) << "src=" << src.at<int>(0, 0);
2204
}
2205
2206
{
2207
Mat src(4, 64, CV_32SC1, Scalar(INT_MIN + 32767));
2208
Mat dst;
2209
src.convertTo(dst, CV_16U);
2210
EXPECT_EQ(0, dst.at<ushort>(0, 0)) << "src=" << src.at<int>(0, 0);
2211
}
2212
2213
{
2214
Mat src(4, 64, CV_32SC1, Scalar(INT_MIN + 32768));
2215
Mat dst;
2216
src.convertTo(dst, CV_16U);
2217
EXPECT_EQ(0, dst.at<ushort>(0, 0)) << "src=" << src.at<int>(0, 0);
2218
}
2219
2220
{
2221
Mat src(4, 64, CV_32SC1, Scalar(65536));
2222
Mat dst;
2223
src.convertTo(dst, CV_16U);
2224
EXPECT_EQ(65535, dst.at<ushort>(0, 0)) << "src=" << src.at<int>(0, 0);
2225
}
2226
}
2227
2228
TEST(Core_MeanStdDev, regression_multichannel)
2229
{
2230
{
2231
uchar buf[] = { 1, 2, 3, 4, 5, 6, 7, 8,
2232
3, 4, 5, 6, 7, 8, 9, 10 };
2233
double ref_buf[] = { 2., 3., 4., 5., 6., 7., 8., 9.,
2234
1., 1., 1., 1., 1., 1., 1., 1. };
2235
Mat src(1, 2, CV_MAKETYPE(CV_8U, 8), buf);
2236
Mat ref_m(8, 1, CV_64FC1, ref_buf);
2237
Mat ref_sd(8, 1, CV_64FC1, ref_buf + 8);
2238
Mat dst_m, dst_sd;
2239
meanStdDev(src, dst_m, dst_sd);
2240
EXPECT_EQ(0, cv::norm(dst_m, ref_m, NORM_L1));
2241
EXPECT_EQ(0, cv::norm(dst_sd, ref_sd, NORM_L1));
2242
}
2243
}
2244
2245
template <typename T> static inline
2246
void testDivideInitData(Mat& src1, Mat& src2)
2247
{
2248
CV_StaticAssert(std::numeric_limits<T>::is_integer, "");
2249
const static T src1_[] = {
2250
0, 0, 0, 0,
2251
8, 8, 8, 8,
2252
-8, -8, -8, -8
2253
};
2254
Mat(3, 4, traits::Type<T>::value, (void*)src1_).copyTo(src1);
2255
const static T src2_[] = {
2256
1, 2, 0, std::numeric_limits<T>::max(),
2257
1, 2, 0, std::numeric_limits<T>::max(),
2258
1, 2, 0, std::numeric_limits<T>::max(),
2259
};
2260
Mat(3, 4, traits::Type<T>::value, (void*)src2_).copyTo(src2);
2261
}
2262
2263
template <typename T> static inline
2264
void testDivideInitDataFloat(Mat& src1, Mat& src2)
2265
{
2266
CV_StaticAssert(!std::numeric_limits<T>::is_integer, "");
2267
const static T src1_[] = {
2268
0, 0, 0, 0,
2269
8, 8, 8, 8,
2270
-8, -8, -8, -8
2271
};
2272
Mat(3, 4, traits::Type<T>::value, (void*)src1_).copyTo(src1);
2273
const static T src2_[] = {
2274
1, 2, 0, std::numeric_limits<T>::infinity(),
2275
1, 2, 0, std::numeric_limits<T>::infinity(),
2276
1, 2, 0, std::numeric_limits<T>::infinity(),
2277
};
2278
Mat(3, 4, traits::Type<T>::value, (void*)src2_).copyTo(src2);
2279
}
2280
2281
template <> inline void testDivideInitData<float>(Mat& src1, Mat& src2) { testDivideInitDataFloat<float>(src1, src2); }
2282
template <> inline void testDivideInitData<double>(Mat& src1, Mat& src2) { testDivideInitDataFloat<double>(src1, src2); }
2283
2284
2285
template <typename T> static inline
2286
void testDivideChecks(const Mat& dst)
2287
{
2288
ASSERT_FALSE(dst.empty());
2289
CV_StaticAssert(std::numeric_limits<T>::is_integer, "");
2290
for (int y = 0; y < dst.rows; y++)
2291
{
2292
for (int x = 0; x < dst.cols; x++)
2293
{
2294
if (x == 2)
2295
{
2296
EXPECT_EQ(0, dst.at<T>(y, x)) << "dst(" << y << ", " << x << ") = " << dst.at<T>(y, x);
2297
}
2298
}
2299
}
2300
}
2301
2302
template <typename T> static inline
2303
void testDivideChecksFP(const Mat& dst)
2304
{
2305
ASSERT_FALSE(dst.empty());
2306
CV_StaticAssert(!std::numeric_limits<T>::is_integer, "");
2307
for (int y = 0; y < dst.rows; y++)
2308
{
2309
for (int x = 0; x < dst.cols; x++)
2310
{
2311
if (y == 0 && x == 2)
2312
{
2313
EXPECT_TRUE(cvIsNaN(dst.at<T>(y, x))) << "dst(" << y << ", " << x << ") = " << dst.at<T>(y, x);
2314
}
2315
else if (x == 2)
2316
{
2317
EXPECT_TRUE(cvIsInf(dst.at<T>(y, x))) << "dst(" << y << ", " << x << ") = " << dst.at<T>(y, x);
2318
}
2319
else
2320
{
2321
EXPECT_FALSE(cvIsNaN(dst.at<T>(y, x))) << "dst(" << y << ", " << x << ") = " << dst.at<T>(y, x);
2322
EXPECT_FALSE(cvIsInf(dst.at<T>(y, x))) << "dst(" << y << ", " << x << ") = " << dst.at<T>(y, x);
2323
}
2324
}
2325
}
2326
}
2327
2328
template <> inline void testDivideChecks<float>(const Mat& dst) { testDivideChecksFP<float>(dst); }
2329
template <> inline void testDivideChecks<double>(const Mat& dst) { testDivideChecksFP<double>(dst); }
2330
2331
2332
template <typename T, bool isUMat> static inline
2333
void testDivide()
2334
{
2335
Mat src1, src2;
2336
testDivideInitData<T>(src1, src2);
2337
ASSERT_FALSE(src1.empty()); ASSERT_FALSE(src2.empty());
2338
2339
Mat dst;
2340
if (!isUMat)
2341
{
2342
cv::divide(src1, src2, dst);
2343
}
2344
else
2345
{
2346
UMat usrc1, usrc2, udst;
2347
src1.copyTo(usrc1);
2348
src2.copyTo(usrc2);
2349
cv::divide(usrc1, usrc2, udst);
2350
udst.copyTo(dst);
2351
}
2352
2353
testDivideChecks<T>(dst);
2354
2355
if (::testing::Test::HasFailure())
2356
{
2357
std::cout << "src1 = " << std::endl << src1 << std::endl;
2358
std::cout << "src2 = " << std::endl << src2 << std::endl;
2359
std::cout << "dst = " << std::endl << dst << std::endl;
2360
}
2361
}
2362
2363
TEST(Core_DivideRules, type_32s) { testDivide<int, false>(); }
2364
TEST(UMat_Core_DivideRules, type_32s) { testDivide<int, true>(); }
2365
TEST(Core_DivideRules, type_16s) { testDivide<short, false>(); }
2366
TEST(UMat_Core_DivideRules, type_16s) { testDivide<short, true>(); }
2367
TEST(Core_DivideRules, type_32f) { testDivide<float, false>(); }
2368
TEST(UMat_Core_DivideRules, type_32f) { testDivide<float, true>(); }
2369
TEST(Core_DivideRules, type_64f) { testDivide<double, false>(); }
2370
TEST(UMat_Core_DivideRules, type_64f) { testDivide<double, true>(); }
2371
2372
2373
TEST(Core_MinMaxIdx, rows_overflow)
2374
{
2375
const int N = 65536 + 1;
2376
const int M = 1;
2377
{
2378
setRNGSeed(123);
2379
Mat m(N, M, CV_32FC1);
2380
randu(m, -100, 100);
2381
double minVal = 0, maxVal = 0;
2382
int minIdx[CV_MAX_DIM] = { 0 }, maxIdx[CV_MAX_DIM] = { 0 };
2383
cv::minMaxIdx(m, &minVal, &maxVal, minIdx, maxIdx);
2384
2385
double minVal0 = 0, maxVal0 = 0;
2386
int minIdx0[CV_MAX_DIM] = { 0 }, maxIdx0[CV_MAX_DIM] = { 0 };
2387
cv::ipp::setUseIPP(false);
2388
cv::minMaxIdx(m, &minVal0, &maxVal0, minIdx0, maxIdx0);
2389
cv::ipp::setUseIPP(true);
2390
2391
EXPECT_FALSE(fabs(minVal0 - minVal) > 1e-6 || fabs(maxVal0 - maxVal) > 1e-6) << "NxM=" << N << "x" << M <<
2392
" min=" << minVal0 << " vs " << minVal <<
2393
" max=" << maxVal0 << " vs " << maxVal;
2394
}
2395
}
2396
2397
2398
}} // namespace
2399
2400