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, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2014, 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 #include "precomp.hpp"
45 #include "opencl_kernels_imgproc.hpp"
46 #include "opencv2/core/hal/intrin.hpp"
47 #define CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
48 #include "accum.simd.hpp"
49 #include "accum.simd_declarations.hpp"
50 #include "opencv2/core/openvx/ovx_defs.hpp"
51 
52 namespace cv
53 {
54 
55 typedef void(*AccFunc)(const uchar*, uchar*, const uchar*, int, int);
56 typedef void(*AccProdFunc)(const uchar*, const uchar*, uchar*, const uchar*, int, int);
57 typedef void(*AccWFunc)(const uchar*, uchar*, const uchar*, int, int, double);
58 
59 static AccFunc accTab[] =
60 {
61     (AccFunc)acc_8u32f, (AccFunc)acc_8u64f,
62     (AccFunc)acc_16u32f, (AccFunc)acc_16u64f,
63     (AccFunc)acc_32f, (AccFunc)acc_32f64f,
64     (AccFunc)acc_64f
65 };
66 
67 static AccFunc accSqrTab[] =
68 {
69     (AccFunc)accSqr_8u32f, (AccFunc)accSqr_8u64f,
70     (AccFunc)accSqr_16u32f, (AccFunc)accSqr_16u64f,
71     (AccFunc)accSqr_32f, (AccFunc)accSqr_32f64f,
72     (AccFunc)accSqr_64f
73 };
74 
75 static AccProdFunc accProdTab[] =
76 {
77     (AccProdFunc)accProd_8u32f, (AccProdFunc)accProd_8u64f,
78     (AccProdFunc)accProd_16u32f, (AccProdFunc)accProd_16u64f,
79     (AccProdFunc)accProd_32f, (AccProdFunc)accProd_32f64f,
80     (AccProdFunc)accProd_64f
81 };
82 
83 static AccWFunc accWTab[] =
84 {
85     (AccWFunc)accW_8u32f, (AccWFunc)accW_8u64f,
86     (AccWFunc)accW_16u32f, (AccWFunc)accW_16u64f,
87     (AccWFunc)accW_32f, (AccWFunc)accW_32f64f,
88     (AccWFunc)accW_64f
89 };
90 
getAccTabIdx(int sdepth,int ddepth)91 inline int getAccTabIdx(int sdepth, int ddepth)
92 {
93     return sdepth == CV_8U && ddepth == CV_32F ? 0 :
94            sdepth == CV_8U && ddepth == CV_64F ? 1 :
95            sdepth == CV_16U && ddepth == CV_32F ? 2 :
96            sdepth == CV_16U && ddepth == CV_64F ? 3 :
97            sdepth == CV_32F && ddepth == CV_32F ? 4 :
98            sdepth == CV_32F && ddepth == CV_64F ? 5 :
99            sdepth == CV_64F && ddepth == CV_64F ? 6 : -1;
100 }
101 
102 #ifdef HAVE_OPENCL
103 
104 enum
105 {
106     ACCUMULATE = 0,
107     ACCUMULATE_SQUARE = 1,
108     ACCUMULATE_PRODUCT = 2,
109     ACCUMULATE_WEIGHTED = 3
110 };
111 
ocl_accumulate(InputArray _src,InputArray _src2,InputOutputArray _dst,double alpha,InputArray _mask,int op_type)112 static bool ocl_accumulate( InputArray _src, InputArray _src2, InputOutputArray _dst, double alpha,
113                             InputArray _mask, int op_type )
114 {
115     CV_Assert(op_type == ACCUMULATE || op_type == ACCUMULATE_SQUARE ||
116               op_type == ACCUMULATE_PRODUCT || op_type == ACCUMULATE_WEIGHTED);
117 
118     const ocl::Device & dev = ocl::Device::getDefault();
119     bool haveMask = !_mask.empty(), doubleSupport = dev.doubleFPConfig() > 0;
120     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), ddepth = _dst.depth();
121     int kercn = haveMask ? cn : ocl::predictOptimalVectorWidthMax(_src, _src2, _dst), rowsPerWI = dev.isIntel() ? 4 : 1;
122 
123     if (!doubleSupport && (sdepth == CV_64F || ddepth == CV_64F))
124         return false;
125 
126     const char * const opMap[4] = { "ACCUMULATE", "ACCUMULATE_SQUARE", "ACCUMULATE_PRODUCT",
127                                    "ACCUMULATE_WEIGHTED" };
128 
129     char cvt[40];
130     ocl::Kernel k("accumulate", ocl::imgproc::accumulate_oclsrc,
131                   format("-D %s%s -D srcT1=%s -D cn=%d -D dstT1=%s%s -D rowsPerWI=%d -D convertToDT=%s",
132                          opMap[op_type], haveMask ? " -D HAVE_MASK" : "",
133                          ocl::typeToStr(sdepth), kercn, ocl::typeToStr(ddepth),
134                          doubleSupport ? " -D DOUBLE_SUPPORT" : "", rowsPerWI,
135                          ocl::convertTypeStr(sdepth, ddepth, 1, cvt)));
136     if (k.empty())
137         return false;
138 
139     UMat src = _src.getUMat(), src2 = _src2.getUMat(), dst = _dst.getUMat(), mask = _mask.getUMat();
140 
141     ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
142             src2arg = ocl::KernelArg::ReadOnlyNoSize(src2),
143             dstarg = ocl::KernelArg::ReadWrite(dst, cn, kercn),
144             maskarg = ocl::KernelArg::ReadOnlyNoSize(mask);
145 
146     int argidx = k.set(0, srcarg);
147     if (op_type == ACCUMULATE_PRODUCT)
148         argidx = k.set(argidx, src2arg);
149     argidx = k.set(argidx, dstarg);
150     if (op_type == ACCUMULATE_WEIGHTED)
151     {
152         if (ddepth == CV_32F)
153             argidx = k.set(argidx, (float)alpha);
154         else
155             argidx = k.set(argidx, alpha);
156     }
157     if (haveMask)
158         k.set(argidx, maskarg);
159 
160     size_t globalsize[2] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
161     return k.run(2, globalsize, NULL, false);
162 }
163 
164 #endif
165 
166 }
167 
168 #if defined(HAVE_IPP)
169 namespace cv
170 {
ipp_accumulate(InputArray _src,InputOutputArray _dst,InputArray _mask)171 static bool ipp_accumulate(InputArray _src, InputOutputArray _dst, InputArray _mask)
172 {
173     CV_INSTRUMENT_REGION_IPP();
174 
175     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
176     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype);
177 
178     Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
179 
180     if (src.dims <= 2 || (src.isContinuous() && dst.isContinuous() && (mask.empty() || mask.isContinuous())))
181     {
182         typedef IppStatus (CV_STDCALL * IppiAdd)(const void * pSrc, int srcStep, Ipp32f * pSrcDst, int srcdstStep, IppiSize roiSize);
183         typedef IppStatus (CV_STDCALL * IppiAddMask)(const void * pSrc, int srcStep, const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst,
184                                                     int srcDstStep, IppiSize roiSize);
185         IppiAdd ippiAdd_I = 0;
186         IppiAddMask ippiAdd_IM = 0;
187 
188         if (mask.empty())
189         {
190             CV_SUPPRESS_DEPRECATED_START
191             ippiAdd_I = sdepth == CV_8U && ddepth == CV_32F ? (IppiAdd)ippiAdd_8u32f_C1IR :
192                 sdepth == CV_16U && ddepth == CV_32F ? (IppiAdd)ippiAdd_16u32f_C1IR :
193                 sdepth == CV_32F && ddepth == CV_32F ? (IppiAdd)ippiAdd_32f_C1IR : 0;
194             CV_SUPPRESS_DEPRECATED_END
195         }
196         else if (scn == 1)
197         {
198             ippiAdd_IM = sdepth == CV_8U && ddepth == CV_32F ? (IppiAddMask)ippiAdd_8u32f_C1IMR :
199                 sdepth == CV_16U && ddepth == CV_32F ? (IppiAddMask)ippiAdd_16u32f_C1IMR :
200                 sdepth == CV_32F && ddepth == CV_32F ? (IppiAddMask)ippiAdd_32f_C1IMR : 0;
201         }
202 
203         if (ippiAdd_I || ippiAdd_IM)
204         {
205             IppStatus status = ippStsErr;
206 
207             Size size = src.size();
208             int srcstep = (int)src.step, dststep = (int)dst.step, maskstep = (int)mask.step;
209             if (src.isContinuous() && dst.isContinuous() && mask.isContinuous())
210             {
211                 srcstep = static_cast<int>(src.total() * src.elemSize());
212                 dststep = static_cast<int>(dst.total() * dst.elemSize());
213                 maskstep = static_cast<int>(mask.total() * mask.elemSize());
214                 size.width = static_cast<int>(src.total());
215                 size.height = 1;
216             }
217             size.width *= scn;
218 
219             if (ippiAdd_I)
220                 status = CV_INSTRUMENT_FUN_IPP(ippiAdd_I, src.ptr(), srcstep, dst.ptr<Ipp32f>(), dststep, ippiSize(size.width, size.height));
221             else if (ippiAdd_IM)
222                 status = CV_INSTRUMENT_FUN_IPP(ippiAdd_IM, src.ptr(), srcstep, mask.ptr<Ipp8u>(), maskstep,
223                     dst.ptr<Ipp32f>(), dststep, ippiSize(size.width, size.height));
224 
225             if (status >= 0)
226                 return true;
227         }
228     }
229     return false;
230 }
231 }
232 #endif
233 
234 #ifdef HAVE_OPENVX
235 namespace cv
236 {
237 enum
238 {
239     VX_ACCUMULATE_OP = 0,
240     VX_ACCUMULATE_SQUARE_OP = 1,
241     VX_ACCUMULATE_WEIGHTED_OP = 2
242 };
243 
244 namespace ovx {
skipSmallImages(int w,int h)245     template <> inline bool skipSmallImages<VX_KERNEL_ACCUMULATE>(int w, int h) { return w*h < 120 * 60; }
246 }
openvx_accumulate(InputArray _src,InputOutputArray _dst,InputArray _mask,double _weight,int opType)247 static bool openvx_accumulate(InputArray _src, InputOutputArray _dst, InputArray _mask, double _weight, int opType)
248 {
249     Mat srcMat = _src.getMat(), dstMat = _dst.getMat();
250     if (ovx::skipSmallImages<VX_KERNEL_ACCUMULATE>(srcMat.cols, srcMat.rows))
251         return false;
252     if(!_mask.empty() ||
253        (opType == VX_ACCUMULATE_WEIGHTED_OP && dstMat.type() != CV_8UC1  ) ||
254        (opType != VX_ACCUMULATE_WEIGHTED_OP && dstMat.type() != CV_16SC1 ) ||
255        srcMat.type() != CV_8UC1)
256     {
257         return false;
258     }
259     //TODO: handle different number of channels (channel extract && channel combine)
260     //TODO: handle mask (threshold mask to 0xff && bitwise AND with src)
261     //(both things can be done by creating a graph)
262 
263     try
264     {
265         ivx::Context context = ovx::getOpenVXContext();
266         ivx::Image srcImage = ivx::Image::createFromHandle(context, ivx::Image::matTypeToFormat(srcMat.type()),
267                                                            ivx::Image::createAddressing(srcMat), srcMat.data);
268         ivx::Image dstImage = ivx::Image::createFromHandle(context, ivx::Image::matTypeToFormat(dstMat.type()),
269                                                            ivx::Image::createAddressing(dstMat), dstMat.data);
270         ivx::Scalar shift = ivx::Scalar::create<VX_TYPE_UINT32>(context, 0);
271         ivx::Scalar alpha = ivx::Scalar::create<VX_TYPE_FLOAT32>(context, _weight);
272 
273         switch (opType)
274         {
275         case VX_ACCUMULATE_OP:
276             ivx::IVX_CHECK_STATUS(vxuAccumulateImage(context, srcImage, dstImage));
277             break;
278         case VX_ACCUMULATE_SQUARE_OP:
279             ivx::IVX_CHECK_STATUS(vxuAccumulateSquareImage(context, srcImage, shift, dstImage));
280             break;
281         case VX_ACCUMULATE_WEIGHTED_OP:
282             ivx::IVX_CHECK_STATUS(vxuAccumulateWeightedImage(context, srcImage, alpha, dstImage));
283             break;
284         default:
285             break;
286         }
287 
288 #ifdef VX_VERSION_1_1
289         //we should take user memory back before release
290         //(it's not done automatically according to standard)
291         srcImage.swapHandle(); dstImage.swapHandle();
292 #endif
293     }
294     catch (const ivx::RuntimeError & e)
295     {
296         VX_DbgThrow(e.what());
297     }
298     catch (const ivx::WrapperError & e)
299     {
300         VX_DbgThrow(e.what());
301     }
302 
303     return true;
304 }
305 }
306 #endif
307 
accumulate(InputArray _src,InputOutputArray _dst,InputArray _mask)308 void cv::accumulate( InputArray _src, InputOutputArray _dst, InputArray _mask )
309 {
310     CV_INSTRUMENT_REGION();
311 
312     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
313     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
314 
315     CV_Assert( _src.sameSize(_dst) && dcn == scn );
316     CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) );
317 
318     CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
319                ocl_accumulate(_src, noArray(), _dst, 0.0, _mask, ACCUMULATE))
320 
321     CV_IPP_RUN((_src.dims() <= 2 || (_src.isContinuous() && _dst.isContinuous() && (_mask.empty() || _mask.isContinuous()))),
322         ipp_accumulate(_src, _dst, _mask));
323 
324     CV_OVX_RUN(_src.dims() <= 2,
325                openvx_accumulate(_src, _dst, _mask, 0.0, VX_ACCUMULATE_OP))
326 
327     Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
328 
329 
330     int fidx = getAccTabIdx(sdepth, ddepth);
331     AccFunc func = fidx >= 0 ? accTab[fidx] : 0;
332     CV_Assert( func != 0 );
333 
334     const Mat* arrays[] = {&src, &dst, &mask, 0};
335     uchar* ptrs[3] = {};
336     NAryMatIterator it(arrays, ptrs);
337     int len = (int)it.size;
338 
339     for( size_t i = 0; i < it.nplanes; i++, ++it )
340         func(ptrs[0], ptrs[1], ptrs[2], len, scn);
341 }
342 
343 #if defined(HAVE_IPP)
344 namespace cv
345 {
ipp_accumulate_square(InputArray _src,InputOutputArray _dst,InputArray _mask)346 static bool ipp_accumulate_square(InputArray _src, InputOutputArray _dst, InputArray _mask)
347 {
348     CV_INSTRUMENT_REGION_IPP();
349 
350     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
351     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype);
352 
353     Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
354 
355     if (src.dims <= 2 || (src.isContinuous() && dst.isContinuous() && (mask.empty() || mask.isContinuous())))
356     {
357         typedef IppStatus (CV_STDCALL * ippiAddSquare)(const void * pSrc, int srcStep, Ipp32f * pSrcDst, int srcdstStep, IppiSize roiSize);
358         typedef IppStatus (CV_STDCALL * ippiAddSquareMask)(const void * pSrc, int srcStep, const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst,
359                                                             int srcDstStep, IppiSize roiSize);
360         ippiAddSquare ippiAddSquare_I = 0;
361         ippiAddSquareMask ippiAddSquare_IM = 0;
362 
363         if (mask.empty())
364         {
365             ippiAddSquare_I = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddSquare)ippiAddSquare_8u32f_C1IR :
366                 sdepth == CV_16U && ddepth == CV_32F ? (ippiAddSquare)ippiAddSquare_16u32f_C1IR :
367                 sdepth == CV_32F && ddepth == CV_32F ? (ippiAddSquare)ippiAddSquare_32f_C1IR : 0;
368         }
369         else if (scn == 1)
370         {
371             ippiAddSquare_IM = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddSquareMask)ippiAddSquare_8u32f_C1IMR :
372                 sdepth == CV_16U && ddepth == CV_32F ? (ippiAddSquareMask)ippiAddSquare_16u32f_C1IMR :
373                 sdepth == CV_32F && ddepth == CV_32F ? (ippiAddSquareMask)ippiAddSquare_32f_C1IMR : 0;
374         }
375 
376         if (ippiAddSquare_I || ippiAddSquare_IM)
377         {
378             IppStatus status = ippStsErr;
379 
380             Size size = src.size();
381             int srcstep = (int)src.step, dststep = (int)dst.step, maskstep = (int)mask.step;
382             if (src.isContinuous() && dst.isContinuous() && mask.isContinuous())
383             {
384                 srcstep = static_cast<int>(src.total() * src.elemSize());
385                 dststep = static_cast<int>(dst.total() * dst.elemSize());
386                 maskstep = static_cast<int>(mask.total() * mask.elemSize());
387                 size.width = static_cast<int>(src.total());
388                 size.height = 1;
389             }
390             size.width *= scn;
391 
392             if (ippiAddSquare_I)
393                 status = CV_INSTRUMENT_FUN_IPP(ippiAddSquare_I, src.ptr(), srcstep, dst.ptr<Ipp32f>(), dststep, ippiSize(size.width, size.height));
394             else if (ippiAddSquare_IM)
395                 status = CV_INSTRUMENT_FUN_IPP(ippiAddSquare_IM, src.ptr(), srcstep, mask.ptr<Ipp8u>(), maskstep,
396                     dst.ptr<Ipp32f>(), dststep, ippiSize(size.width, size.height));
397 
398             if (status >= 0)
399                 return true;
400         }
401     }
402     return false;
403 }
404 }
405 #endif
406 
accumulateSquare(InputArray _src,InputOutputArray _dst,InputArray _mask)407 void cv::accumulateSquare( InputArray _src, InputOutputArray _dst, InputArray _mask )
408 {
409     CV_INSTRUMENT_REGION();
410 
411     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
412     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
413 
414     CV_Assert( _src.sameSize(_dst) && dcn == scn );
415     CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) );
416 
417     CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
418                ocl_accumulate(_src, noArray(), _dst, 0.0, _mask, ACCUMULATE_SQUARE))
419 
420     CV_IPP_RUN((_src.dims() <= 2 || (_src.isContinuous() && _dst.isContinuous() && (_mask.empty() || _mask.isContinuous()))),
421         ipp_accumulate_square(_src, _dst, _mask));
422 
423     CV_OVX_RUN(_src.dims() <= 2,
424                openvx_accumulate(_src, _dst, _mask, 0.0, VX_ACCUMULATE_SQUARE_OP))
425 
426     Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
427 
428     int fidx = getAccTabIdx(sdepth, ddepth);
429     AccFunc func = fidx >= 0 ? accSqrTab[fidx] : 0;
430     CV_Assert( func != 0 );
431 
432     const Mat* arrays[] = {&src, &dst, &mask, 0};
433     uchar* ptrs[3] = {};
434     NAryMatIterator it(arrays, ptrs);
435     int len = (int)it.size;
436 
437     for( size_t i = 0; i < it.nplanes; i++, ++it )
438         func(ptrs[0], ptrs[1], ptrs[2], len, scn);
439 }
440 
441 #if defined(HAVE_IPP)
442 namespace cv
443 {
ipp_accumulate_product(InputArray _src1,InputArray _src2,InputOutputArray _dst,InputArray _mask)444 static bool ipp_accumulate_product(InputArray _src1, InputArray _src2,
445                             InputOutputArray _dst, InputArray _mask)
446 {
447     CV_INSTRUMENT_REGION_IPP();
448 
449     int stype = _src1.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
450     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype);
451 
452     Mat src1 = _src1.getMat(), src2 = _src2.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
453 
454     if (src1.dims <= 2 || (src1.isContinuous() && src2.isContinuous() && dst.isContinuous()))
455     {
456         typedef IppStatus (CV_STDCALL * ippiAddProduct)(const void * pSrc1, int src1Step, const void * pSrc2,
457                                                         int src2Step, Ipp32f * pSrcDst, int srcDstStep, IppiSize roiSize);
458         typedef IppStatus (CV_STDCALL * ippiAddProductMask)(const void * pSrc1, int src1Step, const void * pSrc2, int src2Step,
459                                                             const Ipp8u * pMask, int maskStep, Ipp32f * pSrcDst, int srcDstStep, IppiSize roiSize);
460         ippiAddProduct ippiAddProduct_I = 0;
461         ippiAddProductMask ippiAddProduct_IM = 0;
462 
463         if (mask.empty())
464         {
465             ippiAddProduct_I = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddProduct)ippiAddProduct_8u32f_C1IR :
466                 sdepth == CV_16U && ddepth == CV_32F ? (ippiAddProduct)ippiAddProduct_16u32f_C1IR :
467                 sdepth == CV_32F && ddepth == CV_32F ? (ippiAddProduct)ippiAddProduct_32f_C1IR : 0;
468         }
469         else if (scn == 1)
470         {
471             ippiAddProduct_IM = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddProductMask)ippiAddProduct_8u32f_C1IMR :
472                 sdepth == CV_16U && ddepth == CV_32F ? (ippiAddProductMask)ippiAddProduct_16u32f_C1IMR :
473                 sdepth == CV_32F && ddepth == CV_32F ? (ippiAddProductMask)ippiAddProduct_32f_C1IMR : 0;
474         }
475 
476         if (ippiAddProduct_I || ippiAddProduct_IM)
477         {
478             IppStatus status = ippStsErr;
479 
480             Size size = src1.size();
481             int src1step = (int)src1.step, src2step = (int)src2.step, dststep = (int)dst.step, maskstep = (int)mask.step;
482             if (src1.isContinuous() && src2.isContinuous() && dst.isContinuous() && mask.isContinuous())
483             {
484                 src1step = static_cast<int>(src1.total() * src1.elemSize());
485                 src2step = static_cast<int>(src2.total() * src2.elemSize());
486                 dststep = static_cast<int>(dst.total() * dst.elemSize());
487                 maskstep = static_cast<int>(mask.total() * mask.elemSize());
488                 size.width = static_cast<int>(src1.total());
489                 size.height = 1;
490             }
491             size.width *= scn;
492 
493             if (ippiAddProduct_I)
494                 status = CV_INSTRUMENT_FUN_IPP(ippiAddProduct_I, src1.ptr(), src1step, src2.ptr(), src2step, dst.ptr<Ipp32f>(),
495                     dststep, ippiSize(size.width, size.height));
496             else if (ippiAddProduct_IM)
497                 status = CV_INSTRUMENT_FUN_IPP(ippiAddProduct_IM, src1.ptr(), src1step, src2.ptr(), src2step, mask.ptr<Ipp8u>(), maskstep,
498                     dst.ptr<Ipp32f>(), dststep, ippiSize(size.width, size.height));
499 
500             if (status >= 0)
501                 return true;
502         }
503     }
504     return false;
505 }
506 }
507 #endif
508 
509 
510 
accumulateProduct(InputArray _src1,InputArray _src2,InputOutputArray _dst,InputArray _mask)511 void cv::accumulateProduct( InputArray _src1, InputArray _src2,
512                             InputOutputArray _dst, InputArray _mask )
513 {
514     CV_INSTRUMENT_REGION();
515 
516     int stype = _src1.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
517     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
518 
519     CV_Assert( _src1.sameSize(_src2) && stype == _src2.type() );
520     CV_Assert( _src1.sameSize(_dst) && dcn == scn );
521     CV_Assert( _mask.empty() || (_src1.sameSize(_mask) && _mask.type() == CV_8U) );
522 
523     CV_OCL_RUN(_src1.dims() <= 2 && _dst.isUMat(),
524                ocl_accumulate(_src1, _src2, _dst, 0.0, _mask, ACCUMULATE_PRODUCT))
525 
526     CV_IPP_RUN( (_src1.dims() <= 2 || (_src1.isContinuous() && _src2.isContinuous() && _dst.isContinuous())),
527         ipp_accumulate_product(_src1, _src2, _dst, _mask));
528 
529     Mat src1 = _src1.getMat(), src2 = _src2.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
530 
531     int fidx = getAccTabIdx(sdepth, ddepth);
532     AccProdFunc func = fidx >= 0 ? accProdTab[fidx] : 0;
533     CV_Assert( func != 0 );
534 
535     const Mat* arrays[] = {&src1, &src2, &dst, &mask, 0};
536     uchar* ptrs[4] = {};
537     NAryMatIterator it(arrays, ptrs);
538     int len = (int)it.size;
539 
540     for( size_t i = 0; i < it.nplanes; i++, ++it )
541         func(ptrs[0], ptrs[1], ptrs[2], ptrs[3], len, scn);
542 }
543 
544 #if defined(HAVE_IPP)
545 namespace cv
546 {
ipp_accumulate_weighted(InputArray _src,InputOutputArray _dst,double alpha,InputArray _mask)547 static bool ipp_accumulate_weighted( InputArray _src, InputOutputArray _dst,
548                              double alpha, InputArray _mask )
549 {
550     CV_INSTRUMENT_REGION_IPP();
551 
552     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
553     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype);
554 
555     Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
556 
557     if (src.dims <= 2 || (src.isContinuous() && dst.isContinuous() && mask.isContinuous()))
558     {
559         typedef IppStatus (CV_STDCALL * ippiAddWeighted)(const void * pSrc, int srcStep, Ipp32f * pSrcDst, int srcdstStep,
560                                                             IppiSize roiSize, Ipp32f alpha);
561         typedef IppStatus (CV_STDCALL * ippiAddWeightedMask)(const void * pSrc, int srcStep, const Ipp8u * pMask,
562                                                                 int maskStep, Ipp32f * pSrcDst,
563                                                                 int srcDstStep, IppiSize roiSize, Ipp32f alpha);
564         ippiAddWeighted ippiAddWeighted_I = 0;
565         ippiAddWeightedMask ippiAddWeighted_IM = 0;
566 
567         if (mask.empty())
568         {
569             ippiAddWeighted_I = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddWeighted)ippiAddWeighted_8u32f_C1IR :
570                 sdepth == CV_16U && ddepth == CV_32F ? (ippiAddWeighted)ippiAddWeighted_16u32f_C1IR :
571                 sdepth == CV_32F && ddepth == CV_32F ? (ippiAddWeighted)ippiAddWeighted_32f_C1IR : 0;
572         }
573         else if (scn == 1)
574         {
575             ippiAddWeighted_IM = sdepth == CV_8U && ddepth == CV_32F ? (ippiAddWeightedMask)ippiAddWeighted_8u32f_C1IMR :
576                 sdepth == CV_16U && ddepth == CV_32F ? (ippiAddWeightedMask)ippiAddWeighted_16u32f_C1IMR :
577                 sdepth == CV_32F && ddepth == CV_32F ? (ippiAddWeightedMask)ippiAddWeighted_32f_C1IMR : 0;
578         }
579 
580         if (ippiAddWeighted_I || ippiAddWeighted_IM)
581         {
582             IppStatus status = ippStsErr;
583 
584             Size size = src.size();
585             int srcstep = (int)src.step, dststep = (int)dst.step, maskstep = (int)mask.step;
586             if (src.isContinuous() && dst.isContinuous() && mask.isContinuous())
587             {
588                 srcstep = static_cast<int>(src.total() * src.elemSize());
589                 dststep = static_cast<int>(dst.total() * dst.elemSize());
590                 maskstep = static_cast<int>(mask.total() * mask.elemSize());
591                 size.width = static_cast<int>((int)src.total());
592                 size.height = 1;
593             }
594             size.width *= scn;
595 
596             if (ippiAddWeighted_I)
597                 status = CV_INSTRUMENT_FUN_IPP(ippiAddWeighted_I, src.ptr(), srcstep, dst.ptr<Ipp32f>(), dststep, ippiSize(size.width, size.height), (Ipp32f)alpha);
598             else if (ippiAddWeighted_IM)
599                 status = CV_INSTRUMENT_FUN_IPP(ippiAddWeighted_IM, src.ptr(), srcstep, mask.ptr<Ipp8u>(), maskstep,
600                     dst.ptr<Ipp32f>(), dststep, ippiSize(size.width, size.height), (Ipp32f)alpha);
601 
602             if (status >= 0)
603                 return true;
604         }
605     }
606     return false;
607 }
608 }
609 #endif
610 
accumulateWeighted(InputArray _src,InputOutputArray _dst,double alpha,InputArray _mask)611 void cv::accumulateWeighted( InputArray _src, InputOutputArray _dst,
612                              double alpha, InputArray _mask )
613 {
614     CV_INSTRUMENT_REGION();
615 
616     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
617     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
618 
619     CV_Assert( _src.sameSize(_dst) && dcn == scn );
620     CV_Assert( _mask.empty() || (_src.sameSize(_mask) && _mask.type() == CV_8U) );
621 
622     CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
623                ocl_accumulate(_src, noArray(), _dst, alpha, _mask, ACCUMULATE_WEIGHTED))
624 
625     CV_IPP_RUN((_src.dims() <= 2 || (_src.isContinuous() && _dst.isContinuous() && _mask.isContinuous())), ipp_accumulate_weighted(_src, _dst, alpha, _mask));
626 
627     CV_OVX_RUN(_src.dims() <= 2,
628                openvx_accumulate(_src, _dst, _mask, alpha, VX_ACCUMULATE_WEIGHTED_OP))
629 
630     Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat();
631 
632 
633     int fidx = getAccTabIdx(sdepth, ddepth);
634     AccWFunc func = fidx >= 0 ? accWTab[fidx] : 0;
635     CV_Assert( func != 0 );
636 
637     const Mat* arrays[] = {&src, &dst, &mask, 0};
638     uchar* ptrs[3] = {};
639     NAryMatIterator it(arrays, ptrs);
640     int len = (int)it.size;
641 
642     for( size_t i = 0; i < it.nplanes; i++, ++it )
643         func(ptrs[0], ptrs[1], ptrs[2], len, scn, alpha);
644 }
645 
646 
647 CV_IMPL void
cvAcc(const void * arr,void * sumarr,const void * maskarr)648 cvAcc( const void* arr, void* sumarr, const void* maskarr )
649 {
650     cv::Mat src = cv::cvarrToMat(arr), dst = cv::cvarrToMat(sumarr), mask;
651     if( maskarr )
652         mask = cv::cvarrToMat(maskarr);
653     cv::accumulate( src, dst, mask );
654 }
655 
656 CV_IMPL void
cvSquareAcc(const void * arr,void * sumarr,const void * maskarr)657 cvSquareAcc( const void* arr, void* sumarr, const void* maskarr )
658 {
659     cv::Mat src = cv::cvarrToMat(arr), dst = cv::cvarrToMat(sumarr), mask;
660     if( maskarr )
661         mask = cv::cvarrToMat(maskarr);
662     cv::accumulateSquare( src, dst, mask );
663 }
664 
665 CV_IMPL void
cvMultiplyAcc(const void * arr1,const void * arr2,void * sumarr,const void * maskarr)666 cvMultiplyAcc( const void* arr1, const void* arr2,
667                void* sumarr, const void* maskarr )
668 {
669     cv::Mat src1 = cv::cvarrToMat(arr1), src2 = cv::cvarrToMat(arr2);
670     cv::Mat dst = cv::cvarrToMat(sumarr), mask;
671     if( maskarr )
672         mask = cv::cvarrToMat(maskarr);
673     cv::accumulateProduct( src1, src2, dst, mask );
674 }
675 
676 CV_IMPL void
cvRunningAvg(const void * arr,void * sumarr,double alpha,const void * maskarr)677 cvRunningAvg( const void* arr, void* sumarr, double alpha, const void* maskarr )
678 {
679     cv::Mat src = cv::cvarrToMat(arr), dst = cv::cvarrToMat(sumarr), mask;
680     if( maskarr )
681         mask = cv::cvarrToMat(maskarr);
682     cv::accumulateWeighted( src, dst, alpha, mask );
683 }
684 
685 /* End of file. */
686