1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 //   * Redistribution's of source code must retain the above copyright notice,
22 //     this list of conditions and the following disclaimer.
23 //
24 //   * Redistribution's in binary form must reproduce the above copyright notice,
25 //     this list of conditions and the following disclaimer in the documentation
26 //     and/or other materials provided with the distribution.
27 //
28 //   * The name of the copyright holders may not be used to endorse or promote products
29 //     derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43 
44 /* ////////////////////////////////////////////////////////////////////
45 //
46 //  Arithmetic and logical operations: +, -, *, /, &, |, ^, ~, abs ...
47 //
48 // */
49 
50 #include "precomp.hpp"
51 #include "opencl_kernels_core.hpp"
52 
53 namespace cv
54 {
55 
56 /****************************************************************************************\
57 *                                   logical operations                                   *
58 \****************************************************************************************/
59 
60 enum { OCL_OP_ADD=0, OCL_OP_SUB=1, OCL_OP_RSUB=2, OCL_OP_ABSDIFF=3, OCL_OP_MUL=4,
61        OCL_OP_MUL_SCALE=5, OCL_OP_DIV_SCALE=6, OCL_OP_RECIP_SCALE=7, OCL_OP_ADDW=8,
62        OCL_OP_AND=9, OCL_OP_OR=10, OCL_OP_XOR=11, OCL_OP_NOT=12, OCL_OP_MIN=13, OCL_OP_MAX=14,
63        OCL_OP_RDIV_SCALE=15 };
64 
65 #ifdef HAVE_OPENCL
66 
67 static const char* oclop2str[] = { "OP_ADD", "OP_SUB", "OP_RSUB", "OP_ABSDIFF",
68     "OP_MUL", "OP_MUL_SCALE", "OP_DIV_SCALE", "OP_RECIP_SCALE",
69     "OP_ADDW", "OP_AND", "OP_OR", "OP_XOR", "OP_NOT", "OP_MIN", "OP_MAX", "OP_RDIV_SCALE", 0 };
70 
ocl_binary_op(InputArray _src1,InputArray _src2,OutputArray _dst,InputArray _mask,bool bitwise,int oclop,bool haveScalar)71 static bool ocl_binary_op(InputArray _src1, InputArray _src2, OutputArray _dst,
72                           InputArray _mask, bool bitwise, int oclop, bool haveScalar )
73 {
74     bool haveMask = !_mask.empty();
75     int srctype = _src1.type();
76     int srcdepth = CV_MAT_DEPTH(srctype);
77     int cn = CV_MAT_CN(srctype);
78 
79     const ocl::Device d = ocl::Device::getDefault();
80     bool doubleSupport = d.doubleFPConfig() > 0;
81     if( oclop < 0 || ((haveMask || haveScalar) && cn > 4) ||
82             (!doubleSupport && srcdepth == CV_64F && !bitwise))
83         return false;
84 
85     char opts[1024];
86     int kercn = haveMask || haveScalar ? cn : ocl::predictOptimalVectorWidth(_src1, _src2, _dst);
87     int scalarcn = kercn == 3 ? 4 : kercn;
88     int rowsPerWI = d.isIntel() ? 4 : 1;
89 
90     const int dstDepth = srcdepth;
91     const int dstType = CV_MAKETYPE(dstDepth, kercn);
92     const int dstType1 = CV_MAKETYPE(dstDepth, 1);
93     const int scalarType = CV_MAKETYPE(srcdepth, scalarcn);
94 
95     sprintf(opts, "-D %s%s -D %s%s -D dstT=%s -D DEPTH_dst=%d -D dstT_C1=%s -D workST=%s -D cn=%d -D rowsPerWI=%d",
96             haveMask ? "MASK_" : "", haveScalar ? "UNARY_OP" : "BINARY_OP", oclop2str[oclop],
97             doubleSupport ? " -D DOUBLE_SUPPORT" : "",
98             bitwise ? ocl::memopTypeToStr(dstType) : ocl::typeToStr(dstType),
99             dstDepth,
100             bitwise ? ocl::memopTypeToStr(dstType1) : ocl::typeToStr(dstType1),
101             bitwise ? ocl::memopTypeToStr(scalarType) : ocl::typeToStr(scalarType),
102             kercn, rowsPerWI);
103 
104     ocl::Kernel k("KF", ocl::core::arithm_oclsrc, opts);
105     if (k.empty())
106         return false;
107 
108     UMat src1 = _src1.getUMat(), src2;
109     UMat dst = _dst.getUMat(), mask = _mask.getUMat();
110 
111     ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1, cn, kercn);
112     ocl::KernelArg dstarg = haveMask ? ocl::KernelArg::ReadWrite(dst, cn, kercn) :
113                                        ocl::KernelArg::WriteOnly(dst, cn, kercn);
114     ocl::KernelArg maskarg = ocl::KernelArg::ReadOnlyNoSize(mask, 1);
115 
116     if( haveScalar )
117     {
118         size_t esz = CV_ELEM_SIZE1(srctype)*scalarcn;
119         double buf[4] = {0,0,0,0};
120 
121         if( oclop != OCL_OP_NOT )
122         {
123             Mat src2sc = _src2.getMat();
124             convertAndUnrollScalar(src2sc, srctype, (uchar*)buf, 1);
125         }
126 
127         ocl::KernelArg scalararg = ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, buf, esz);
128 
129         if( !haveMask )
130             k.args(src1arg, dstarg, scalararg);
131         else
132             k.args(src1arg, maskarg, dstarg, scalararg);
133     }
134     else
135     {
136         src2 = _src2.getUMat();
137         ocl::KernelArg src2arg = ocl::KernelArg::ReadOnlyNoSize(src2, cn, kercn);
138 
139         if( !haveMask )
140             k.args(src1arg, src2arg, dstarg);
141         else
142             k.args(src1arg, src2arg, maskarg, dstarg);
143     }
144 
145     size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI };
146     return k.run(2, globalsize, 0, false);
147 }
148 
149 #endif
150 
binary_op(InputArray _src1,InputArray _src2,OutputArray _dst,InputArray _mask,const BinaryFuncC * tab,bool bitwise,int oclop)151 static void binary_op( InputArray _src1, InputArray _src2, OutputArray _dst,
152                        InputArray _mask, const BinaryFuncC* tab,
153                        bool bitwise, int oclop )
154 {
155     const _InputArray *psrc1 = &_src1, *psrc2 = &_src2;
156     _InputArray::KindFlag kind1 = psrc1->kind(), kind2 = psrc2->kind();
157     int type1 = psrc1->type(), depth1 = CV_MAT_DEPTH(type1), cn = CV_MAT_CN(type1);
158     int type2 = psrc2->type(), depth2 = CV_MAT_DEPTH(type2), cn2 = CV_MAT_CN(type2);
159     int dims1 = psrc1->dims(), dims2 = psrc2->dims();
160     Size sz1 = dims1 <= 2 ? psrc1->size() : Size();
161     Size sz2 = dims2 <= 2 ? psrc2->size() : Size();
162 #ifdef HAVE_OPENCL
163     bool use_opencl = (kind1 == _InputArray::UMAT || kind2 == _InputArray::UMAT) &&
164             dims1 <= 2 && dims2 <= 2;
165 #endif
166     bool haveMask = !_mask.empty(), haveScalar = false;
167     BinaryFuncC func;
168 
169     if( dims1 <= 2 && dims2 <= 2 && kind1 == kind2 && sz1 == sz2 && type1 == type2 && !haveMask )
170     {
171         _dst.create(sz1, type1);
172         CV_OCL_RUN(use_opencl,
173                    ocl_binary_op(*psrc1, *psrc2, _dst, _mask, bitwise, oclop, false))
174 
175         if( bitwise )
176         {
177             func = *tab;
178             cn = (int)CV_ELEM_SIZE(type1);
179         }
180         else
181         {
182             func = tab[depth1];
183         }
184         CV_Assert(func);
185 
186         Mat src1 = psrc1->getMat(), src2 = psrc2->getMat(), dst = _dst.getMat();
187         Size sz = getContinuousSize2D(src1, src2, dst);
188         size_t len = sz.width*(size_t)cn;
189         if (len < INT_MAX)  // FIXIT similar code below doesn't have that check
190         {
191             sz.width = (int)len;
192             func(src1.ptr(), src1.step, src2.ptr(), src2.step, dst.ptr(), dst.step, sz.width, sz.height, 0);
193             return;
194         }
195     }
196 
197     if( oclop == OCL_OP_NOT )
198         haveScalar = true;
199     else if( (kind1 == _InputArray::MATX) + (kind2 == _InputArray::MATX) == 1 ||
200         !psrc1->sameSize(*psrc2) || type1 != type2 )
201     {
202         if( checkScalar(*psrc1, type2, kind1, kind2) )
203         {
204             // src1 is a scalar; swap it with src2
205             swap(psrc1, psrc2);
206             swap(type1, type2);
207             swap(depth1, depth2);
208             swap(cn, cn2);
209             swap(sz1, sz2);
210         }
211         else if( !checkScalar(*psrc2, type1, kind2, kind1) )
212             CV_Error( CV_StsUnmatchedSizes,
213                       "The operation is neither 'array op array' (where arrays have the same size and type), "
214                       "nor 'array op scalar', nor 'scalar op array'" );
215         haveScalar = true;
216     }
217     else
218     {
219         CV_Assert( psrc1->sameSize(*psrc2) && type1 == type2 );
220     }
221 
222     size_t esz = CV_ELEM_SIZE(type1);
223     size_t blocksize0 = (BLOCK_SIZE + esz-1)/esz;
224     BinaryFunc copymask = 0;
225     bool reallocate = false;
226 
227     if( haveMask )
228     {
229         int mtype = _mask.type();
230         CV_Assert( (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1));
231         copymask = getCopyMaskFunc(esz);
232         reallocate = !_dst.sameSize(*psrc1) || _dst.type() != type1;
233     }
234 
235     AutoBuffer<uchar> _buf;
236     uchar *scbuf = 0, *maskbuf = 0;
237 
238     _dst.createSameSize(*psrc1, type1);
239     // if this is mask operation and dst has been reallocated,
240     // we have to clear the destination
241     if( haveMask && reallocate )
242         _dst.setTo(0.);
243 
244     CV_OCL_RUN(use_opencl,
245                ocl_binary_op(*psrc1, *psrc2, _dst, _mask, bitwise, oclop, haveScalar))
246 
247 
248     Mat src1 = psrc1->getMat(), src2 = psrc2->getMat();
249     Mat dst = _dst.getMat(), mask = _mask.getMat();
250 
251     if( bitwise )
252     {
253         func = *tab;
254         cn = (int)esz;
255     }
256     else
257         func = tab[depth1];
258     CV_Assert(func);
259 
260     if( !haveScalar )
261     {
262         const Mat* arrays[] = { &src1, &src2, &dst, &mask, 0 };
263         uchar* ptrs[4] = {};
264 
265         NAryMatIterator it(arrays, ptrs);
266         size_t total = it.size, blocksize = total;
267 
268         if( blocksize*cn > INT_MAX )
269             blocksize = INT_MAX/cn;
270 
271         if( haveMask )
272         {
273             blocksize = std::min(blocksize, blocksize0);
274             _buf.allocate(blocksize*esz);
275             maskbuf = _buf.data();
276         }
277 
278         for( size_t i = 0; i < it.nplanes; i++, ++it )
279         {
280             for( size_t j = 0; j < total; j += blocksize )
281             {
282                 int bsz = (int)MIN(total - j, blocksize);
283 
284                 func( ptrs[0], 0, ptrs[1], 0, haveMask ? maskbuf : ptrs[2], 0, bsz*cn, 1, 0 );
285                 if( haveMask )
286                 {
287                     copymask( maskbuf, 0, ptrs[3], 0, ptrs[2], 0, Size(bsz, 1), &esz );
288                     ptrs[3] += bsz;
289                 }
290 
291                 bsz *= (int)esz;
292                 ptrs[0] += bsz; ptrs[1] += bsz; ptrs[2] += bsz;
293             }
294         }
295     }
296     else
297     {
298         const Mat* arrays[] = { &src1, &dst, &mask, 0 };
299         uchar* ptrs[3] = {};
300 
301         NAryMatIterator it(arrays, ptrs);
302         size_t total = it.size, blocksize = std::min(total, blocksize0);
303 
304         _buf.allocate(blocksize*(haveMask ? 2 : 1)*esz + 32);
305         scbuf = _buf.data();
306         maskbuf = alignPtr(scbuf + blocksize*esz, 16);
307 
308         convertAndUnrollScalar( src2, src1.type(), scbuf, blocksize);
309 
310         for( size_t i = 0; i < it.nplanes; i++, ++it )
311         {
312             for( size_t j = 0; j < total; j += blocksize )
313             {
314                 int bsz = (int)MIN(total - j, blocksize);
315 
316                 func( ptrs[0], 0, scbuf, 0, haveMask ? maskbuf : ptrs[1], 0, bsz*cn, 1, 0 );
317                 if( haveMask )
318                 {
319                     copymask( maskbuf, 0, ptrs[2], 0, ptrs[1], 0, Size(bsz, 1), &esz );
320                     ptrs[2] += bsz;
321                 }
322 
323                 bsz *= (int)esz;
324                 ptrs[0] += bsz; ptrs[1] += bsz;
325             }
326         }
327     }
328 }
329 
getMaxTab()330 static BinaryFuncC* getMaxTab()
331 {
332     static BinaryFuncC maxTab[] =
333     {
334         (BinaryFuncC)GET_OPTIMIZED(cv::hal::max8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::max8s),
335         (BinaryFuncC)GET_OPTIMIZED(cv::hal::max16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::max16s),
336         (BinaryFuncC)GET_OPTIMIZED(cv::hal::max32s),
337         (BinaryFuncC)GET_OPTIMIZED(cv::hal::max32f), (BinaryFuncC)cv::hal::max64f,
338         0
339     };
340 
341     return maxTab;
342 }
343 
getMinTab()344 static BinaryFuncC* getMinTab()
345 {
346     static BinaryFuncC minTab[] =
347     {
348         (BinaryFuncC)GET_OPTIMIZED(cv::hal::min8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::min8s),
349         (BinaryFuncC)GET_OPTIMIZED(cv::hal::min16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::min16s),
350         (BinaryFuncC)GET_OPTIMIZED(cv::hal::min32s),
351         (BinaryFuncC)GET_OPTIMIZED(cv::hal::min32f), (BinaryFuncC)cv::hal::min64f,
352         0
353     };
354 
355     return minTab;
356 }
357 
358 }
359 
bitwise_and(InputArray a,InputArray b,OutputArray c,InputArray mask)360 void cv::bitwise_and(InputArray a, InputArray b, OutputArray c, InputArray mask)
361 {
362     CV_INSTRUMENT_REGION();
363 
364     BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::and8u);
365     binary_op(a, b, c, mask, &f, true, OCL_OP_AND);
366 }
367 
bitwise_or(InputArray a,InputArray b,OutputArray c,InputArray mask)368 void cv::bitwise_or(InputArray a, InputArray b, OutputArray c, InputArray mask)
369 {
370     CV_INSTRUMENT_REGION();
371 
372     BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::or8u);
373     binary_op(a, b, c, mask, &f, true, OCL_OP_OR);
374 }
375 
bitwise_xor(InputArray a,InputArray b,OutputArray c,InputArray mask)376 void cv::bitwise_xor(InputArray a, InputArray b, OutputArray c, InputArray mask)
377 {
378     CV_INSTRUMENT_REGION();
379 
380     BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::xor8u);
381     binary_op(a, b, c, mask, &f, true, OCL_OP_XOR);
382 }
383 
bitwise_not(InputArray a,OutputArray c,InputArray mask)384 void cv::bitwise_not(InputArray a, OutputArray c, InputArray mask)
385 {
386     CV_INSTRUMENT_REGION();
387 
388     BinaryFuncC f = (BinaryFuncC)GET_OPTIMIZED(cv::hal::not8u);
389     binary_op(a, a, c, mask, &f, true, OCL_OP_NOT);
390 }
391 
max(InputArray src1,InputArray src2,OutputArray dst)392 void cv::max( InputArray src1, InputArray src2, OutputArray dst )
393 {
394     CV_INSTRUMENT_REGION();
395 
396     binary_op(src1, src2, dst, noArray(), getMaxTab(), false, OCL_OP_MAX );
397 }
398 
min(InputArray src1,InputArray src2,OutputArray dst)399 void cv::min( InputArray src1, InputArray src2, OutputArray dst )
400 {
401     CV_INSTRUMENT_REGION();
402 
403     binary_op(src1, src2, dst, noArray(), getMinTab(), false, OCL_OP_MIN );
404 }
405 
max(const Mat & src1,const Mat & src2,Mat & dst)406 void cv::max(const Mat& src1, const Mat& src2, Mat& dst)
407 {
408     CV_INSTRUMENT_REGION();
409 
410     OutputArray _dst(dst);
411     binary_op(src1, src2, _dst, noArray(), getMaxTab(), false, OCL_OP_MAX );
412 }
413 
min(const Mat & src1,const Mat & src2,Mat & dst)414 void cv::min(const Mat& src1, const Mat& src2, Mat& dst)
415 {
416     CV_INSTRUMENT_REGION();
417 
418     OutputArray _dst(dst);
419     binary_op(src1, src2, _dst, noArray(), getMinTab(), false, OCL_OP_MIN );
420 }
421 
max(const UMat & src1,const UMat & src2,UMat & dst)422 void cv::max(const UMat& src1, const UMat& src2, UMat& dst)
423 {
424     CV_INSTRUMENT_REGION();
425 
426     OutputArray _dst(dst);
427     binary_op(src1, src2, _dst, noArray(), getMaxTab(), false, OCL_OP_MAX );
428 }
429 
min(const UMat & src1,const UMat & src2,UMat & dst)430 void cv::min(const UMat& src1, const UMat& src2, UMat& dst)
431 {
432     CV_INSTRUMENT_REGION();
433 
434     OutputArray _dst(dst);
435     binary_op(src1, src2, _dst, noArray(), getMinTab(), false, OCL_OP_MIN );
436 }
437 
438 
439 /****************************************************************************************\
440 *                                      add/subtract                                      *
441 \****************************************************************************************/
442 
443 namespace cv
444 {
445 
actualScalarDepth(const double * data,int len)446 static int actualScalarDepth(const double* data, int len)
447 {
448     int i = 0, minval = INT_MAX, maxval = INT_MIN;
449     for(; i < len; ++i)
450     {
451         int ival = cvRound(data[i]);
452         if( ival != data[i] )
453             break;
454         minval = MIN(minval, ival);
455         maxval = MAX(maxval, ival);
456     }
457     return i < len ? CV_64F :
458         minval >= 0 && maxval <= (int)UCHAR_MAX ? CV_8U :
459         minval >= (int)SCHAR_MIN && maxval <= (int)SCHAR_MAX ? CV_8S :
460         minval >= 0 && maxval <= (int)USHRT_MAX ? CV_16U :
461         minval >= (int)SHRT_MIN && maxval <= (int)SHRT_MAX ? CV_16S :
462         CV_32S;
463 }
464 
465 #ifdef HAVE_OPENCL
466 
ocl_arithm_op(InputArray _src1,InputArray _src2,OutputArray _dst,InputArray _mask,int wtype,void * usrdata,int oclop,bool haveScalar)467 static bool ocl_arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst,
468                           InputArray _mask, int wtype,
469                           void* usrdata, int oclop,
470                           bool haveScalar )
471 {
472     const ocl::Device d = ocl::Device::getDefault();
473     bool doubleSupport = d.doubleFPConfig() > 0;
474     int type1 = _src1.type(), depth1 = CV_MAT_DEPTH(type1), cn = CV_MAT_CN(type1);
475     bool haveMask = !_mask.empty();
476 
477     if ( (haveMask || haveScalar) && cn > 4 )
478         return false;
479 
480     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), wdepth = std::max(CV_32S, CV_MAT_DEPTH(wtype));
481     if (!doubleSupport)
482         wdepth = std::min(wdepth, CV_32F);
483 
484     wtype = CV_MAKETYPE(wdepth, cn);
485     int type2 = haveScalar ? wtype : _src2.type(), depth2 = CV_MAT_DEPTH(type2);
486     if (!doubleSupport && (depth2 == CV_64F || depth1 == CV_64F))
487         return false;
488 
489     int kercn = haveMask || haveScalar ? cn : ocl::predictOptimalVectorWidth(_src1, _src2, _dst);
490     int scalarcn = kercn == 3 ? 4 : kercn, rowsPerWI = d.isIntel() ? 4 : 1;
491 
492     char cvtstr[4][32], opts[1024];
493     sprintf(opts, "-D %s%s -D %s -D srcT1=%s -D srcT1_C1=%s -D srcT2=%s -D srcT2_C1=%s "
494             "-D dstT=%s -D DEPTH_dst=%d -D dstT_C1=%s -D workT=%s -D workST=%s -D scaleT=%s -D wdepth=%d -D convertToWT1=%s "
495             "-D convertToWT2=%s -D convertToDT=%s%s -D cn=%d -D rowsPerWI=%d -D convertFromU=%s",
496             (haveMask ? "MASK_" : ""), (haveScalar ? "UNARY_OP" : "BINARY_OP"),
497             oclop2str[oclop], ocl::typeToStr(CV_MAKETYPE(depth1, kercn)),
498             ocl::typeToStr(depth1), ocl::typeToStr(CV_MAKETYPE(depth2, kercn)),
499             ocl::typeToStr(depth2), ocl::typeToStr(CV_MAKETYPE(ddepth, kercn)), ddepth,
500             ocl::typeToStr(ddepth), ocl::typeToStr(CV_MAKETYPE(wdepth, kercn)),
501             ocl::typeToStr(CV_MAKETYPE(wdepth, scalarcn)),
502             ocl::typeToStr(wdepth), wdepth,
503             ocl::convertTypeStr(depth1, wdepth, kercn, cvtstr[0]),
504             ocl::convertTypeStr(depth2, wdepth, kercn, cvtstr[1]),
505             ocl::convertTypeStr(wdepth, ddepth, kercn, cvtstr[2]),
506             doubleSupport ? " -D DOUBLE_SUPPORT" : "", kercn, rowsPerWI,
507             oclop == OCL_OP_ABSDIFF && wdepth == CV_32S && ddepth == wdepth ?
508             ocl::convertTypeStr(CV_8U, ddepth, kercn, cvtstr[3]) : "noconvert");
509 
510     size_t usrdata_esz = CV_ELEM_SIZE(wdepth);
511     const uchar* usrdata_p = (const uchar*)usrdata;
512     const double* usrdata_d = (const double*)usrdata;
513     float usrdata_f[3];
514     int i, n = oclop == OCL_OP_MUL_SCALE || oclop == OCL_OP_DIV_SCALE ||
515         oclop == OCL_OP_RDIV_SCALE || oclop == OCL_OP_RECIP_SCALE ? 1 : oclop == OCL_OP_ADDW ? 3 : 0;
516     if( usrdata && n > 0 && wdepth == CV_32F )
517     {
518         for( i = 0; i < n; i++ )
519             usrdata_f[i] = (float)usrdata_d[i];
520         usrdata_p = (const uchar*)usrdata_f;
521     }
522 
523     ocl::Kernel k("KF", ocl::core::arithm_oclsrc, opts);
524     if (k.empty())
525         return false;
526 
527     UMat src1 = _src1.getUMat(), src2;
528     UMat dst = _dst.getUMat(), mask = _mask.getUMat();
529 
530     ocl::KernelArg src1arg = ocl::KernelArg::ReadOnlyNoSize(src1, cn, kercn);
531     ocl::KernelArg dstarg = haveMask ? ocl::KernelArg::ReadWrite(dst, cn, kercn) :
532                                        ocl::KernelArg::WriteOnly(dst, cn, kercn);
533     ocl::KernelArg maskarg = ocl::KernelArg::ReadOnlyNoSize(mask, 1);
534 
535     if( haveScalar )
536     {
537         size_t esz = CV_ELEM_SIZE1(wtype)*scalarcn;
538         double buf[4]={0,0,0,0};
539         Mat src2sc = _src2.getMat();
540 
541         if( !src2sc.empty() )
542             convertAndUnrollScalar(src2sc, wtype, (uchar*)buf, 1);
543         ocl::KernelArg scalararg = ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, buf, esz);
544 
545         if( !haveMask )
546         {
547             if(n == 0)
548                 k.args(src1arg, dstarg, scalararg);
549             else if(n == 1)
550                 k.args(src1arg, dstarg, scalararg,
551                        ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, usrdata_p, usrdata_esz));
552             else
553                 CV_Error(Error::StsNotImplemented, "unsupported number of extra parameters");
554         }
555         else
556             k.args(src1arg, maskarg, dstarg, scalararg);
557     }
558     else
559     {
560         src2 = _src2.getUMat();
561         ocl::KernelArg src2arg = ocl::KernelArg::ReadOnlyNoSize(src2, cn, kercn);
562 
563         if( !haveMask )
564         {
565             if (n == 0)
566                 k.args(src1arg, src2arg, dstarg);
567             else if (n == 1)
568                 k.args(src1arg, src2arg, dstarg,
569                        ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, usrdata_p, usrdata_esz));
570             else if (n == 3)
571                 k.args(src1arg, src2arg, dstarg,
572                        ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, usrdata_p, usrdata_esz),
573                        ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, usrdata_p + usrdata_esz, usrdata_esz),
574                        ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, usrdata_p + usrdata_esz*2, usrdata_esz));
575             else
576                 CV_Error(Error::StsNotImplemented, "unsupported number of extra parameters");
577         }
578         else
579             k.args(src1arg, src2arg, maskarg, dstarg);
580     }
581 
582     size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI };
583     return k.run(2, globalsize, NULL, false);
584 }
585 
586 #endif
587 
arithm_op(InputArray _src1,InputArray _src2,OutputArray _dst,InputArray _mask,int dtype,BinaryFuncC * tab,bool muldiv=false,void * usrdata=0,int oclop=-1)588 static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst,
589                       InputArray _mask, int dtype, BinaryFuncC* tab, bool muldiv=false,
590                       void* usrdata=0, int oclop=-1 )
591 {
592     const _InputArray *psrc1 = &_src1, *psrc2 = &_src2;
593     _InputArray::KindFlag kind1 = psrc1->kind(), kind2 = psrc2->kind();
594     bool haveMask = !_mask.empty();
595     bool reallocate = false;
596     int type1 = psrc1->type(), depth1 = CV_MAT_DEPTH(type1), cn = CV_MAT_CN(type1);
597     int type2 = psrc2->type(), depth2 = CV_MAT_DEPTH(type2), cn2 = CV_MAT_CN(type2);
598     int wtype, dims1 = psrc1->dims(), dims2 = psrc2->dims();
599     Size sz1 = dims1 <= 2 ? psrc1->size() : Size();
600     Size sz2 = dims2 <= 2 ? psrc2->size() : Size();
601 #ifdef HAVE_OPENCL
602     bool use_opencl = OCL_PERFORMANCE_CHECK(_dst.isUMat()) && dims1 <= 2 && dims2 <= 2;
603 #endif
604     bool src1Scalar = checkScalar(*psrc1, type2, kind1, kind2);
605     bool src2Scalar = checkScalar(*psrc2, type1, kind2, kind1);
606 
607     if( (kind1 == kind2 || cn == 1) && sz1 == sz2 && dims1 <= 2 && dims2 <= 2 && type1 == type2 &&
608         !haveMask && ((!_dst.fixedType() && (dtype < 0 || CV_MAT_DEPTH(dtype) == depth1)) ||
609                        (_dst.fixedType() && _dst.type() == type1)) &&
610         (src1Scalar == src2Scalar) )
611     {
612         _dst.createSameSize(*psrc1, type1);
613         CV_OCL_RUN(use_opencl,
614             ocl_arithm_op(*psrc1, *psrc2, _dst, _mask,
615                           (!usrdata ? type1 : std::max(depth1, CV_32F)),
616                           usrdata, oclop, false))
617 
618         Mat src1 = psrc1->getMat(), src2 = psrc2->getMat(), dst = _dst.getMat();
619         Size sz = getContinuousSize2D(src1, src2, dst, src1.channels());
620         tab[depth1](src1.ptr(), src1.step, src2.ptr(), src2.step, dst.ptr(), dst.step, sz.width, sz.height, usrdata);
621         return;
622     }
623 
624     bool haveScalar = false, swapped12 = false;
625 
626     if( dims1 != dims2 || sz1 != sz2 || cn != cn2 ||
627         (kind1 == _InputArray::MATX && (sz1 == Size(1,4) || sz1 == Size(1,1))) ||
628         (kind2 == _InputArray::MATX && (sz2 == Size(1,4) || sz2 == Size(1,1))) )
629     {
630         if ((type1 == CV_64F && (sz1.height == 1 || sz1.height == 4)) &&
631             checkScalar(*psrc1, type2, kind1, kind2))
632         {
633             // src1 is a scalar; swap it with src2
634             swap(psrc1, psrc2);
635             swap(sz1, sz2);
636             swap(type1, type2);
637             swap(depth1, depth2);
638             swap(cn, cn2);
639             swap(dims1, dims2);
640             swapped12 = true;
641             if( oclop == OCL_OP_SUB )
642                 oclop = OCL_OP_RSUB;
643             if ( oclop == OCL_OP_DIV_SCALE )
644                 oclop = OCL_OP_RDIV_SCALE;
645         }
646         else if( !checkScalar(*psrc2, type1, kind2, kind1) )
647             CV_Error( CV_StsUnmatchedSizes,
648                      "The operation is neither 'array op array' "
649                      "(where arrays have the same size and the same number of channels), "
650                      "nor 'array op scalar', nor 'scalar op array'" );
651         haveScalar = true;
652         CV_Assert(type2 == CV_64F && (sz2.height == 1 || sz2.height == 4));
653 
654         if (!muldiv)
655         {
656             Mat sc = psrc2->getMat();
657             depth2 = actualScalarDepth(sc.ptr<double>(), sz2 == Size(1, 1) ? cn2 : cn);
658             if( depth2 == CV_64F && (depth1 < CV_32S || depth1 == CV_32F) )
659                 depth2 = CV_32F;
660         }
661         else
662             depth2 = CV_64F;
663     }
664 
665     if( dtype < 0 )
666     {
667         if( _dst.fixedType() )
668             dtype = _dst.type();
669         else
670         {
671             if( !haveScalar && type1 != type2 )
672                 CV_Error(CV_StsBadArg,
673                      "When the input arrays in add/subtract/multiply/divide functions have different types, "
674                      "the output array type must be explicitly specified");
675             dtype = type1;
676         }
677     }
678     dtype = CV_MAT_DEPTH(dtype);
679 
680     if( depth1 == depth2 && dtype == depth1 )
681         wtype = dtype;
682     else if( !muldiv )
683     {
684         wtype = depth1 <= CV_8S && depth2 <= CV_8S ? CV_16S :
685                 depth1 <= CV_32S && depth2 <= CV_32S ? CV_32S : std::max(depth1, depth2);
686         wtype = std::max(wtype, dtype);
687 
688         // when the result of addition should be converted to an integer type,
689         // and just one of the input arrays is floating-point, it makes sense to convert that input to integer type before the operation,
690         // instead of converting the other input to floating-point and then converting the operation result back to integers.
691         if( dtype < CV_32F && (depth1 < CV_32F || depth2 < CV_32F) )
692             wtype = CV_32S;
693     }
694     else
695     {
696         wtype = std::max(depth1, std::max(depth2, CV_32F));
697         wtype = std::max(wtype, dtype);
698     }
699 
700     dtype = CV_MAKETYPE(dtype, cn);
701     wtype = CV_MAKETYPE(wtype, cn);
702 
703     if( haveMask )
704     {
705         int mtype = _mask.type();
706         CV_Assert( (mtype == CV_8UC1 || mtype == CV_8SC1) && _mask.sameSize(*psrc1) );
707         reallocate = !_dst.sameSize(*psrc1) || _dst.type() != dtype;
708     }
709 
710     _dst.createSameSize(*psrc1, dtype);
711     if( reallocate )
712         _dst.setTo(0.);
713 
714     CV_OCL_RUN(use_opencl,
715                ocl_arithm_op(*psrc1, *psrc2, _dst, _mask, wtype,
716                usrdata, oclop, haveScalar))
717 
718     BinaryFunc cvtsrc1 = type1 == wtype ? 0 : getConvertFunc(type1, wtype);
719     BinaryFunc cvtsrc2 = type2 == type1 ? cvtsrc1 : type2 == wtype ? 0 : getConvertFunc(type2, wtype);
720     BinaryFunc cvtdst = dtype == wtype ? 0 : getConvertFunc(wtype, dtype);
721 
722     size_t esz1 = CV_ELEM_SIZE(type1), esz2 = CV_ELEM_SIZE(type2);
723     size_t dsz = CV_ELEM_SIZE(dtype), wsz = CV_ELEM_SIZE(wtype);
724     size_t blocksize0 = (size_t)(BLOCK_SIZE + wsz-1)/wsz;
725     BinaryFunc copymask = getCopyMaskFunc(dsz);
726     Mat src1 = psrc1->getMat(), src2 = psrc2->getMat(), dst = _dst.getMat(), mask = _mask.getMat();
727 
728     AutoBuffer<uchar> _buf;
729     uchar *buf, *maskbuf = 0, *buf1 = 0, *buf2 = 0, *wbuf = 0;
730     size_t bufesz = (cvtsrc1 ? wsz : 0) +
731                     (cvtsrc2 || haveScalar ? wsz : 0) +
732                     (cvtdst ? wsz : 0) +
733                     (haveMask ? dsz : 0);
734     BinaryFuncC func = tab[CV_MAT_DEPTH(wtype)];
735     CV_Assert(func);
736 
737     if( !haveScalar )
738     {
739         const Mat* arrays[] = { &src1, &src2, &dst, &mask, 0 };
740         uchar* ptrs[4] = {};
741 
742         NAryMatIterator it(arrays, ptrs);
743         size_t total = it.size, blocksize = total;
744 
745         if( haveMask || cvtsrc1 || cvtsrc2 || cvtdst )
746             blocksize = std::min(blocksize, blocksize0);
747 
748         _buf.allocate(bufesz*blocksize + 64);
749         buf = _buf.data();
750         if( cvtsrc1 )
751             buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16);
752         if( cvtsrc2 )
753             buf2 = buf, buf = alignPtr(buf + blocksize*wsz, 16);
754         wbuf = maskbuf = buf;
755         if( cvtdst )
756             buf = alignPtr(buf + blocksize*wsz, 16);
757         if( haveMask )
758             maskbuf = buf;
759 
760         for( size_t i = 0; i < it.nplanes; i++, ++it )
761         {
762             for( size_t j = 0; j < total; j += blocksize )
763             {
764                 int bsz = (int)MIN(total - j, blocksize);
765                 Size bszn(bsz*cn, 1);
766                 const uchar *sptr1 = ptrs[0], *sptr2 = ptrs[1];
767                 uchar* dptr = ptrs[2];
768                 if( cvtsrc1 )
769                 {
770                     cvtsrc1( sptr1, 1, 0, 1, buf1, 1, bszn, 0 );
771                     sptr1 = buf1;
772                 }
773                 if( ptrs[0] == ptrs[1] )
774                     sptr2 = sptr1;
775                 else if( cvtsrc2 )
776                 {
777                     cvtsrc2( sptr2, 1, 0, 1, buf2, 1, bszn, 0 );
778                     sptr2 = buf2;
779                 }
780 
781                 if( !haveMask && !cvtdst )
782                     func( sptr1, 1, sptr2, 1, dptr, 1, bszn.width, bszn.height, usrdata );
783                 else
784                 {
785                     func( sptr1, 1, sptr2, 1, wbuf, 0, bszn.width, bszn.height, usrdata );
786                     if( !haveMask )
787                         cvtdst( wbuf, 1, 0, 1, dptr, 1, bszn, 0 );
788                     else if( !cvtdst )
789                     {
790                         copymask( wbuf, 1, ptrs[3], 1, dptr, 1, Size(bsz, 1), &dsz );
791                         ptrs[3] += bsz;
792                     }
793                     else
794                     {
795                         cvtdst( wbuf, 1, 0, 1, maskbuf, 1, bszn, 0 );
796                         copymask( maskbuf, 1, ptrs[3], 1, dptr, 1, Size(bsz, 1), &dsz );
797                         ptrs[3] += bsz;
798                     }
799                 }
800                 ptrs[0] += bsz*esz1; ptrs[1] += bsz*esz2; ptrs[2] += bsz*dsz;
801             }
802         }
803     }
804     else
805     {
806         const Mat* arrays[] = { &src1, &dst, &mask, 0 };
807         uchar* ptrs[3] = {};
808 
809         NAryMatIterator it(arrays, ptrs);
810         size_t total = it.size, blocksize = std::min(total, blocksize0);
811 
812         _buf.allocate(bufesz*blocksize + 64);
813         buf = _buf.data();
814         if( cvtsrc1 )
815             buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16);
816         buf2 = buf; buf = alignPtr(buf + blocksize*wsz, 16);
817         wbuf = maskbuf = buf;
818         if( cvtdst )
819             buf = alignPtr(buf + blocksize*wsz, 16);
820         if( haveMask )
821             maskbuf = buf;
822 
823         convertAndUnrollScalar( src2, wtype, buf2, blocksize);
824 
825         for( size_t i = 0; i < it.nplanes; i++, ++it )
826         {
827             for( size_t j = 0; j < total; j += blocksize )
828             {
829                 int bsz = (int)MIN(total - j, blocksize);
830                 Size bszn(bsz*cn, 1);
831                 const uchar *sptr1 = ptrs[0];
832                 const uchar* sptr2 = buf2;
833                 uchar* dptr = ptrs[1];
834 
835                 if( cvtsrc1 )
836                 {
837                     cvtsrc1( sptr1, 1, 0, 1, buf1, 1, bszn, 0 );
838                     sptr1 = buf1;
839                 }
840 
841                 if( swapped12 )
842                     std::swap(sptr1, sptr2);
843 
844                 if( !haveMask && !cvtdst )
845                     func( sptr1, 1, sptr2, 1, dptr, 1, bszn.width, bszn.height, usrdata );
846                 else
847                 {
848                     func( sptr1, 1, sptr2, 1, wbuf, 1, bszn.width, bszn.height, usrdata );
849                     if( !haveMask )
850                         cvtdst( wbuf, 1, 0, 1, dptr, 1, bszn, 0 );
851                     else if( !cvtdst )
852                     {
853                         copymask( wbuf, 1, ptrs[2], 1, dptr, 1, Size(bsz, 1), &dsz );
854                         ptrs[2] += bsz;
855                     }
856                     else
857                     {
858                         cvtdst( wbuf, 1, 0, 1, maskbuf, 1, bszn, 0 );
859                         copymask( maskbuf, 1, ptrs[2], 1, dptr, 1, Size(bsz, 1), &dsz );
860                         ptrs[2] += bsz;
861                     }
862                 }
863                 ptrs[0] += bsz*esz1; ptrs[1] += bsz*dsz;
864             }
865         }
866     }
867 }
868 
getAddTab()869 static BinaryFuncC* getAddTab()
870 {
871     static BinaryFuncC addTab[] =
872     {
873         (BinaryFuncC)GET_OPTIMIZED(cv::hal::add8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::add8s),
874         (BinaryFuncC)GET_OPTIMIZED(cv::hal::add16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::add16s),
875         (BinaryFuncC)GET_OPTIMIZED(cv::hal::add32s),
876         (BinaryFuncC)GET_OPTIMIZED(cv::hal::add32f), (BinaryFuncC)cv::hal::add64f,
877         0
878     };
879 
880     return addTab;
881 }
882 
getSubTab()883 static BinaryFuncC* getSubTab()
884 {
885     static BinaryFuncC subTab[] =
886     {
887         (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub8s),
888         (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub16s),
889         (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub32s),
890         (BinaryFuncC)GET_OPTIMIZED(cv::hal::sub32f), (BinaryFuncC)cv::hal::sub64f,
891         0
892     };
893 
894     return subTab;
895 }
896 
getAbsDiffTab()897 static BinaryFuncC* getAbsDiffTab()
898 {
899     static BinaryFuncC absDiffTab[] =
900     {
901         (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff8s),
902         (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff16s),
903         (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff32s),
904         (BinaryFuncC)GET_OPTIMIZED(cv::hal::absdiff32f), (BinaryFuncC)cv::hal::absdiff64f,
905         0
906     };
907 
908     return absDiffTab;
909 }
910 
911 }
912 
add(InputArray src1,InputArray src2,OutputArray dst,InputArray mask,int dtype)913 void cv::add( InputArray src1, InputArray src2, OutputArray dst,
914           InputArray mask, int dtype )
915 {
916     CV_INSTRUMENT_REGION();
917 
918     arithm_op(src1, src2, dst, mask, dtype, getAddTab(), false, 0, OCL_OP_ADD );
919 }
920 
subtract(InputArray _src1,InputArray _src2,OutputArray _dst,InputArray mask,int dtype)921 void cv::subtract( InputArray _src1, InputArray _src2, OutputArray _dst,
922                InputArray mask, int dtype )
923 {
924     CV_INSTRUMENT_REGION();
925 
926     arithm_op(_src1, _src2, _dst, mask, dtype, getSubTab(), false, 0, OCL_OP_SUB );
927 }
928 
absdiff(InputArray src1,InputArray src2,OutputArray dst)929 void cv::absdiff( InputArray src1, InputArray src2, OutputArray dst )
930 {
931     CV_INSTRUMENT_REGION();
932 
933     arithm_op(src1, src2, dst, noArray(), -1, getAbsDiffTab(), false, 0, OCL_OP_ABSDIFF);
934 }
935 
copyTo(InputArray _src,OutputArray _dst,InputArray _mask)936 void cv::copyTo(InputArray _src, OutputArray _dst, InputArray _mask)
937 {
938     CV_INSTRUMENT_REGION();
939 
940     _src.copyTo(_dst, _mask);
941 }
942 
943 /****************************************************************************************\
944 *                                    multiply/divide                                     *
945 \****************************************************************************************/
946 
947 namespace cv
948 {
949 
getMulTab()950 static BinaryFuncC* getMulTab()
951 {
952     static BinaryFuncC mulTab[] =
953     {
954         (BinaryFuncC)cv::hal::mul8u, (BinaryFuncC)cv::hal::mul8s, (BinaryFuncC)cv::hal::mul16u,
955         (BinaryFuncC)cv::hal::mul16s, (BinaryFuncC)cv::hal::mul32s, (BinaryFuncC)cv::hal::mul32f,
956         (BinaryFuncC)cv::hal::mul64f, 0
957     };
958 
959     return mulTab;
960 }
961 
getDivTab()962 static BinaryFuncC* getDivTab()
963 {
964     static BinaryFuncC divTab[] =
965     {
966         (BinaryFuncC)cv::hal::div8u, (BinaryFuncC)cv::hal::div8s, (BinaryFuncC)cv::hal::div16u,
967         (BinaryFuncC)cv::hal::div16s, (BinaryFuncC)cv::hal::div32s, (BinaryFuncC)cv::hal::div32f,
968         (BinaryFuncC)cv::hal::div64f, 0
969     };
970 
971     return divTab;
972 }
973 
getRecipTab()974 static BinaryFuncC* getRecipTab()
975 {
976     static BinaryFuncC recipTab[] =
977     {
978         (BinaryFuncC)cv::hal::recip8u, (BinaryFuncC)cv::hal::recip8s, (BinaryFuncC)cv::hal::recip16u,
979         (BinaryFuncC)cv::hal::recip16s, (BinaryFuncC)cv::hal::recip32s, (BinaryFuncC)cv::hal::recip32f,
980         (BinaryFuncC)cv::hal::recip64f, 0
981     };
982 
983     return recipTab;
984 }
985 
multiply(InputArray src1,InputArray src2,OutputArray dst,double scale,int dtype)986 void multiply(InputArray src1, InputArray src2,
987                   OutputArray dst, double scale, int dtype)
988 {
989     CV_INSTRUMENT_REGION();
990 
991     arithm_op(src1, src2, dst, noArray(), dtype, getMulTab(),
992               true, &scale, std::abs(scale - 1.0) < DBL_EPSILON ? OCL_OP_MUL : OCL_OP_MUL_SCALE);
993 }
994 
divide(InputArray src1,InputArray src2,OutputArray dst,double scale,int dtype)995 void divide(InputArray src1, InputArray src2,
996                 OutputArray dst, double scale, int dtype)
997 {
998     CV_INSTRUMENT_REGION();
999 
1000     arithm_op(src1, src2, dst, noArray(), dtype, getDivTab(), true, &scale, OCL_OP_DIV_SCALE);
1001 }
1002 
divide(double scale,InputArray src2,OutputArray dst,int dtype)1003 void divide(double scale, InputArray src2,
1004                 OutputArray dst, int dtype)
1005 {
1006     CV_INSTRUMENT_REGION();
1007 
1008     arithm_op(src2, src2, dst, noArray(), dtype, getRecipTab(), true, &scale, OCL_OP_RECIP_SCALE);
1009 }
1010 
mul(InputArray m,double scale) const1011 UMat UMat::mul(InputArray m, double scale) const
1012 {
1013     UMat dst;
1014     multiply(*this, m, dst, scale);
1015     return dst;
1016 }
1017 
1018 /****************************************************************************************\
1019 *                                      addWeighted                                       *
1020 \****************************************************************************************/
1021 
getAddWeightedTab()1022 static BinaryFuncC* getAddWeightedTab()
1023 {
1024     static BinaryFuncC addWeightedTab[] =
1025     {
1026         (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted8s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted16u),
1027         (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted16s), (BinaryFuncC)GET_OPTIMIZED(cv::hal::addWeighted32s), (BinaryFuncC)cv::hal::addWeighted32f,
1028         (BinaryFuncC)cv::hal::addWeighted64f, 0
1029     };
1030 
1031     return addWeightedTab;
1032 }
1033 
1034 }
1035 
addWeighted(InputArray src1,double alpha,InputArray src2,double beta,double gamma,OutputArray dst,int dtype)1036 void cv::addWeighted( InputArray src1, double alpha, InputArray src2,
1037                       double beta, double gamma, OutputArray dst, int dtype )
1038 {
1039     CV_INSTRUMENT_REGION();
1040 
1041     double scalars[] = {alpha, beta, gamma};
1042     arithm_op(src1, src2, dst, noArray(), dtype, getAddWeightedTab(), true, scalars, OCL_OP_ADDW);
1043 }
1044 
1045 
1046 /****************************************************************************************\
1047 *                                          compare                                       *
1048 \****************************************************************************************/
1049 
1050 namespace cv
1051 {
1052 
getCmpFunc(int depth)1053 static BinaryFuncC getCmpFunc(int depth)
1054 {
1055     static BinaryFuncC cmpTab[] =
1056     {
1057         (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp8u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp8s),
1058         (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp16u), (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp16s),
1059         (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp32s),
1060         (BinaryFuncC)GET_OPTIMIZED(cv::hal::cmp32f), (BinaryFuncC)cv::hal::cmp64f,
1061         0
1062     };
1063 
1064     return cmpTab[depth];
1065 }
1066 
getMinVal(int depth)1067 static double getMinVal(int depth)
1068 {
1069     static const double tab[] = {0, -128, 0, -32768, INT_MIN, -FLT_MAX, -DBL_MAX, 0};
1070     return tab[depth];
1071 }
1072 
getMaxVal(int depth)1073 static double getMaxVal(int depth)
1074 {
1075     static const double tab[] = {255, 127, 65535, 32767, INT_MAX, FLT_MAX, DBL_MAX, 0};
1076     return tab[depth];
1077 }
1078 
1079 #ifdef HAVE_OPENCL
1080 
ocl_compare(InputArray _src1,InputArray _src2,OutputArray _dst,int op,bool haveScalar)1081 static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op, bool haveScalar)
1082 {
1083     const ocl::Device& dev = ocl::Device::getDefault();
1084     bool doubleSupport = dev.doubleFPConfig() > 0;
1085     int type1 = _src1.type(), depth1 = CV_MAT_DEPTH(type1), cn = CV_MAT_CN(type1),
1086             type2 = _src2.type(), depth2 = CV_MAT_DEPTH(type2);
1087 
1088     if (!doubleSupport && depth1 == CV_64F)
1089         return false;
1090 
1091     if (!haveScalar && (!_src1.sameSize(_src2) || type1 != type2))
1092             return false;
1093 
1094     int kercn = haveScalar ? cn : ocl::predictOptimalVectorWidth(_src1, _src2, _dst), rowsPerWI = dev.isIntel() ? 4 : 1;
1095     // Workaround for bug with "?:" operator in AMD OpenCL compiler
1096     if (depth1 >= CV_16U)
1097         kercn = 1;
1098 
1099     int scalarcn = kercn == 3 ? 4 : kercn;
1100     const char * const operationMap[] = { "==", ">", ">=", "<", "<=", "!=" };
1101     char cvt[40];
1102 
1103     String opts = format("-D %s -D srcT1=%s -D dstT=%s -D DEPTH_dst=%d -D workT=srcT1 -D cn=%d"
1104                          " -D convertToDT=%s -D OP_CMP -D CMP_OPERATOR=%s -D srcT1_C1=%s"
1105                          " -D srcT2_C1=%s -D dstT_C1=%s -D workST=%s -D rowsPerWI=%d%s",
1106                          haveScalar ? "UNARY_OP" : "BINARY_OP",
1107                          ocl::typeToStr(CV_MAKE_TYPE(depth1, kercn)),
1108                          ocl::typeToStr(CV_8UC(kercn)), CV_8U, kercn,
1109                          ocl::convertTypeStr(depth1, CV_8U, kercn, cvt),
1110                          operationMap[op], ocl::typeToStr(depth1),
1111                          ocl::typeToStr(depth1), ocl::typeToStr(CV_8U),
1112                          ocl::typeToStr(CV_MAKE_TYPE(depth1, scalarcn)), rowsPerWI,
1113                          doubleSupport ? " -D DOUBLE_SUPPORT" : "");
1114 
1115     ocl::Kernel k("KF", ocl::core::arithm_oclsrc, opts);
1116     if (k.empty())
1117         return false;
1118 
1119     UMat src1 = _src1.getUMat();
1120     Size size = src1.size();
1121     _dst.create(size, CV_8UC(cn));
1122     UMat dst = _dst.getUMat();
1123 
1124     if (haveScalar)
1125     {
1126         size_t esz = CV_ELEM_SIZE1(type1) * scalarcn;
1127         double buf[4] = { 0, 0, 0, 0 };
1128         Mat src2 = _src2.getMat();
1129 
1130         if( depth1 > CV_32S )
1131             convertAndUnrollScalar( src2, depth1, (uchar *)buf, kercn );
1132         else
1133         {
1134             double fval = 0;
1135             getConvertFunc(depth2, CV_64F)(src2.ptr(), 1, 0, 1, (uchar *)&fval, 1, Size(1, 1), 0);
1136             if( fval < getMinVal(depth1) )
1137                 return dst.setTo(Scalar::all(op == CMP_GT || op == CMP_GE || op == CMP_NE ? 255 : 0)), true;
1138 
1139             if( fval > getMaxVal(depth1) )
1140                 return dst.setTo(Scalar::all(op == CMP_LT || op == CMP_LE || op == CMP_NE ? 255 : 0)), true;
1141 
1142             int ival = cvRound(fval);
1143             if( fval != ival )
1144             {
1145                 if( op == CMP_LT || op == CMP_GE )
1146                     ival = cvCeil(fval);
1147                 else if( op == CMP_LE || op == CMP_GT )
1148                     ival = cvFloor(fval);
1149                 else
1150                     return dst.setTo(Scalar::all(op == CMP_NE ? 255 : 0)), true;
1151             }
1152             convertAndUnrollScalar(Mat(1, 1, CV_32S, &ival), depth1, (uchar *)buf, kercn);
1153         }
1154 
1155         ocl::KernelArg scalararg = ocl::KernelArg(ocl::KernelArg::CONSTANT, 0, 0, 0, buf, esz);
1156 
1157         k.args(ocl::KernelArg::ReadOnlyNoSize(src1, cn, kercn),
1158                ocl::KernelArg::WriteOnly(dst, cn, kercn), scalararg);
1159     }
1160     else
1161     {
1162         UMat src2 = _src2.getUMat();
1163 
1164         k.args(ocl::KernelArg::ReadOnlyNoSize(src1),
1165                ocl::KernelArg::ReadOnlyNoSize(src2),
1166                ocl::KernelArg::WriteOnly(dst, cn, kercn));
1167     }
1168 
1169     size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI };
1170     return k.run(2, globalsize, NULL, false);
1171 }
1172 
1173 #endif
1174 
1175 }
1176 
compare(InputArray _src1,InputArray _src2,OutputArray _dst,int op)1177 void cv::compare(InputArray _src1, InputArray _src2, OutputArray _dst, int op)
1178 {
1179     CV_INSTRUMENT_REGION();
1180 
1181     CV_Assert( op == CMP_LT || op == CMP_LE || op == CMP_EQ ||
1182                op == CMP_NE || op == CMP_GE || op == CMP_GT );
1183 
1184     CV_Assert(_src1.empty() == _src2.empty());
1185     if (_src1.empty() && _src2.empty())
1186     {
1187         _dst.release();
1188         return;
1189     }
1190 
1191     bool haveScalar = false;
1192 
1193     if ((_src1.isMatx() + _src2.isMatx()) == 1
1194             || !_src1.sameSize(_src2)
1195             || _src1.type() != _src2.type())
1196     {
1197         bool is_src1_scalar = checkScalar(_src1, _src2.type(), _src1.kind(), _src2.kind());
1198         bool is_src2_scalar = checkScalar(_src2, _src1.type(), _src2.kind(), _src1.kind());
1199 
1200         if (is_src1_scalar && !is_src2_scalar)
1201         {
1202             op = op == CMP_LT ? CMP_GT : op == CMP_LE ? CMP_GE :
1203                 op == CMP_GE ? CMP_LE : op == CMP_GT ? CMP_LT : op;
1204             // src1 is a scalar; swap it with src2
1205             compare(_src2, _src1, _dst, op);
1206             return;
1207         }
1208         else if(is_src1_scalar == is_src2_scalar)
1209             CV_Error( CV_StsUnmatchedSizes,
1210                      "The operation is neither 'array op array' (where arrays have the same size and the same type), "
1211                      "nor 'array op scalar', nor 'scalar op array'" );
1212         haveScalar = true;
1213     }
1214 
1215     CV_OCL_RUN(_src1.dims() <= 2 && _src2.dims() <= 2 && OCL_PERFORMANCE_CHECK(_dst.isUMat()),
1216                ocl_compare(_src1, _src2, _dst, op, haveScalar))
1217 
1218     _InputArray::KindFlag kind1 = _src1.kind(), kind2 = _src2.kind();
1219     Mat src1 = _src1.getMat(), src2 = _src2.getMat();
1220 
1221     int depth1 = src1.depth(), depth2 = src2.depth();
1222     if (depth1 == CV_16F || depth2 == CV_16F)
1223         CV_Error(Error::StsNotImplemented, "Unsupported depth value CV_16F");
1224 
1225     if( kind1 == kind2 && src1.dims <= 2 && src2.dims <= 2 && src1.size() == src2.size() && src1.type() == src2.type() )
1226     {
1227         int cn = src1.channels();
1228         _dst.create(src1.size(), CV_8UC(cn));
1229         Mat dst = _dst.getMat();
1230         Size sz = getContinuousSize2D(src1, src2, dst, src1.channels());
1231         BinaryFuncC cmpFn = getCmpFunc(depth1);
1232         CV_Assert(cmpFn);
1233         cmpFn(src1.ptr(), src1.step, src2.ptr(), src2.step, dst.ptr(), dst.step, sz.width, sz.height, &op);
1234         return;
1235     }
1236 
1237     int cn = src1.channels();
1238 
1239     _dst.create(src1.dims, src1.size, CV_8UC(cn));
1240     src1 = src1.reshape(1); src2 = src2.reshape(1);
1241     Mat dst = _dst.getMat().reshape(1);
1242 
1243     size_t esz = std::max(src1.elemSize(), (size_t)1);
1244     size_t blocksize0 = (size_t)(BLOCK_SIZE + esz-1)/esz;
1245     BinaryFuncC func = getCmpFunc(depth1);
1246     CV_Assert(func);
1247 
1248     if( !haveScalar )
1249     {
1250         const Mat* arrays[] = { &src1, &src2, &dst, 0 };
1251         uchar* ptrs[3] = {};
1252 
1253         NAryMatIterator it(arrays, ptrs);
1254         size_t total = it.size;
1255 
1256         for( size_t i = 0; i < it.nplanes; i++, ++it )
1257             func( ptrs[0], 0, ptrs[1], 0, ptrs[2], 0, (int)total, 1, &op );
1258     }
1259     else
1260     {
1261         const Mat* arrays[] = { &src1, &dst, 0 };
1262         uchar* ptrs[2] = {};
1263 
1264         NAryMatIterator it(arrays, ptrs);
1265         size_t total = it.size, blocksize = std::min(total, blocksize0);
1266 
1267         AutoBuffer<uchar> _buf(blocksize*esz);
1268         uchar *buf = _buf.data();
1269 
1270         if( depth1 > CV_32S )
1271             convertAndUnrollScalar( src2, depth1, buf, blocksize );
1272         else
1273         {
1274             double fval=0;
1275             BinaryFunc cvtFn = getConvertFunc(depth2, CV_64F);
1276             CV_Assert(cvtFn);
1277             cvtFn(src2.ptr(), 1, 0, 1, (uchar*)&fval, 1, Size(1,1), 0);
1278             if( fval < getMinVal(depth1) )
1279             {
1280                 dst = Scalar::all(op == CMP_GT || op == CMP_GE || op == CMP_NE ? 255 : 0);
1281                 return;
1282             }
1283 
1284             if( fval > getMaxVal(depth1) )
1285             {
1286                 dst = Scalar::all(op == CMP_LT || op == CMP_LE || op == CMP_NE ? 255 : 0);
1287                 return;
1288             }
1289 
1290             int ival = cvRound(fval);
1291             if( fval != ival )
1292             {
1293                 if( op == CMP_LT || op == CMP_GE )
1294                     ival = cvCeil(fval);
1295                 else if( op == CMP_LE || op == CMP_GT )
1296                     ival = cvFloor(fval);
1297                 else
1298                 {
1299                     dst = Scalar::all(op == CMP_NE ? 255 : 0);
1300                     return;
1301                 }
1302             }
1303             convertAndUnrollScalar(Mat(1, 1, CV_32S, &ival), depth1, buf, blocksize);
1304         }
1305 
1306         for( size_t i = 0; i < it.nplanes; i++, ++it )
1307         {
1308             for( size_t j = 0; j < total; j += blocksize )
1309             {
1310                 int bsz = (int)MIN(total - j, blocksize);
1311                 func( ptrs[0], 0, buf, 0, ptrs[1], 0, bsz, 1, &op);
1312                 ptrs[0] += bsz*esz;
1313                 ptrs[1] += bsz;
1314             }
1315         }
1316     }
1317 }
1318 
1319 /****************************************************************************************\
1320 *                                        inRange                                         *
1321 \****************************************************************************************/
1322 
1323 namespace cv
1324 {
1325 
1326 template <typename T>
1327 struct InRange_SIMD
1328 {
operator ()cv::InRange_SIMD1329     int operator () (const T *, const T *, const T *, uchar *, int) const
1330     {
1331         return 0;
1332     }
1333 };
1334 
1335 #if CV_SIMD
1336 
1337 template <>
1338 struct InRange_SIMD<uchar>
1339 {
operator ()cv::InRange_SIMD1340     int operator () (const uchar * src1, const uchar * src2, const uchar * src3,
1341         uchar * dst, int len) const
1342     {
1343         int x = 0;
1344         const int width = v_uint8::nlanes;
1345 
1346         for (; x <= len - width; x += width)
1347         {
1348             v_uint8 values = vx_load(src1 + x);
1349             v_uint8 low = vx_load(src2 + x);
1350             v_uint8 high = vx_load(src3 + x);
1351 
1352             v_store(dst + x, (values >= low) & (high >= values));
1353         }
1354         vx_cleanup();
1355         return x;
1356     }
1357 };
1358 
1359 template <>
1360 struct InRange_SIMD<schar>
1361 {
operator ()cv::InRange_SIMD1362     int operator () (const schar * src1, const schar * src2, const schar * src3,
1363         uchar * dst, int len) const
1364     {
1365         int x = 0;
1366         const int width = v_int8::nlanes;
1367 
1368         for (; x <= len - width; x += width)
1369         {
1370             v_int8 values = vx_load(src1 + x);
1371             v_int8 low = vx_load(src2 + x);
1372             v_int8 high = vx_load(src3 + x);
1373 
1374             v_store((schar*)(dst + x), (values >= low) & (high >= values));
1375         }
1376         vx_cleanup();
1377         return x;
1378     }
1379 };
1380 
1381 template <>
1382 struct InRange_SIMD<ushort>
1383 {
operator ()cv::InRange_SIMD1384     int operator () (const ushort * src1, const ushort * src2, const ushort * src3,
1385         uchar * dst, int len) const
1386     {
1387         int x = 0;
1388         const int width = v_uint16::nlanes * 2;
1389 
1390         for (; x <= len - width; x += width)
1391         {
1392             v_uint16 values1 = vx_load(src1 + x);
1393             v_uint16 low1 = vx_load(src2 + x);
1394             v_uint16 high1 = vx_load(src3 + x);
1395 
1396             v_uint16 values2 = vx_load(src1 + x + v_uint16::nlanes);
1397             v_uint16 low2 = vx_load(src2 + x + v_uint16::nlanes);
1398             v_uint16 high2 = vx_load(src3 + x + v_uint16::nlanes);
1399 
1400             v_store(dst + x, v_pack((values1 >= low1) & (high1 >= values1), (values2 >= low2) & (high2 >= values2)));
1401         }
1402         vx_cleanup();
1403         return x;
1404     }
1405 };
1406 
1407 template <>
1408 struct InRange_SIMD<short>
1409 {
operator ()cv::InRange_SIMD1410     int operator () (const short * src1, const short * src2, const short * src3,
1411         uchar * dst, int len) const
1412     {
1413         int x = 0;
1414         const int width = (int)v_int16::nlanes * 2;
1415 
1416         for (; x <= len - width; x += width)
1417         {
1418             v_int16 values1 = vx_load(src1 + x);
1419             v_int16 low1 = vx_load(src2 + x);
1420             v_int16 high1 = vx_load(src3 + x);
1421 
1422             v_int16 values2 = vx_load(src1 + x + v_int16::nlanes);
1423             v_int16 low2 = vx_load(src2 + x + v_int16::nlanes);
1424             v_int16 high2 = vx_load(src3 + x + v_int16::nlanes);
1425 
1426             v_store((schar*)(dst + x), v_pack((values1 >= low1) & (high1 >= values1), (values2 >= low2) & (high2 >= values2)));
1427         }
1428         vx_cleanup();
1429         return x;
1430     }
1431 };
1432 
1433 template <>
1434 struct InRange_SIMD<int>
1435 {
operator ()cv::InRange_SIMD1436     int operator () (const int * src1, const int * src2, const int * src3,
1437         uchar * dst, int len) const
1438     {
1439         int x = 0;
1440         const int width = (int)v_int32::nlanes * 2;
1441 
1442         for (; x <= len - width; x += width)
1443         {
1444             v_int32 values1 = vx_load(src1 + x);
1445             v_int32 low1 = vx_load(src2 + x);
1446             v_int32 high1 = vx_load(src3 + x);
1447 
1448             v_int32 values2 = vx_load(src1 + x + v_int32::nlanes);
1449             v_int32 low2 = vx_load(src2 + x + v_int32::nlanes);
1450             v_int32 high2 = vx_load(src3 + x + v_int32::nlanes);
1451 
1452             v_pack_store(dst + x, v_reinterpret_as_u16(v_pack((values1 >= low1) & (high1 >= values1), (values2 >= low2) & (high2 >= values2))));
1453         }
1454         vx_cleanup();
1455         return x;
1456     }
1457 };
1458 
1459 template <>
1460 struct InRange_SIMD<float>
1461 {
operator ()cv::InRange_SIMD1462     int operator () (const float * src1, const float * src2, const float * src3,
1463         uchar * dst, int len) const
1464     {
1465         int x = 0;
1466         const int width = (int)v_float32::nlanes * 2;
1467 
1468         for (; x <= len - width; x += width)
1469         {
1470             v_float32 values1 = vx_load(src1 + x);
1471             v_float32 low1 = vx_load(src2 + x);
1472             v_float32 high1 = vx_load(src3 + x);
1473 
1474             v_float32 values2 = vx_load(src1 + x + v_float32::nlanes);
1475             v_float32 low2 = vx_load(src2 + x + v_float32::nlanes);
1476             v_float32 high2 = vx_load(src3 + x + v_float32::nlanes);
1477 
1478             v_pack_store(dst + x, v_pack(v_reinterpret_as_u32(values1 >= low1) & v_reinterpret_as_u32(high1 >= values1),
1479                                          v_reinterpret_as_u32(values2 >= low2) & v_reinterpret_as_u32(high2 >= values2)));
1480         }
1481         vx_cleanup();
1482         return x;
1483     }
1484 };
1485 
1486 #endif
1487 
1488 template <typename T>
inRange_(const T * src1,size_t step1,const T * src2,size_t step2,const T * src3,size_t step3,uchar * dst,size_t step,Size size)1489 static void inRange_(const T* src1, size_t step1, const T* src2, size_t step2,
1490          const T* src3, size_t step3, uchar* dst, size_t step,
1491          Size size)
1492 {
1493     step1 /= sizeof(src1[0]);
1494     step2 /= sizeof(src2[0]);
1495     step3 /= sizeof(src3[0]);
1496 
1497     InRange_SIMD<T> vop;
1498 
1499     for( ; size.height--; src1 += step1, src2 += step2, src3 += step3, dst += step )
1500     {
1501         int x = vop(src1, src2, src3, dst, size.width);
1502         #if CV_ENABLE_UNROLLED
1503         for( ; x <= size.width - 4; x += 4 )
1504         {
1505             int t0, t1;
1506             t0 = src2[x] <= src1[x] && src1[x] <= src3[x];
1507             t1 = src2[x+1] <= src1[x+1] && src1[x+1] <= src3[x+1];
1508             dst[x] = (uchar)-t0; dst[x+1] = (uchar)-t1;
1509             t0 = src2[x+2] <= src1[x+2] && src1[x+2] <= src3[x+2];
1510             t1 = src2[x+3] <= src1[x+3] && src1[x+3] <= src3[x+3];
1511             dst[x+2] = (uchar)-t0; dst[x+3] = (uchar)-t1;
1512         }
1513         #endif
1514         for( ; x < size.width; x++ )
1515             dst[x] = (uchar)-(src2[x] <= src1[x] && src1[x] <= src3[x]);
1516     }
1517 }
1518 
1519 
inRange8u(const uchar * src1,size_t step1,const uchar * src2,size_t step2,const uchar * src3,size_t step3,uchar * dst,size_t step,Size size)1520 static void inRange8u(const uchar* src1, size_t step1, const uchar* src2, size_t step2,
1521                       const uchar* src3, size_t step3, uchar* dst, size_t step, Size size)
1522 {
1523     inRange_(src1, step1, src2, step2, src3, step3, dst, step, size);
1524 }
1525 
inRange8s(const schar * src1,size_t step1,const schar * src2,size_t step2,const schar * src3,size_t step3,uchar * dst,size_t step,Size size)1526 static void inRange8s(const schar* src1, size_t step1, const schar* src2, size_t step2,
1527                       const schar* src3, size_t step3, uchar* dst, size_t step, Size size)
1528 {
1529     inRange_(src1, step1, src2, step2, src3, step3, dst, step, size);
1530 }
1531 
inRange16u(const ushort * src1,size_t step1,const ushort * src2,size_t step2,const ushort * src3,size_t step3,uchar * dst,size_t step,Size size)1532 static void inRange16u(const ushort* src1, size_t step1, const ushort* src2, size_t step2,
1533                        const ushort* src3, size_t step3, uchar* dst, size_t step, Size size)
1534 {
1535     inRange_(src1, step1, src2, step2, src3, step3, dst, step, size);
1536 }
1537 
inRange16s(const short * src1,size_t step1,const short * src2,size_t step2,const short * src3,size_t step3,uchar * dst,size_t step,Size size)1538 static void inRange16s(const short* src1, size_t step1, const short* src2, size_t step2,
1539                        const short* src3, size_t step3, uchar* dst, size_t step, Size size)
1540 {
1541     inRange_(src1, step1, src2, step2, src3, step3, dst, step, size);
1542 }
1543 
inRange32s(const int * src1,size_t step1,const int * src2,size_t step2,const int * src3,size_t step3,uchar * dst,size_t step,Size size)1544 static void inRange32s(const int* src1, size_t step1, const int* src2, size_t step2,
1545                        const int* src3, size_t step3, uchar* dst, size_t step, Size size)
1546 {
1547     inRange_(src1, step1, src2, step2, src3, step3, dst, step, size);
1548 }
1549 
inRange32f(const float * src1,size_t step1,const float * src2,size_t step2,const float * src3,size_t step3,uchar * dst,size_t step,Size size)1550 static void inRange32f(const float* src1, size_t step1, const float* src2, size_t step2,
1551                        const float* src3, size_t step3, uchar* dst, size_t step, Size size)
1552 {
1553     inRange_(src1, step1, src2, step2, src3, step3, dst, step, size);
1554 }
1555 
inRange64f(const double * src1,size_t step1,const double * src2,size_t step2,const double * src3,size_t step3,uchar * dst,size_t step,Size size)1556 static void inRange64f(const double* src1, size_t step1, const double* src2, size_t step2,
1557                        const double* src3, size_t step3, uchar* dst, size_t step, Size size)
1558 {
1559     inRange_(src1, step1, src2, step2, src3, step3, dst, step, size);
1560 }
1561 
inRangeReduce(const uchar * src,uchar * dst,size_t len,int cn)1562 static void inRangeReduce(const uchar* src, uchar* dst, size_t len, int cn)
1563 {
1564     int k = cn % 4 ? cn % 4 : 4;
1565     size_t i, j;
1566     if( k == 1 )
1567         for( i = j = 0; i < len; i++, j += cn )
1568             dst[i] = src[j];
1569     else if( k == 2 )
1570         for( i = j = 0; i < len; i++, j += cn )
1571             dst[i] = src[j] & src[j+1];
1572     else if( k == 3 )
1573         for( i = j = 0; i < len; i++, j += cn )
1574             dst[i] = src[j] & src[j+1] & src[j+2];
1575     else
1576         for( i = j = 0; i < len; i++, j += cn )
1577             dst[i] = src[j] & src[j+1] & src[j+2] & src[j+3];
1578 
1579     for( ; k < cn; k += 4 )
1580     {
1581         for( i = 0, j = k; i < len; i++, j += cn )
1582             dst[i] &= src[j] & src[j+1] & src[j+2] & src[j+3];
1583     }
1584 }
1585 
1586 typedef void (*InRangeFunc)( const uchar* src1, size_t step1, const uchar* src2, size_t step2,
1587                              const uchar* src3, size_t step3, uchar* dst, size_t step, Size sz );
1588 
getInRangeFunc(int depth)1589 static InRangeFunc getInRangeFunc(int depth)
1590 {
1591     static InRangeFunc inRangeTab[] =
1592     {
1593         (InRangeFunc)GET_OPTIMIZED(inRange8u), (InRangeFunc)GET_OPTIMIZED(inRange8s), (InRangeFunc)GET_OPTIMIZED(inRange16u),
1594         (InRangeFunc)GET_OPTIMIZED(inRange16s), (InRangeFunc)GET_OPTIMIZED(inRange32s), (InRangeFunc)GET_OPTIMIZED(inRange32f),
1595         (InRangeFunc)inRange64f, 0
1596     };
1597 
1598     return inRangeTab[depth];
1599 }
1600 
1601 #ifdef HAVE_OPENCL
1602 
ocl_inRange(InputArray _src,InputArray _lowerb,InputArray _upperb,OutputArray _dst)1603 static bool ocl_inRange( InputArray _src, InputArray _lowerb,
1604                          InputArray _upperb, OutputArray _dst )
1605 {
1606     const ocl::Device & d = ocl::Device::getDefault();
1607     _InputArray::KindFlag skind = _src.kind(), lkind = _lowerb.kind(), ukind = _upperb.kind();
1608     Size ssize = _src.size(), lsize = _lowerb.size(), usize = _upperb.size();
1609     int stype = _src.type(), ltype = _lowerb.type(), utype = _upperb.type();
1610     int sdepth = CV_MAT_DEPTH(stype), ldepth = CV_MAT_DEPTH(ltype), udepth = CV_MAT_DEPTH(utype);
1611     int cn = CV_MAT_CN(stype), rowsPerWI = d.isIntel() ? 4 : 1;
1612     bool lbScalar = false, ubScalar = false;
1613 
1614     if( (lkind == _InputArray::MATX && skind != _InputArray::MATX) ||
1615         ssize != lsize || stype != ltype )
1616     {
1617         if( !checkScalar(_lowerb, stype, lkind, skind) )
1618             CV_Error( CV_StsUnmatchedSizes,
1619                      "The lower boundary is neither an array of the same size and same type as src, nor a scalar");
1620         lbScalar = true;
1621     }
1622 
1623     if( (ukind == _InputArray::MATX && skind != _InputArray::MATX) ||
1624         ssize != usize || stype != utype )
1625     {
1626         if( !checkScalar(_upperb, stype, ukind, skind) )
1627             CV_Error( CV_StsUnmatchedSizes,
1628                      "The upper boundary is neither an array of the same size and same type as src, nor a scalar");
1629         ubScalar = true;
1630     }
1631 
1632     if (lbScalar != ubScalar)
1633         return false;
1634 
1635     bool doubleSupport = d.doubleFPConfig() > 0,
1636             haveScalar = lbScalar && ubScalar;
1637 
1638     if ( (!doubleSupport && sdepth == CV_64F) ||
1639          (!haveScalar && (sdepth != ldepth || sdepth != udepth)) )
1640         return false;
1641 
1642     int kercn = haveScalar ? cn : std::max(std::min(ocl::predictOptimalVectorWidth(_src, _lowerb, _upperb, _dst), 4), cn);
1643     if (kercn % cn != 0)
1644         kercn = cn;
1645     int colsPerWI = kercn / cn;
1646     String opts = format("%s-D cn=%d -D srcT=%s -D srcT1=%s -D dstT=%s -D kercn=%d -D depth=%d%s -D colsPerWI=%d",
1647                            haveScalar ? "-D HAVE_SCALAR " : "", cn, ocl::typeToStr(CV_MAKE_TYPE(sdepth, kercn)),
1648                            ocl::typeToStr(sdepth), ocl::typeToStr(CV_8UC(colsPerWI)), kercn, sdepth,
1649                            doubleSupport ? " -D DOUBLE_SUPPORT" : "", colsPerWI);
1650 
1651     ocl::Kernel ker("inrange", ocl::core::inrange_oclsrc, opts);
1652     if (ker.empty())
1653         return false;
1654 
1655     _dst.create(ssize, CV_8UC1);
1656     UMat src = _src.getUMat(), dst = _dst.getUMat(), lscalaru, uscalaru;
1657     Mat lscalar, uscalar;
1658 
1659     if (lbScalar && ubScalar)
1660     {
1661         lscalar = _lowerb.getMat();
1662         uscalar = _upperb.getMat();
1663 
1664         size_t esz = src.elemSize();
1665         size_t blocksize = 36;
1666 
1667         AutoBuffer<uchar> _buf(blocksize*(((int)lbScalar + (int)ubScalar)*esz + cn) + 2*cn*sizeof(int) + 128);
1668         uchar *buf = alignPtr(_buf.data() + blocksize*cn, 16);
1669 
1670         if( ldepth != sdepth && sdepth < CV_32S )
1671         {
1672             int* ilbuf = (int*)alignPtr(buf + blocksize*esz, 16);
1673             int* iubuf = ilbuf + cn;
1674 
1675             BinaryFunc sccvtfunc = getConvertFunc(ldepth, CV_32S);
1676             sccvtfunc(lscalar.ptr(), 1, 0, 1, (uchar*)ilbuf, 1, Size(cn, 1), 0);
1677             sccvtfunc(uscalar.ptr(), 1, 0, 1, (uchar*)iubuf, 1, Size(cn, 1), 0);
1678             int minval = cvRound(getMinVal(sdepth)), maxval = cvRound(getMaxVal(sdepth));
1679 
1680             for( int k = 0; k < cn; k++ )
1681             {
1682                 if( ilbuf[k] > iubuf[k] || ilbuf[k] > maxval || iubuf[k] < minval )
1683                     ilbuf[k] = minval+1, iubuf[k] = minval;
1684             }
1685             lscalar = Mat(cn, 1, CV_32S, ilbuf);
1686             uscalar = Mat(cn, 1, CV_32S, iubuf);
1687         }
1688 
1689         lscalar.convertTo(lscalar, stype);
1690         uscalar.convertTo(uscalar, stype);
1691     }
1692     else
1693     {
1694         lscalaru = _lowerb.getUMat();
1695         uscalaru = _upperb.getUMat();
1696     }
1697 
1698     ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
1699             dstarg = ocl::KernelArg::WriteOnly(dst, 1, colsPerWI);
1700 
1701     if (haveScalar)
1702     {
1703         lscalar.copyTo(lscalaru);
1704         uscalar.copyTo(uscalaru);
1705 
1706         ker.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(lscalaru),
1707                ocl::KernelArg::PtrReadOnly(uscalaru), rowsPerWI);
1708     }
1709     else
1710         ker.args(srcarg, dstarg, ocl::KernelArg::ReadOnlyNoSize(lscalaru),
1711                ocl::KernelArg::ReadOnlyNoSize(uscalaru), rowsPerWI);
1712 
1713     size_t globalsize[2] = { (size_t)ssize.width / colsPerWI, ((size_t)ssize.height + rowsPerWI - 1) / rowsPerWI };
1714     return ker.run(2, globalsize, NULL, false);
1715 }
1716 
1717 #endif
1718 
1719 }
1720 
inRange(InputArray _src,InputArray _lowerb,InputArray _upperb,OutputArray _dst)1721 void cv::inRange(InputArray _src, InputArray _lowerb,
1722                  InputArray _upperb, OutputArray _dst)
1723 {
1724     CV_INSTRUMENT_REGION();
1725 
1726     CV_Assert(! _src.empty());
1727 
1728     CV_OCL_RUN(_src.dims() <= 2 && _lowerb.dims() <= 2 &&
1729                _upperb.dims() <= 2 && OCL_PERFORMANCE_CHECK(_dst.isUMat()),
1730                ocl_inRange(_src, _lowerb, _upperb, _dst))
1731 
1732     _InputArray::KindFlag skind = _src.kind(), lkind = _lowerb.kind(), ukind = _upperb.kind();
1733     Mat src = _src.getMat(), lb = _lowerb.getMat(), ub = _upperb.getMat();
1734 
1735     bool lbScalar = false, ubScalar = false;
1736 
1737     if( (lkind == _InputArray::MATX && skind != _InputArray::MATX) ||
1738         src.size != lb.size || src.type() != lb.type() )
1739     {
1740         if( !checkScalar(lb, src.type(), lkind, skind) )
1741             CV_Error( CV_StsUnmatchedSizes,
1742                      "The lower boundary is neither an array of the same size and same type as src, nor a scalar");
1743         lbScalar = true;
1744     }
1745 
1746     if( (ukind == _InputArray::MATX && skind != _InputArray::MATX) ||
1747         src.size != ub.size || src.type() != ub.type() )
1748     {
1749         if( !checkScalar(ub, src.type(), ukind, skind) )
1750             CV_Error( CV_StsUnmatchedSizes,
1751                      "The upper boundary is neither an array of the same size and same type as src, nor a scalar");
1752         ubScalar = true;
1753     }
1754 
1755     CV_Assert(lbScalar == ubScalar);
1756 
1757     int cn = src.channels(), depth = src.depth();
1758 
1759     size_t esz = src.elemSize();
1760     size_t blocksize0 = (size_t)(BLOCK_SIZE + esz-1)/esz;
1761 
1762     _dst.create(src.dims, src.size, CV_8UC1);
1763     Mat dst = _dst.getMat();
1764     InRangeFunc func = getInRangeFunc(depth);
1765 
1766     const Mat* arrays_sc[] = { &src, &dst, 0 };
1767     const Mat* arrays_nosc[] = { &src, &dst, &lb, &ub, 0 };
1768     uchar* ptrs[4] = {};
1769 
1770     NAryMatIterator it(lbScalar && ubScalar ? arrays_sc : arrays_nosc, ptrs);
1771     size_t total = it.size, blocksize = std::min(total, blocksize0);
1772 
1773     AutoBuffer<uchar> _buf(blocksize*(((int)lbScalar + (int)ubScalar)*esz + cn) + 2*cn*sizeof(int) + 128);
1774     uchar *buf = _buf.data(), *mbuf = buf, *lbuf = 0, *ubuf = 0;
1775     buf = alignPtr(buf + blocksize*cn, 16);
1776 
1777     if( lbScalar && ubScalar )
1778     {
1779         lbuf = buf;
1780         ubuf = buf = alignPtr(buf + blocksize*esz, 16);
1781 
1782         CV_Assert( lb.type() == ub.type() );
1783         int scdepth = lb.depth();
1784 
1785         if( scdepth != depth && depth < CV_32S )
1786         {
1787             int* ilbuf = (int*)alignPtr(buf + blocksize*esz, 16);
1788             int* iubuf = ilbuf + cn;
1789 
1790             BinaryFunc sccvtfunc = getConvertFunc(scdepth, CV_32S);
1791             sccvtfunc(lb.ptr(), 1, 0, 1, (uchar*)ilbuf, 1, Size(cn, 1), 0);
1792             sccvtfunc(ub.ptr(), 1, 0, 1, (uchar*)iubuf, 1, Size(cn, 1), 0);
1793             int minval = cvRound(getMinVal(depth)), maxval = cvRound(getMaxVal(depth));
1794 
1795             for( int k = 0; k < cn; k++ )
1796             {
1797                 if( ilbuf[k] > iubuf[k] || ilbuf[k] > maxval || iubuf[k] < minval )
1798                     ilbuf[k] = minval+1, iubuf[k] = minval;
1799             }
1800             lb = Mat(cn, 1, CV_32S, ilbuf);
1801             ub = Mat(cn, 1, CV_32S, iubuf);
1802         }
1803 
1804         convertAndUnrollScalar( lb, src.type(), lbuf, blocksize );
1805         convertAndUnrollScalar( ub, src.type(), ubuf, blocksize );
1806     }
1807 
1808     for( size_t i = 0; i < it.nplanes; i++, ++it )
1809     {
1810         for( size_t j = 0; j < total; j += blocksize )
1811         {
1812             int bsz = (int)MIN(total - j, blocksize);
1813             size_t delta = bsz*esz;
1814             uchar *lptr = lbuf, *uptr = ubuf;
1815             if( !lbScalar )
1816             {
1817                 lptr = ptrs[2];
1818                 ptrs[2] += delta;
1819             }
1820             if( !ubScalar )
1821             {
1822                 int idx = !lbScalar ? 3 : 2;
1823                 uptr = ptrs[idx];
1824                 ptrs[idx] += delta;
1825             }
1826             func( ptrs[0], 0, lptr, 0, uptr, 0, cn == 1 ? ptrs[1] : mbuf, 0, Size(bsz*cn, 1));
1827             if( cn > 1 )
1828                 inRangeReduce(mbuf, ptrs[1], bsz, cn);
1829             ptrs[0] += delta;
1830             ptrs[1] += bsz;
1831         }
1832     }
1833 }
1834 
1835 
1836 #ifndef OPENCV_EXCLUDE_C_API
1837 
1838 /****************************************************************************************\
1839 *                                Earlier API: cvAdd etc.                                 *
1840 \****************************************************************************************/
1841 
1842 CV_IMPL void
cvNot(const CvArr * srcarr,CvArr * dstarr)1843 cvNot( const CvArr* srcarr, CvArr* dstarr )
1844 {
1845     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
1846     CV_Assert( src.size == dst.size && src.type() == dst.type() );
1847     cv::bitwise_not( src, dst );
1848 }
1849 
1850 
1851 CV_IMPL void
cvAnd(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr,const CvArr * maskarr)1852 cvAnd( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr, const CvArr* maskarr )
1853 {
1854     cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2),
1855         dst = cv::cvarrToMat(dstarr), mask;
1856     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
1857     if( maskarr )
1858         mask = cv::cvarrToMat(maskarr);
1859     cv::bitwise_and( src1, src2, dst, mask );
1860 }
1861 
1862 
1863 CV_IMPL void
cvOr(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr,const CvArr * maskarr)1864 cvOr( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr, const CvArr* maskarr )
1865 {
1866     cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2),
1867         dst = cv::cvarrToMat(dstarr), mask;
1868     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
1869     if( maskarr )
1870         mask = cv::cvarrToMat(maskarr);
1871     cv::bitwise_or( src1, src2, dst, mask );
1872 }
1873 
1874 
1875 CV_IMPL void
cvXor(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr,const CvArr * maskarr)1876 cvXor( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr, const CvArr* maskarr )
1877 {
1878     cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2),
1879         dst = cv::cvarrToMat(dstarr), mask;
1880     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
1881     if( maskarr )
1882         mask = cv::cvarrToMat(maskarr);
1883     cv::bitwise_xor( src1, src2, dst, mask );
1884 }
1885 
1886 
1887 CV_IMPL void
cvAndS(const CvArr * srcarr,CvScalar s,CvArr * dstarr,const CvArr * maskarr)1888 cvAndS( const CvArr* srcarr, CvScalar s, CvArr* dstarr, const CvArr* maskarr )
1889 {
1890     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr), mask;
1891     CV_Assert( src.size == dst.size && src.type() == dst.type() );
1892     if( maskarr )
1893         mask = cv::cvarrToMat(maskarr);
1894     cv::bitwise_and( src, (const cv::Scalar&)s, dst, mask );
1895 }
1896 
1897 
1898 CV_IMPL void
cvOrS(const CvArr * srcarr,CvScalar s,CvArr * dstarr,const CvArr * maskarr)1899 cvOrS( const CvArr* srcarr, CvScalar s, CvArr* dstarr, const CvArr* maskarr )
1900 {
1901     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr), mask;
1902     CV_Assert( src.size == dst.size && src.type() == dst.type() );
1903     if( maskarr )
1904         mask = cv::cvarrToMat(maskarr);
1905     cv::bitwise_or( src, (const cv::Scalar&)s, dst, mask );
1906 }
1907 
1908 
1909 CV_IMPL void
cvXorS(const CvArr * srcarr,CvScalar s,CvArr * dstarr,const CvArr * maskarr)1910 cvXorS( const CvArr* srcarr, CvScalar s, CvArr* dstarr, const CvArr* maskarr )
1911 {
1912     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr), mask;
1913     CV_Assert( src.size == dst.size && src.type() == dst.type() );
1914     if( maskarr )
1915         mask = cv::cvarrToMat(maskarr);
1916     cv::bitwise_xor( src, (const cv::Scalar&)s, dst, mask );
1917 }
1918 
1919 
cvAdd(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr,const CvArr * maskarr)1920 CV_IMPL void cvAdd( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr, const CvArr* maskarr )
1921 {
1922     cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2),
1923         dst = cv::cvarrToMat(dstarr), mask;
1924     CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() );
1925     if( maskarr )
1926         mask = cv::cvarrToMat(maskarr);
1927     cv::add( src1, src2, dst, mask, dst.type() );
1928 }
1929 
1930 
cvSub(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr,const CvArr * maskarr)1931 CV_IMPL void cvSub( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr, const CvArr* maskarr )
1932 {
1933     cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2),
1934         dst = cv::cvarrToMat(dstarr), mask;
1935     CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() );
1936     if( maskarr )
1937         mask = cv::cvarrToMat(maskarr);
1938     cv::subtract( src1, src2, dst, mask, dst.type() );
1939 }
1940 
1941 
cvAddS(const CvArr * srcarr1,CvScalar value,CvArr * dstarr,const CvArr * maskarr)1942 CV_IMPL void cvAddS( const CvArr* srcarr1, CvScalar value, CvArr* dstarr, const CvArr* maskarr )
1943 {
1944     cv::Mat src1 = cv::cvarrToMat(srcarr1),
1945         dst = cv::cvarrToMat(dstarr), mask;
1946     CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() );
1947     if( maskarr )
1948         mask = cv::cvarrToMat(maskarr);
1949     cv::add( src1, (const cv::Scalar&)value, dst, mask, dst.type() );
1950 }
1951 
1952 
cvSubRS(const CvArr * srcarr1,CvScalar value,CvArr * dstarr,const CvArr * maskarr)1953 CV_IMPL void cvSubRS( const CvArr* srcarr1, CvScalar value, CvArr* dstarr, const CvArr* maskarr )
1954 {
1955     cv::Mat src1 = cv::cvarrToMat(srcarr1),
1956         dst = cv::cvarrToMat(dstarr), mask;
1957     CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() );
1958     if( maskarr )
1959         mask = cv::cvarrToMat(maskarr);
1960     cv::subtract( (const cv::Scalar&)value, src1, dst, mask, dst.type() );
1961 }
1962 
1963 
cvMul(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr,double scale)1964 CV_IMPL void cvMul( const CvArr* srcarr1, const CvArr* srcarr2,
1965                     CvArr* dstarr, double scale )
1966 {
1967     cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2),
1968         dst = cv::cvarrToMat(dstarr);
1969     CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() );
1970     cv::multiply( src1, src2, dst, scale, dst.type() );
1971 }
1972 
1973 
cvDiv(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr,double scale)1974 CV_IMPL void cvDiv( const CvArr* srcarr1, const CvArr* srcarr2,
1975                     CvArr* dstarr, double scale )
1976 {
1977     cv::Mat src2 = cv::cvarrToMat(srcarr2),
1978         dst = cv::cvarrToMat(dstarr), mask;
1979     CV_Assert( src2.size == dst.size && src2.channels() == dst.channels() );
1980 
1981     if( srcarr1 )
1982         cv::divide( cv::cvarrToMat(srcarr1), src2, dst, scale, dst.type() );
1983     else
1984         cv::divide( scale, src2, dst, dst.type() );
1985 }
1986 
1987 
1988 CV_IMPL void
cvAddWeighted(const CvArr * srcarr1,double alpha,const CvArr * srcarr2,double beta,double gamma,CvArr * dstarr)1989 cvAddWeighted( const CvArr* srcarr1, double alpha,
1990                const CvArr* srcarr2, double beta,
1991                double gamma, CvArr* dstarr )
1992 {
1993     cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2),
1994         dst = cv::cvarrToMat(dstarr);
1995     CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() );
1996     cv::addWeighted( src1, alpha, src2, beta, gamma, dst, dst.type() );
1997 }
1998 
1999 
2000 CV_IMPL  void
cvAbsDiff(const CvArr * srcarr1,const CvArr * srcarr2,CvArr * dstarr)2001 cvAbsDiff( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr )
2002 {
2003     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2004     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
2005 
2006     cv::absdiff( src1, cv::cvarrToMat(srcarr2), dst );
2007 }
2008 
2009 
2010 CV_IMPL void
cvAbsDiffS(const CvArr * srcarr1,CvArr * dstarr,CvScalar scalar)2011 cvAbsDiffS( const CvArr* srcarr1, CvArr* dstarr, CvScalar scalar )
2012 {
2013     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2014     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
2015 
2016     cv::absdiff( src1, (const cv::Scalar&)scalar, dst );
2017 }
2018 
2019 
2020 CV_IMPL void
cvInRange(const void * srcarr1,const void * srcarr2,const void * srcarr3,void * dstarr)2021 cvInRange( const void* srcarr1, const void* srcarr2,
2022            const void* srcarr3, void* dstarr )
2023 {
2024     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2025     CV_Assert( src1.size == dst.size && dst.type() == CV_8U );
2026 
2027     cv::inRange( src1, cv::cvarrToMat(srcarr2), cv::cvarrToMat(srcarr3), dst );
2028 }
2029 
2030 
2031 CV_IMPL void
cvInRangeS(const void * srcarr1,CvScalar lowerb,CvScalar upperb,void * dstarr)2032 cvInRangeS( const void* srcarr1, CvScalar lowerb, CvScalar upperb, void* dstarr )
2033 {
2034     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2035     CV_Assert( src1.size == dst.size && dst.type() == CV_8U );
2036 
2037     cv::inRange( src1, (const cv::Scalar&)lowerb, (const cv::Scalar&)upperb, dst );
2038 }
2039 
2040 
2041 CV_IMPL void
cvCmp(const void * srcarr1,const void * srcarr2,void * dstarr,int cmp_op)2042 cvCmp( const void* srcarr1, const void* srcarr2, void* dstarr, int cmp_op )
2043 {
2044     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2045     CV_Assert( src1.size == dst.size && dst.type() == CV_8U );
2046 
2047     cv::compare( src1, cv::cvarrToMat(srcarr2), dst, cmp_op );
2048 }
2049 
2050 
2051 CV_IMPL void
cvCmpS(const void * srcarr1,double value,void * dstarr,int cmp_op)2052 cvCmpS( const void* srcarr1, double value, void* dstarr, int cmp_op )
2053 {
2054     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2055     CV_Assert( src1.size == dst.size && dst.type() == CV_8U );
2056 
2057     cv::compare( src1, value, dst, cmp_op );
2058 }
2059 
2060 
2061 CV_IMPL void
cvMin(const void * srcarr1,const void * srcarr2,void * dstarr)2062 cvMin( const void* srcarr1, const void* srcarr2, void* dstarr )
2063 {
2064     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2065     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
2066 
2067     cv::min( src1, cv::cvarrToMat(srcarr2), dst );
2068 }
2069 
2070 
2071 CV_IMPL void
cvMax(const void * srcarr1,const void * srcarr2,void * dstarr)2072 cvMax( const void* srcarr1, const void* srcarr2, void* dstarr )
2073 {
2074     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2075     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
2076 
2077     cv::max( src1, cv::cvarrToMat(srcarr2), dst );
2078 }
2079 
2080 
2081 CV_IMPL void
cvMinS(const void * srcarr1,double value,void * dstarr)2082 cvMinS( const void* srcarr1, double value, void* dstarr )
2083 {
2084     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2085     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
2086 
2087     cv::min( src1, value, dst );
2088 }
2089 
2090 
2091 CV_IMPL void
cvMaxS(const void * srcarr1,double value,void * dstarr)2092 cvMaxS( const void* srcarr1, double value, void* dstarr )
2093 {
2094     cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr);
2095     CV_Assert( src1.size == dst.size && src1.type() == dst.type() );
2096 
2097     cv::max( src1, value, dst );
2098 }
2099 
2100 #endif  // OPENCV_EXCLUDE_C_API
2101 /* End of file. */
2102