1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
43 #include "precomp.hpp"
47 #include "opencl_kernels.hpp"
52 template<typename T> static inline Scalar rawToScalar(const T& v)
55 typedef typename DataType<T>::channel_type T1;
56 int i, n = DataType<T>::channels;
57 for( i = 0; i < n; i++ )
58 s.val[i] = ((T1*)&v)[i];
62 /****************************************************************************************\
64 \****************************************************************************************/
66 template<typename T, typename ST>
67 static int sum_(const T* src0, const uchar* mask, ST* dst, int len, int cn )
78 #if CV_ENABLE_UNROLLED
79 for(; i <= len - 4; i += 4, src += cn*4 )
80 s0 += src[0] + src[cn] + src[cn*2] + src[cn*3];
82 for( ; i < len; i++, src += cn )
88 ST s0 = dst[0], s1 = dst[1];
89 for( i = 0; i < len; i++, src += cn )
99 ST s0 = dst[0], s1 = dst[1], s2 = dst[2];
100 for( i = 0; i < len; i++, src += cn )
111 for( ; k < cn; k += 4 )
114 ST s0 = dst[k], s1 = dst[k+1], s2 = dst[k+2], s3 = dst[k+3];
115 for( i = 0; i < len; i++, src += cn )
117 s0 += src[0]; s1 += src[1];
118 s2 += src[2]; s3 += src[3];
132 for( i = 0; i < len; i++ )
142 ST s0 = dst[0], s1 = dst[1], s2 = dst[2];
143 for( i = 0; i < len; i++, src += 3 )
157 for( i = 0; i < len; i++, src += cn )
161 #if CV_ENABLE_UNROLLED
162 for( ; k <= cn - 4; k += 4 )
165 s0 = dst[k] + src[k];
166 s1 = dst[k+1] + src[k+1];
167 dst[k] = s0; dst[k+1] = s1;
168 s0 = dst[k+2] + src[k+2];
169 s1 = dst[k+3] + src[k+3];
170 dst[k+2] = s0; dst[k+3] = s1;
182 static int sum8u( const uchar* src, const uchar* mask, int* dst, int len, int cn )
183 { return sum_(src, mask, dst, len, cn); }
185 static int sum8s( const schar* src, const uchar* mask, int* dst, int len, int cn )
186 { return sum_(src, mask, dst, len, cn); }
188 static int sum16u( const ushort* src, const uchar* mask, int* dst, int len, int cn )
189 { return sum_(src, mask, dst, len, cn); }
191 static int sum16s( const short* src, const uchar* mask, int* dst, int len, int cn )
192 { return sum_(src, mask, dst, len, cn); }
194 static int sum32s( const int* src, const uchar* mask, double* dst, int len, int cn )
195 { return sum_(src, mask, dst, len, cn); }
197 static int sum32f( const float* src, const uchar* mask, double* dst, int len, int cn )
198 { return sum_(src, mask, dst, len, cn); }
200 static int sum64f( const double* src, const uchar* mask, double* dst, int len, int cn )
201 { return sum_(src, mask, dst, len, cn); }
203 typedef int (*SumFunc)(const uchar*, const uchar* mask, uchar*, int, int);
205 static SumFunc getSumFunc(int depth)
207 static SumFunc sumTab[] =
209 (SumFunc)GET_OPTIMIZED(sum8u), (SumFunc)sum8s,
210 (SumFunc)sum16u, (SumFunc)sum16s,
212 (SumFunc)GET_OPTIMIZED(sum32f), (SumFunc)sum64f,
216 return sumTab[depth];
220 static int countNonZero_(const T* src, int len )
223 #if CV_ENABLE_UNROLLED
224 for(; i <= len - 4; i += 4 )
225 nz += (src[i] != 0) + (src[i+1] != 0) + (src[i+2] != 0) + (src[i+3] != 0);
227 for( ; i < len; i++ )
232 static int countNonZero8u( const uchar* src, int len )
238 __m128i pattern = _mm_setzero_si128 ();
239 static uchar tab[256];
240 static volatile bool initialized = false;
243 // we compute inverse popcount table,
244 // since we pass (img[x] == 0) mask as index in the table.
245 for( int j = 0; j < 256; j++ )
248 for( int mask = 1; mask < 256; mask += mask )
249 val += (j & mask) == 0;
255 for (; i<=len-16; i+=16)
257 __m128i r0 = _mm_loadu_si128((const __m128i*)(src+i));
258 int val = _mm_movemask_epi8(_mm_cmpeq_epi8(r0, pattern));
259 nz += tab[val & 255] + tab[val >> 8];
263 for( ; i < len; i++ )
268 static int countNonZero16u( const ushort* src, int len )
269 { return countNonZero_(src, len); }
271 static int countNonZero32s( const int* src, int len )
272 { return countNonZero_(src, len); }
274 static int countNonZero32f( const float* src, int len )
275 { return countNonZero_(src, len); }
277 static int countNonZero64f( const double* src, int len )
278 { return countNonZero_(src, len); }
280 typedef int (*CountNonZeroFunc)(const uchar*, int);
282 static CountNonZeroFunc getCountNonZeroTab(int depth)
284 static CountNonZeroFunc countNonZeroTab[] =
286 (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero8u),
287 (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero16u),
288 (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32s), (CountNonZeroFunc)GET_OPTIMIZED(countNonZero32f),
289 (CountNonZeroFunc)GET_OPTIMIZED(countNonZero64f), 0
292 return countNonZeroTab[depth];
295 template<typename T, typename ST, typename SQT>
296 static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn )
309 for( i = 0; i < len; i++, src += cn )
312 s0 += v; sq0 += (SQT)v*v;
319 ST s0 = sum[0], s1 = sum[1];
320 SQT sq0 = sqsum[0], sq1 = sqsum[1];
321 for( i = 0; i < len; i++, src += cn )
323 T v0 = src[0], v1 = src[1];
324 s0 += v0; sq0 += (SQT)v0*v0;
325 s1 += v1; sq1 += (SQT)v1*v1;
327 sum[0] = s0; sum[1] = s1;
328 sqsum[0] = sq0; sqsum[1] = sq1;
332 ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
333 SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
334 for( i = 0; i < len; i++, src += cn )
336 T v0 = src[0], v1 = src[1], v2 = src[2];
337 s0 += v0; sq0 += (SQT)v0*v0;
338 s1 += v1; sq1 += (SQT)v1*v1;
339 s2 += v2; sq2 += (SQT)v2*v2;
341 sum[0] = s0; sum[1] = s1; sum[2] = s2;
342 sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
345 for( ; k < cn; k += 4 )
348 ST s0 = sum[k], s1 = sum[k+1], s2 = sum[k+2], s3 = sum[k+3];
349 SQT sq0 = sqsum[k], sq1 = sqsum[k+1], sq2 = sqsum[k+2], sq3 = sqsum[k+3];
350 for( i = 0; i < len; i++, src += cn )
353 v0 = src[0], v1 = src[1];
354 s0 += v0; sq0 += (SQT)v0*v0;
355 s1 += v1; sq1 += (SQT)v1*v1;
356 v0 = src[2], v1 = src[3];
357 s2 += v0; sq2 += (SQT)v0*v0;
358 s3 += v1; sq3 += (SQT)v1*v1;
360 sum[k] = s0; sum[k+1] = s1;
361 sum[k+2] = s2; sum[k+3] = s3;
362 sqsum[k] = sq0; sqsum[k+1] = sq1;
363 sqsum[k+2] = sq2; sqsum[k+3] = sq3;
374 for( i = 0; i < len; i++ )
378 s0 += v; sq0 += (SQT)v*v;
386 ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
387 SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
388 for( i = 0; i < len; i++, src += 3 )
391 T v0 = src[0], v1 = src[1], v2 = src[2];
392 s0 += v0; sq0 += (SQT)v0*v0;
393 s1 += v1; sq1 += (SQT)v1*v1;
394 s2 += v2; sq2 += (SQT)v2*v2;
397 sum[0] = s0; sum[1] = s1; sum[2] = s2;
398 sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
402 for( i = 0; i < len; i++, src += cn )
405 for( int k = 0; k < cn; k++ )
409 SQT sq = sqsum[k] + (SQT)v*v;
410 sum[k] = s; sqsum[k] = sq;
419 static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
420 { return sumsqr_(src, mask, sum, sqsum, len, cn); }
422 static int sqsum8s( const schar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
423 { return sumsqr_(src, mask, sum, sqsum, len, cn); }
425 static int sqsum16u( const ushort* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
426 { return sumsqr_(src, mask, sum, sqsum, len, cn); }
428 static int sqsum16s( const short* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
429 { return sumsqr_(src, mask, sum, sqsum, len, cn); }
431 static int sqsum32s( const int* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
432 { return sumsqr_(src, mask, sum, sqsum, len, cn); }
434 static int sqsum32f( const float* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
435 { return sumsqr_(src, mask, sum, sqsum, len, cn); }
437 static int sqsum64f( const double* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
438 { return sumsqr_(src, mask, sum, sqsum, len, cn); }
440 typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int);
442 static SumSqrFunc getSumSqrTab(int depth)
444 static SumSqrFunc sumSqrTab[] =
446 (SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s,
447 (SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0
450 return sumSqrTab[depth];
455 template <typename T> Scalar ocl_part_sum(Mat m)
457 CV_Assert(m.rows == 1);
459 Scalar s = Scalar::all(0);
460 int cn = m.channels();
461 const T * const ptr = m.ptr<T>(0);
463 for (int x = 0, w = m.cols * cn; x < w; )
464 for (int c = 0; c < cn; ++c, ++x)
470 enum { OCL_OP_SUM = 0, OCL_OP_SUM_ABS = 1, OCL_OP_SUM_SQR = 2 };
472 static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask = noArray(),
473 InputArray _src2 = noArray(), bool calc2 = false, const Scalar & res2 = Scalar() )
475 CV_Assert(sum_op == OCL_OP_SUM || sum_op == OCL_OP_SUM_ABS || sum_op == OCL_OP_SUM_SQR);
477 const ocl::Device & dev = ocl::Device::getDefault();
478 bool doubleSupport = dev.doubleFPConfig() > 0,
479 haveMask = _mask.kind() != _InputArray::NONE,
480 haveSrc2 = _src2.kind() != _InputArray::NONE;
481 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
482 kercn = cn == 1 && !haveMask ? ocl::predictOptimalVectorWidth(_src) : 1,
483 mcn = std::max(cn, kercn);
484 CV_Assert(!haveSrc2 || _src2.type() == type);
486 if ( (!doubleSupport && depth == CV_64F) || cn > 4 )
489 int ngroups = dev.maxComputeUnits(), dbsize = ngroups * (calc2 ? 2 : 1);
490 size_t wgs = dev.maxWorkGroupSize();
492 int ddepth = std::max(sum_op == OCL_OP_SUM_SQR ? CV_32F : CV_32S, depth),
493 dtype = CV_MAKE_TYPE(ddepth, cn);
494 CV_Assert(!haveMask || _mask.type() == CV_8UC1);
496 int wgs2_aligned = 1;
497 while (wgs2_aligned < (int)wgs)
501 static const char * const opMap[3] = { "OP_SUM", "OP_SUM_ABS", "OP_SUM_SQR" };
503 String opts = format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstTK=%s -D dstT1=%s -D ddepth=%d -D cn=%d"
504 " -D convertToDT=%s -D %s -D WGS=%d -D WGS2_ALIGNED=%d%s%s%s%s -D kercn=%d%s%s%s",
505 ocl::typeToStr(CV_MAKE_TYPE(depth, mcn)), ocl::typeToStr(depth),
506 ocl::typeToStr(dtype), ocl::typeToStr(CV_MAKE_TYPE(ddepth, mcn)),
507 ocl::typeToStr(ddepth), ddepth, cn,
508 ocl::convertTypeStr(depth, ddepth, mcn, cvt),
509 opMap[sum_op], (int)wgs, wgs2_aligned,
510 doubleSupport ? " -D DOUBLE_SUPPORT" : "",
511 haveMask ? " -D HAVE_MASK" : "",
512 _src.isContinuous() ? " -D HAVE_SRC_CONT" : "",
513 haveMask && _mask.isContinuous() ? " -D HAVE_MASK_CONT" : "", kercn,
514 haveSrc2 ? " -D HAVE_SRC2" : "", calc2 ? " -D OP_CALC2" : "",
515 haveSrc2 && _src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "");
517 ocl::Kernel k("reduce", ocl::core::reduce_oclsrc, opts);
521 UMat src = _src.getUMat(), src2 = _src2.getUMat(),
522 db(1, dbsize, dtype), mask = _mask.getUMat();
524 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
525 dbarg = ocl::KernelArg::PtrWriteOnly(db),
526 maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
527 src2arg = ocl::KernelArg::ReadOnlyNoSize(src2);
532 k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg, src2arg);
534 k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, maskarg);
539 k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg, src2arg);
541 k.args(srcarg, src.cols, (int)src.total(), ngroups, dbarg);
544 size_t globalsize = ngroups * wgs;
545 if (k.run(1, &globalsize, &wgs, false))
547 typedef Scalar (*part_sum)(Mat m);
548 part_sum funcs[3] = { ocl_part_sum<int>, ocl_part_sum<float>, ocl_part_sum<double> },
549 func = funcs[ddepth - CV_32S];
551 Mat mres = db.getMat(ACCESS_READ);
553 const_cast<Scalar &>(res2) = func(mres.colRange(ngroups, dbsize));
555 res = func(mres.colRange(0, ngroups));
565 cv::Scalar cv::sum( InputArray _src )
569 CV_OCL_RUN_(_src.isUMat() && _src.dims() <= 2,
570 ocl_sum(_src, _res, OCL_OP_SUM),
574 Mat src = _src.getMat();
575 int k, cn = src.channels(), depth = src.depth();
577 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
578 size_t total_size = src.total();
579 int rows = src.size[0], cols = (int)(total_size/rows);
580 if( src.dims == 2 || (src.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
582 IppiSize sz = { cols, rows };
583 int type = src.type();
584 typedef IppStatus (CV_STDCALL* ippiSumFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm);
585 typedef IppStatus (CV_STDCALL* ippiSumFuncNoHint)(const void*, int, IppiSize, double *);
586 ippiSumFuncHint ippFuncHint =
587 type == CV_32FC1 ? (ippiSumFuncHint)ippiSum_32f_C1R :
588 type == CV_32FC3 ? (ippiSumFuncHint)ippiSum_32f_C3R :
589 type == CV_32FC4 ? (ippiSumFuncHint)ippiSum_32f_C4R :
591 ippiSumFuncNoHint ippFuncNoHint =
592 type == CV_8UC1 ? (ippiSumFuncNoHint)ippiSum_8u_C1R :
593 type == CV_8UC3 ? (ippiSumFuncNoHint)ippiSum_8u_C3R :
594 type == CV_8UC4 ? (ippiSumFuncNoHint)ippiSum_8u_C4R :
595 type == CV_16UC1 ? (ippiSumFuncNoHint)ippiSum_16u_C1R :
596 type == CV_16UC3 ? (ippiSumFuncNoHint)ippiSum_16u_C3R :
597 type == CV_16UC4 ? (ippiSumFuncNoHint)ippiSum_16u_C4R :
598 type == CV_16SC1 ? (ippiSumFuncNoHint)ippiSum_16s_C1R :
599 type == CV_16SC3 ? (ippiSumFuncNoHint)ippiSum_16s_C3R :
600 type == CV_16SC4 ? (ippiSumFuncNoHint)ippiSum_16s_C4R :
602 CV_Assert(!ippFuncHint || !ippFuncNoHint);
603 if( ippFuncHint || ippFuncNoHint )
606 IppStatus ret = ippFuncHint ? ippFuncHint(src.data, (int)src.step[0], sz, res, ippAlgHintAccurate) :
607 ippFuncNoHint(src.data, (int)src.step[0], sz, res);
611 for( int i = 0; i < cn; i++ )
620 SumFunc func = getSumFunc(depth);
622 CV_Assert( cn <= 4 && func != 0 );
624 const Mat* arrays[] = {&src, 0};
626 NAryMatIterator it(arrays, ptrs);
628 int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
630 AutoBuffer<int> _buf;
631 int* buf = (int*)&s[0];
633 bool blockSum = depth < CV_32S;
637 intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15);
638 blockSize = std::min(blockSize, intSumBlockSize);
642 for( k = 0; k < cn; k++ )
644 esz = src.elemSize();
647 for( size_t i = 0; i < it.nplanes; i++, ++it )
649 for( j = 0; j < total; j += blockSize )
651 int bsz = std::min(total - j, blockSize);
652 func( ptrs[0], 0, (uchar*)buf, bsz, cn );
654 if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
656 for( k = 0; k < cn; k++ )
673 static bool ocl_countNonZero( InputArray _src, int & res )
675 int type = _src.type(), depth = CV_MAT_DEPTH(type), kercn = ocl::predictOptimalVectorWidth(_src);
676 bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
678 if (depth == CV_64F && !doubleSupport)
681 int dbsize = ocl::Device::getDefault().maxComputeUnits();
682 size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
684 int wgs2_aligned = 1;
685 while (wgs2_aligned < (int)wgs)
689 ocl::Kernel k("reduce", ocl::core::reduce_oclsrc,
690 format("-D srcT=%s -D srcT1=%s -D cn=1 -D OP_COUNT_NON_ZERO"
691 " -D WGS=%d -D kercn=%d -D WGS2_ALIGNED=%d%s%s",
692 ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)),
693 ocl::typeToStr(depth), (int)wgs, kercn,
694 wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
695 _src.isContinuous() ? " -D HAVE_SRC_CONT" : ""));
699 UMat src = _src.getUMat(), db(1, dbsize, CV_32SC1);
700 k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
701 dbsize, ocl::KernelArg::PtrWriteOnly(db));
703 size_t globalsize = dbsize * wgs;
704 if (k.run(1, &globalsize, &wgs, true))
705 return res = saturate_cast<int>(cv::sum(db.getMat(ACCESS_READ))[0]), true;
713 int cv::countNonZero( InputArray _src )
715 int type = _src.type(), cn = CV_MAT_CN(type);
716 CV_Assert( cn == 1 );
720 CV_OCL_RUN_(_src.isUMat() && _src.dims() <= 2,
721 ocl_countNonZero(_src, res),
725 Mat src = _src.getMat();
727 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && 0
728 if (src.dims <= 2 || src.isContinuous())
730 IppiSize roiSize = { src.cols, src.rows };
731 Ipp32s count = 0, srcstep = (Ipp32s)src.step;
732 IppStatus status = (IppStatus)-1;
734 if (src.isContinuous())
736 roiSize.width = (Ipp32s)src.total();
738 srcstep = (Ipp32s)src.total() * CV_ELEM_SIZE(type);
741 int depth = CV_MAT_DEPTH(type);
743 status = ippiCountInRange_8u_C1R((const Ipp8u *)src.data, srcstep, roiSize, &count, 0, 0);
744 else if (depth == CV_32F)
745 status = ippiCountInRange_32f_C1R((const Ipp32f *)src.data, srcstep, roiSize, &count, 0, 0);
748 return (Ipp32s)src.total() - count;
753 CountNonZeroFunc func = getCountNonZeroTab(src.depth());
754 CV_Assert( func != 0 );
756 const Mat* arrays[] = {&src, 0};
758 NAryMatIterator it(arrays, ptrs);
759 int total = (int)it.size, nz = 0;
761 for( size_t i = 0; i < it.nplanes; i++, ++it )
762 nz += func( ptrs[0], total );
767 cv::Scalar cv::mean( InputArray _src, InputArray _mask )
769 Mat src = _src.getMat(), mask = _mask.getMat();
770 CV_Assert( mask.empty() || mask.type() == CV_8U );
772 int k, cn = src.channels(), depth = src.depth();
774 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
775 size_t total_size = src.total();
776 int rows = src.size[0], cols = (int)(total_size/rows);
777 if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
779 IppiSize sz = { cols, rows };
780 int type = src.type();
783 typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC1)(const void *, int, void *, int, IppiSize, Ipp64f *);
784 ippiMaskMeanFuncC1 ippFuncC1 =
785 type == CV_8UC1 ? (ippiMaskMeanFuncC1)ippiMean_8u_C1MR :
786 type == CV_16UC1 ? (ippiMaskMeanFuncC1)ippiMean_16u_C1MR :
787 type == CV_32FC1 ? (ippiMaskMeanFuncC1)ippiMean_32f_C1MR :
792 if( ippFuncC1(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, &res) >= 0 )
796 typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, void *, int, IppiSize, int, Ipp64f *);
797 ippiMaskMeanFuncC3 ippFuncC3 =
798 type == CV_8UC3 ? (ippiMaskMeanFuncC3)ippiMean_8u_C3CMR :
799 type == CV_16UC3 ? (ippiMaskMeanFuncC3)ippiMean_16u_C3CMR :
800 type == CV_32FC3 ? (ippiMaskMeanFuncC3)ippiMean_32f_C3CMR :
804 Ipp64f res1, res2, res3;
805 if( ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &res1) >= 0 &&
806 ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &res2) >= 0 &&
807 ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &res3) >= 0 )
809 return Scalar(res1, res2, res3);
816 typedef IppStatus (CV_STDCALL* ippiMeanFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm);
817 typedef IppStatus (CV_STDCALL* ippiMeanFuncNoHint)(const void*, int, IppiSize, double *);
818 ippiMeanFuncHint ippFuncHint =
819 type == CV_32FC1 ? (ippiMeanFuncHint)ippiMean_32f_C1R :
820 type == CV_32FC3 ? (ippiMeanFuncHint)ippiMean_32f_C3R :
821 type == CV_32FC4 ? (ippiMeanFuncHint)ippiMean_32f_C4R :
823 ippiMeanFuncNoHint ippFuncNoHint =
824 type == CV_8UC1 ? (ippiMeanFuncNoHint)ippiMean_8u_C1R :
825 type == CV_8UC3 ? (ippiMeanFuncNoHint)ippiMean_8u_C3R :
826 type == CV_8UC4 ? (ippiMeanFuncNoHint)ippiMean_8u_C4R :
827 type == CV_16UC1 ? (ippiMeanFuncNoHint)ippiMean_16u_C1R :
828 type == CV_16UC3 ? (ippiMeanFuncNoHint)ippiMean_16u_C3R :
829 type == CV_16UC4 ? (ippiMeanFuncNoHint)ippiMean_16u_C4R :
830 type == CV_16SC1 ? (ippiMeanFuncNoHint)ippiMean_16s_C1R :
831 type == CV_16SC3 ? (ippiMeanFuncNoHint)ippiMean_16s_C3R :
832 type == CV_16SC4 ? (ippiMeanFuncNoHint)ippiMean_16s_C4R :
834 // Make sure only zero or one version of the function pointer is valid
835 CV_Assert(!ippFuncHint || !ippFuncNoHint);
836 if( ippFuncHint || ippFuncNoHint )
839 IppStatus ret = ippFuncHint ? ippFuncHint(src.data, (int)src.step[0], sz, res, ippAlgHintAccurate) :
840 ippFuncNoHint(src.data, (int)src.step[0], sz, res);
844 for( int i = 0; i < cn; i++ )
854 SumFunc func = getSumFunc(depth);
856 CV_Assert( cn <= 4 && func != 0 );
858 const Mat* arrays[] = {&src, &mask, 0};
860 NAryMatIterator it(arrays, ptrs);
862 int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
864 AutoBuffer<int> _buf;
865 int* buf = (int*)&s[0];
866 bool blockSum = depth <= CV_16S;
867 size_t esz = 0, nz0 = 0;
871 intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15);
872 blockSize = std::min(blockSize, intSumBlockSize);
876 for( k = 0; k < cn; k++ )
878 esz = src.elemSize();
881 for( size_t i = 0; i < it.nplanes; i++, ++it )
883 for( j = 0; j < total; j += blockSize )
885 int bsz = std::min(total - j, blockSize);
886 int nz = func( ptrs[0], ptrs[1], (uchar*)buf, bsz, cn );
889 if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
891 for( k = 0; k < cn; k++ )
903 return s*(nz0 ? 1./nz0 : 0);
910 static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask )
912 bool haveMask = _mask.kind() != _InputArray::NONE;
913 int nz = haveMask ? -1 : (int)_src.total();
917 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
918 bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0,
919 isContinuous = _src.isContinuous();
920 int groups = ocl::Device::getDefault().maxComputeUnits();
921 size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
923 int ddepth = std::max(CV_32S, depth), sqddepth = std::max(CV_32F, depth),
924 dtype = CV_MAKE_TYPE(ddepth, cn),
925 sqdtype = CV_MAKETYPE(sqddepth, cn);
926 CV_Assert(!haveMask || _mask.type() == CV_8UC1);
928 int wgs2_aligned = 1;
929 while (wgs2_aligned < (int)wgs)
933 if ( (!doubleSupport && depth == CV_64F) || cn > 4 )
937 String opts = format("-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D sqddepth=%d"
938 " -D sqdstT=%s -D sqdstT1=%s -D convertToSDT=%s -D cn=%d%s"
939 " -D convertToDT=%s -D WGS=%d -D WGS2_ALIGNED=%d%s%s",
940 ocl::typeToStr(type), ocl::typeToStr(depth),
941 ocl::typeToStr(dtype), ocl::typeToStr(ddepth), sqddepth,
942 ocl::typeToStr(sqdtype), ocl::typeToStr(sqddepth),
943 ocl::convertTypeStr(depth, sqddepth, cn, cvt[0]),
944 cn, isContinuous ? " -D HAVE_SRC_CONT" : "",
945 ocl::convertTypeStr(depth, ddepth, cn, cvt[1]),
946 (int)wgs, wgs2_aligned, haveMask ? " -D HAVE_MASK" : "",
947 doubleSupport ? " -D DOUBLE_SUPPORT" : "");
949 ocl::Kernel k("meanStdDev", ocl::core::meanstddev_oclsrc, opts);
953 int dbsize = groups * ((haveMask ? CV_ELEM_SIZE1(CV_32S) : 0) +
954 CV_ELEM_SIZE(sqdtype) + CV_ELEM_SIZE(dtype));
955 UMat src = _src.getUMat(), db(1, dbsize, CV_8UC1), mask = _mask.getUMat();
957 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
958 dbarg = ocl::KernelArg::PtrWriteOnly(db),
959 maskarg = ocl::KernelArg::ReadOnlyNoSize(mask);
962 k.args(srcarg, src.cols, (int)src.total(), groups, dbarg, maskarg);
964 k.args(srcarg, src.cols, (int)src.total(), groups, dbarg);
966 size_t globalsize = groups * wgs;
967 if (!k.run(1, &globalsize, &wgs, false))
970 typedef Scalar (* part_sum)(Mat m);
971 part_sum funcs[3] = { ocl_part_sum<int>, ocl_part_sum<float>, ocl_part_sum<double> };
972 Mat dbm = db.getMat(ACCESS_READ);
974 mean = funcs[ddepth - CV_32S](Mat(1, groups, dtype, dbm.data));
975 stddev = funcs[sqddepth - CV_32S](Mat(1, groups, sqdtype, dbm.data + groups * CV_ELEM_SIZE(dtype)));
978 nz = saturate_cast<int>(funcs[0](Mat(1, groups, CV_32SC1, dbm.data +
979 groups * (CV_ELEM_SIZE(dtype) +
980 CV_ELEM_SIZE(sqdtype))))[0]);
983 double total = nz != 0 ? 1.0 / nz : 0;
984 int k, j, cn = _src.channels();
985 for (int i = 0; i < cn; ++i)
988 stddev[i] = std::sqrt(std::max(stddev[i] * total - mean[i] * mean[i] , 0.));
991 for( j = 0; j < 2; j++ )
993 const double * const sptr = j == 0 ? &mean[0] : &stddev[0];
994 _OutputArray _dst = j == 0 ? _mean : _sdv;
998 if( !_dst.fixedSize() )
999 _dst.create(cn, 1, CV_64F, -1, true);
1000 Mat dst = _dst.getMat();
1001 int dcn = (int)dst.total();
1002 CV_Assert( dst.type() == CV_64F && dst.isContinuous() &&
1003 (dst.cols == 1 || dst.rows == 1) && dcn >= cn );
1004 double* dptr = dst.ptr<double>();
1005 for( k = 0; k < cn; k++ )
1007 for( ; k < dcn; k++ )
1018 void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask )
1020 CV_OCL_RUN(_src.isUMat() && _src.dims() <= 2,
1021 ocl_meanStdDev(_src, _mean, _sdv, _mask))
1023 Mat src = _src.getMat(), mask = _mask.getMat();
1024 CV_Assert( mask.empty() || mask.type() == CV_8UC1 );
1026 int k, cn = src.channels(), depth = src.depth();
1028 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
1029 size_t total_size = src.total();
1030 int rows = src.size[0], cols = (int)(total_size/rows);
1031 if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
1033 Ipp64f mean_temp[3];
1034 Ipp64f stddev_temp[3];
1035 Ipp64f *pmean = &mean_temp[0];
1036 Ipp64f *pstddev = &stddev_temp[0];
1039 if( _mean.needed() )
1041 if( !_mean.fixedSize() )
1042 _mean.create(cn, 1, CV_64F, -1, true);
1043 mean = _mean.getMat();
1044 dcn_mean = (int)mean.total();
1045 pmean = (Ipp64f *)mean.data;
1047 int dcn_stddev = -1;
1050 if( !_sdv.fixedSize() )
1051 _sdv.create(cn, 1, CV_64F, -1, true);
1052 stddev = _sdv.getMat();
1053 dcn_stddev = (int)stddev.total();
1054 pstddev = (Ipp64f *)stddev.data;
1056 for( int c = cn; c < dcn_mean; c++ )
1058 for( int c = cn; c < dcn_stddev; c++ )
1060 IppiSize sz = { cols, rows };
1061 int type = src.type();
1064 typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC1)(const void *, int, void *, int, IppiSize, Ipp64f *, Ipp64f *);
1065 ippiMaskMeanStdDevFuncC1 ippFuncC1 =
1066 type == CV_8UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_8u_C1MR :
1067 type == CV_16UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_16u_C1MR :
1068 type == CV_32FC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_32f_C1MR :
1072 if( ippFuncC1(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, pmean, pstddev) >= 0 )
1074 setIppErrorStatus();
1076 typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC3)(const void *, int, void *, int, IppiSize, int, Ipp64f *, Ipp64f *);
1077 ippiMaskMeanStdDevFuncC3 ippFuncC3 =
1078 type == CV_8UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CMR :
1079 type == CV_16UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CMR :
1080 type == CV_32FC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CMR :
1084 if( ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 &&
1085 ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 &&
1086 ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 )
1088 setIppErrorStatus();
1093 typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC1)(const void *, int, IppiSize, Ipp64f *, Ipp64f *);
1094 ippiMeanStdDevFuncC1 ippFuncC1 =
1095 type == CV_8UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_8u_C1R :
1096 type == CV_16UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_16u_C1R :
1097 #if (IPP_VERSION_X100 >= 801)
1098 type == CV_32FC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_32f_C1R ://Aug 2013: bug in IPP 7.1, 8.0
1103 if( ippFuncC1(src.data, (int)src.step[0], sz, pmean, pstddev) >= 0 )
1105 setIppErrorStatus();
1107 typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC3)(const void *, int, IppiSize, int, Ipp64f *, Ipp64f *);
1108 ippiMeanStdDevFuncC3 ippFuncC3 =
1109 type == CV_8UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CR :
1110 type == CV_16UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CR :
1111 type == CV_32FC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CR :
1115 if( ippFuncC3(src.data, (int)src.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 &&
1116 ippFuncC3(src.data, (int)src.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 &&
1117 ippFuncC3(src.data, (int)src.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 )
1119 setIppErrorStatus();
1126 SumSqrFunc func = getSumSqrTab(depth);
1128 CV_Assert( func != 0 );
1130 const Mat* arrays[] = {&src, &mask, 0};
1132 NAryMatIterator it(arrays, ptrs);
1133 int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
1134 int j, count = 0, nz0 = 0;
1135 AutoBuffer<double> _buf(cn*4);
1136 double *s = (double*)_buf, *sq = s + cn;
1137 int *sbuf = (int*)s, *sqbuf = (int*)sq;
1138 bool blockSum = depth <= CV_16S, blockSqSum = depth <= CV_8S;
1141 for( k = 0; k < cn; k++ )
1146 intSumBlockSize = 1 << 15;
1147 blockSize = std::min(blockSize, intSumBlockSize);
1148 sbuf = (int*)(sq + cn);
1151 for( k = 0; k < cn; k++ )
1152 sbuf[k] = sqbuf[k] = 0;
1153 esz = src.elemSize();
1156 for( size_t i = 0; i < it.nplanes; i++, ++it )
1158 for( j = 0; j < total; j += blockSize )
1160 int bsz = std::min(total - j, blockSize);
1161 int nz = func( ptrs[0], ptrs[1], (uchar*)sbuf, (uchar*)sqbuf, bsz, cn );
1164 if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
1166 for( k = 0; k < cn; k++ )
1173 for( k = 0; k < cn; k++ )
1187 double scale = nz0 ? 1./nz0 : 0.;
1188 for( k = 0; k < cn; k++ )
1191 sq[k] = std::sqrt(std::max(sq[k]*scale - s[k]*s[k], 0.));
1194 for( j = 0; j < 2; j++ )
1196 const double* sptr = j == 0 ? s : sq;
1197 _OutputArray _dst = j == 0 ? _mean : _sdv;
1198 if( !_dst.needed() )
1201 if( !_dst.fixedSize() )
1202 _dst.create(cn, 1, CV_64F, -1, true);
1203 Mat dst = _dst.getMat();
1204 int dcn = (int)dst.total();
1205 CV_Assert( dst.type() == CV_64F && dst.isContinuous() &&
1206 (dst.cols == 1 || dst.rows == 1) && dcn >= cn );
1207 double* dptr = dst.ptr<double>();
1208 for( k = 0; k < cn; k++ )
1210 for( ; k < dcn; k++ )
1215 /****************************************************************************************\
1217 \****************************************************************************************/
1222 template<typename T, typename WT> static void
1223 minMaxIdx_( const T* src, const uchar* mask, WT* _minVal, WT* _maxVal,
1224 size_t* _minIdx, size_t* _maxIdx, int len, size_t startIdx )
1226 WT minVal = *_minVal, maxVal = *_maxVal;
1227 size_t minIdx = *_minIdx, maxIdx = *_maxIdx;
1231 for( int i = 0; i < len; i++ )
1237 minIdx = startIdx + i;
1242 maxIdx = startIdx + i;
1248 for( int i = 0; i < len; i++ )
1251 if( mask[i] && val < minVal )
1254 minIdx = startIdx + i;
1256 if( mask[i] && val > maxVal )
1259 maxIdx = startIdx + i;
1270 static void minMaxIdx_8u(const uchar* src, const uchar* mask, int* minval, int* maxval,
1271 size_t* minidx, size_t* maxidx, int len, size_t startidx )
1272 { minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
1274 static void minMaxIdx_8s(const schar* src, const uchar* mask, int* minval, int* maxval,
1275 size_t* minidx, size_t* maxidx, int len, size_t startidx )
1276 { minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
1278 static void minMaxIdx_16u(const ushort* src, const uchar* mask, int* minval, int* maxval,
1279 size_t* minidx, size_t* maxidx, int len, size_t startidx )
1280 { minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
1282 static void minMaxIdx_16s(const short* src, const uchar* mask, int* minval, int* maxval,
1283 size_t* minidx, size_t* maxidx, int len, size_t startidx )
1284 { minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
1286 static void minMaxIdx_32s(const int* src, const uchar* mask, int* minval, int* maxval,
1287 size_t* minidx, size_t* maxidx, int len, size_t startidx )
1288 { minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
1290 static void minMaxIdx_32f(const float* src, const uchar* mask, float* minval, float* maxval,
1291 size_t* minidx, size_t* maxidx, int len, size_t startidx )
1292 { minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
1294 static void minMaxIdx_64f(const double* src, const uchar* mask, double* minval, double* maxval,
1295 size_t* minidx, size_t* maxidx, int len, size_t startidx )
1296 { minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
1298 typedef void (*MinMaxIdxFunc)(const uchar*, const uchar*, int*, int*, size_t*, size_t*, int, size_t);
1300 static MinMaxIdxFunc getMinmaxTab(int depth)
1302 static MinMaxIdxFunc minmaxTab[] =
1304 (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_8s),
1305 (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16u), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_16s),
1306 (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_32s),
1307 (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_32f), (MinMaxIdxFunc)GET_OPTIMIZED(minMaxIdx_64f),
1311 return minmaxTab[depth];
1314 static void ofs2idx(const Mat& a, size_t ofs, int* idx)
1320 for( i = d-1; i >= 0; i-- )
1323 idx[i] = (int)(ofs % sz);
1329 for( i = d-1; i >= 0; i-- )
1336 template <typename T>
1337 void getMinMaxRes(const Mat & db, double * minVal, double * maxVal,
1338 int* minLoc, int* maxLoc,
1339 int groupnum, int cols, double * maxVal2)
1341 uint index_max = std::numeric_limits<uint>::max();
1342 T minval = std::numeric_limits<T>::max();
1343 T maxval = std::numeric_limits<T>::min() > 0 ? -std::numeric_limits<T>::max() : std::numeric_limits<T>::min(), maxval2 = maxval;
1344 uint minloc = index_max, maxloc = index_max;
1347 const T * minptr = NULL, * maxptr = NULL, * maxptr2 = NULL;
1348 const uint * minlocptr = NULL, * maxlocptr = NULL;
1349 if (minVal || minLoc)
1351 minptr = (const T *)db.data;
1352 index += sizeof(T) * groupnum;
1354 if (maxVal || maxLoc)
1356 maxptr = (const T *)(db.data + index);
1357 index += sizeof(T) * groupnum;
1361 minlocptr = (uint *)(db.data + index);
1362 index += sizeof(uint) * groupnum;
1366 maxlocptr = (uint *)(db.data + index);
1367 index += sizeof(uint) * groupnum;
1370 maxptr2 = (const T *)(db.data + index);
1372 for (int i = 0; i < groupnum; i++)
1374 if (minptr && minptr[i] <= minval)
1376 if (minptr[i] == minval)
1379 minloc = std::min(minlocptr[i], minloc);
1384 minloc = minlocptr[i];
1388 if (maxptr && maxptr[i] >= maxval)
1390 if (maxptr[i] == maxval)
1393 maxloc = std::min(maxlocptr[i], maxloc);
1398 maxloc = maxlocptr[i];
1402 if (maxptr2 && maxptr2[i] > maxval2)
1403 maxval2 = maxptr2[i];
1405 bool zero_mask = (minLoc && minloc == index_max) ||
1406 (maxLoc && maxloc == index_max);
1409 *minVal = zero_mask ? 0 : (double)minval;
1411 *maxVal = zero_mask ? 0 : (double)maxval;
1413 *maxVal2 = zero_mask ? 0 : (double)maxval2;
1417 minLoc[0] = zero_mask ? -1 : minloc / cols;
1418 minLoc[1] = zero_mask ? -1 : minloc % cols;
1422 maxLoc[0] = zero_mask ? -1 : maxloc / cols;
1423 maxLoc[1] = zero_mask ? -1 : maxloc % cols;
1427 typedef void (*getMinMaxResFunc)(const Mat & db, double * minVal, double * maxVal,
1428 int * minLoc, int *maxLoc, int gropunum, int cols, double * maxVal2);
1430 static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* minLoc, int* maxLoc, InputArray _mask,
1431 int ddepth = -1, bool absValues = false, InputArray _src2 = noArray(), double * maxVal2 = NULL)
1433 const ocl::Device & dev = ocl::Device::getDefault();
1434 bool doubleSupport = dev.doubleFPConfig() > 0, haveMask = !_mask.empty(),
1435 haveSrc2 = _src2.kind() != _InputArray::NONE;
1436 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
1437 kercn = haveMask ? cn : std::min(4, ocl::predictOptimalVectorWidth(_src));
1439 CV_Assert( (cn == 1 && (!haveMask || _mask.type() == CV_8U)) ||
1440 (cn >= 1 && (!haveMask || haveSrc2) && !minLoc && !maxLoc) );
1445 CV_Assert(!haveSrc2 || _src2.type() == type);
1447 if ((depth == CV_64F || ddepth == CV_64F) && !doubleSupport)
1450 int groupnum = dev.maxComputeUnits();
1451 size_t wgs = dev.maxWorkGroupSize();
1453 int wgs2_aligned = 1;
1454 while (wgs2_aligned < (int)wgs)
1458 bool needMinVal = minVal || minLoc, needMinLoc = minLoc != NULL,
1459 needMaxVal = maxVal || maxLoc, needMaxLoc = maxLoc != NULL;
1461 // in case of mask we must know whether mask is filled with zeros or not
1462 // so let's calculate min or max location, if it's undefined, so mask is zeros
1463 if (!(needMaxLoc || needMinLoc) && haveMask)
1472 String opts = format("-D DEPTH_%d -D srcT1=%s%s -D WGS=%d -D srcT=%s"
1473 " -D WGS2_ALIGNED=%d%s%s%s -D kercn=%d%s%s%s%s"
1474 " -D dstT1=%s -D dstT=%s -D convertToDT=%s%s%s%s%s",
1475 depth, ocl::typeToStr(depth), haveMask ? " -D HAVE_MASK" : "", (int)wgs,
1476 ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)), wgs2_aligned,
1477 doubleSupport ? " -D DOUBLE_SUPPORT" : "",
1478 _src.isContinuous() ? " -D HAVE_SRC_CONT" : "",
1479 _mask.isContinuous() ? " -D HAVE_MASK_CONT" : "", kercn,
1480 needMinVal ? " -D NEED_MINVAL" : "", needMaxVal ? " -D NEED_MAXVAL" : "",
1481 needMinLoc ? " -D NEED_MINLOC" : "", needMaxLoc ? " -D NEED_MAXLOC" : "",
1482 ocl::typeToStr(ddepth), ocl::typeToStr(CV_MAKE_TYPE(ddepth, kercn)),
1483 ocl::convertTypeStr(depth, ddepth, kercn, cvt), absValues ? " -D OP_ABS" : "",
1484 haveSrc2 ? " -D HAVE_SRC2" : "", maxVal2 ? " -D OP_CALC2" : "",
1485 haveSrc2 && _src2.isContinuous() ? " -D HAVE_SRC2_CONT" : "");
1487 printf("%s\n", opts.c_str());
1489 ocl::Kernel k("minmaxloc", ocl::core::minmaxloc_oclsrc, opts);
1493 int esz = CV_ELEM_SIZE(ddepth), esz32s = CV_ELEM_SIZE1(CV_32S),
1494 dbsize = groupnum * ((needMinVal ? esz : 0) + (needMaxVal ? esz : 0) +
1495 (needMinLoc ? esz32s : 0) + (needMaxLoc ? esz32s : 0) +
1496 (maxVal2 ? esz : 0));
1497 UMat src = _src.getUMat(), src2 = _src2.getUMat(), db(1, dbsize, CV_8UC1), mask = _mask.getUMat();
1501 src = src.reshape(1);
1502 src2 = src2.reshape(1);
1508 k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
1509 groupnum, ocl::KernelArg::PtrWriteOnly(db), ocl::KernelArg::ReadOnlyNoSize(src2));
1511 k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
1512 groupnum, ocl::KernelArg::PtrWriteOnly(db), ocl::KernelArg::ReadOnlyNoSize(mask),
1513 ocl::KernelArg::ReadOnlyNoSize(src2));
1518 k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
1519 groupnum, ocl::KernelArg::PtrWriteOnly(db));
1521 k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
1522 groupnum, ocl::KernelArg::PtrWriteOnly(db), ocl::KernelArg::ReadOnlyNoSize(mask));
1525 size_t globalsize = groupnum * wgs;
1526 if (!k.run(1, &globalsize, &wgs, false))
1529 static const getMinMaxResFunc functab[7] =
1531 getMinMaxRes<uchar>,
1533 getMinMaxRes<ushort>,
1534 getMinMaxRes<short>,
1536 getMinMaxRes<float>,
1537 getMinMaxRes<double>
1540 getMinMaxResFunc func = functab[ddepth];
1543 func(db.getMat(ACCESS_READ), minVal, maxVal,
1544 needMinLoc ? minLoc ? minLoc : locTemp : minLoc,
1545 needMaxLoc ? maxLoc ? maxLoc : locTemp : maxLoc,
1546 groupnum, src.cols, maxVal2);
1555 void cv::minMaxIdx(InputArray _src, double* minVal,
1556 double* maxVal, int* minIdx, int* maxIdx,
1559 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
1560 CV_Assert( (cn == 1 && (_mask.empty() || _mask.type() == CV_8U)) ||
1561 (cn > 1 && _mask.empty() && !minIdx && !maxIdx) );
1563 CV_OCL_RUN(_src.isUMat() && _src.dims() <= 2 && (_mask.empty() || _src.size() == _mask.size()),
1564 ocl_minMaxIdx(_src, minVal, maxVal, minIdx, maxIdx, _mask))
1566 Mat src = _src.getMat(), mask = _mask.getMat();
1568 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
1569 size_t total_size = src.total();
1570 int rows = src.size[0], cols = (int)(total_size/rows);
1571 if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
1573 IppiSize sz = { cols * cn, rows };
1577 typedef IppStatus (CV_STDCALL* ippiMaskMinMaxIndxFuncC1)(const void *, int, const void *, int,
1578 IppiSize, Ipp32f *, Ipp32f *, IppiPoint *, IppiPoint *);
1580 CV_SUPPRESS_DEPRECATED_START
1581 ippiMaskMinMaxIndxFuncC1 ippFuncC1 =
1582 type == CV_8UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1MR :
1583 type == CV_8SC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1MR :
1584 type == CV_16UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1MR :
1585 type == CV_32FC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1MR : 0;
1586 CV_SUPPRESS_DEPRECATED_END
1591 IppiPoint minp, maxp;
1592 if( ippFuncC1(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, &min, &max, &minp, &maxp) >= 0 )
1595 *minVal = (double)min;
1597 *maxVal = (double)max;
1598 if( !minp.x && !minp.y && !maxp.x && !maxp.y && !mask.data[0] )
1599 minp.x = maxp.x = -1;
1602 size_t minidx = minp.y * cols + minp.x + 1;
1603 ofs2idx(src, minidx, minIdx);
1607 size_t maxidx = maxp.y * cols + maxp.x + 1;
1608 ofs2idx(src, maxidx, maxIdx);
1612 setIppErrorStatus();
1617 typedef IppStatus (CV_STDCALL* ippiMinMaxIndxFuncC1)(const void *, int, IppiSize, Ipp32f *, Ipp32f *, IppiPoint *, IppiPoint *);
1619 CV_SUPPRESS_DEPRECATED_START
1620 ippiMinMaxIndxFuncC1 ippFuncC1 =
1621 depth == CV_8U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1R :
1622 depth == CV_8S ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1R :
1623 depth == CV_16U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1R :
1624 depth == CV_32F ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1R : 0;
1625 CV_SUPPRESS_DEPRECATED_END
1630 IppiPoint minp, maxp;
1631 if( ippFuncC1(src.data, (int)src.step[0], sz, &min, &max, &minp, &maxp) >= 0 )
1634 *minVal = (double)min;
1636 *maxVal = (double)max;
1639 size_t minidx = minp.y * cols + minp.x + 1;
1640 ofs2idx(src, minidx, minIdx);
1644 size_t maxidx = maxp.y * cols + maxp.x + 1;
1645 ofs2idx(src, maxidx, maxIdx);
1649 setIppErrorStatus();
1655 MinMaxIdxFunc func = getMinmaxTab(depth);
1656 CV_Assert( func != 0 );
1658 const Mat* arrays[] = {&src, &mask, 0};
1660 NAryMatIterator it(arrays, ptrs);
1662 size_t minidx = 0, maxidx = 0;
1663 int iminval = INT_MAX, imaxval = INT_MIN;
1664 float fminval = FLT_MAX, fmaxval = -FLT_MAX;
1665 double dminval = DBL_MAX, dmaxval = -DBL_MAX;
1666 size_t startidx = 1;
1667 int *minval = &iminval, *maxval = &imaxval;
1668 int planeSize = (int)it.size*cn;
1670 if( depth == CV_32F )
1671 minval = (int*)&fminval, maxval = (int*)&fmaxval;
1672 else if( depth == CV_64F )
1673 minval = (int*)&dminval, maxval = (int*)&dmaxval;
1675 for( size_t i = 0; i < it.nplanes; i++, ++it, startidx += planeSize )
1676 func( ptrs[0], ptrs[1], minval, maxval, &minidx, &maxidx, planeSize, startidx );
1679 dminval = dmaxval = 0;
1680 else if( depth == CV_32F )
1681 dminval = fminval, dmaxval = fmaxval;
1682 else if( depth <= CV_32S )
1683 dminval = iminval, dmaxval = imaxval;
1691 ofs2idx(src, minidx, minIdx);
1693 ofs2idx(src, maxidx, maxIdx);
1696 void cv::minMaxLoc( InputArray _img, double* minVal, double* maxVal,
1697 Point* minLoc, Point* maxLoc, InputArray mask )
1699 CV_Assert(_img.dims() <= 2);
1701 minMaxIdx(_img, minVal, maxVal, (int*)minLoc, (int*)maxLoc, mask);
1703 std::swap(minLoc->x, minLoc->y);
1705 std::swap(maxLoc->x, maxLoc->y);
1708 /****************************************************************************************\
1710 \****************************************************************************************/
1715 float normL2Sqr_(const float* a, const float* b, int n)
1717 int j = 0; float d = 0.f;
1721 float CV_DECL_ALIGNED(16) buf[4];
1722 __m128 d0 = _mm_setzero_ps(), d1 = _mm_setzero_ps();
1724 for( ; j <= n - 8; j += 8 )
1726 __m128 t0 = _mm_sub_ps(_mm_loadu_ps(a + j), _mm_loadu_ps(b + j));
1727 __m128 t1 = _mm_sub_ps(_mm_loadu_ps(a + j + 4), _mm_loadu_ps(b + j + 4));
1728 d0 = _mm_add_ps(d0, _mm_mul_ps(t0, t0));
1729 d1 = _mm_add_ps(d1, _mm_mul_ps(t1, t1));
1731 _mm_store_ps(buf, _mm_add_ps(d0, d1));
1732 d = buf[0] + buf[1] + buf[2] + buf[3];
1737 for( ; j <= n - 4; j += 4 )
1739 float t0 = a[j] - b[j], t1 = a[j+1] - b[j+1], t2 = a[j+2] - b[j+2], t3 = a[j+3] - b[j+3];
1740 d += t0*t0 + t1*t1 + t2*t2 + t3*t3;
1746 float t = a[j] - b[j];
1753 float normL1_(const float* a, const float* b, int n)
1755 int j = 0; float d = 0.f;
1759 float CV_DECL_ALIGNED(16) buf[4];
1760 static const int CV_DECL_ALIGNED(16) absbuf[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
1761 __m128 d0 = _mm_setzero_ps(), d1 = _mm_setzero_ps();
1762 __m128 absmask = _mm_load_ps((const float*)absbuf);
1764 for( ; j <= n - 8; j += 8 )
1766 __m128 t0 = _mm_sub_ps(_mm_loadu_ps(a + j), _mm_loadu_ps(b + j));
1767 __m128 t1 = _mm_sub_ps(_mm_loadu_ps(a + j + 4), _mm_loadu_ps(b + j + 4));
1768 d0 = _mm_add_ps(d0, _mm_and_ps(t0, absmask));
1769 d1 = _mm_add_ps(d1, _mm_and_ps(t1, absmask));
1771 _mm_store_ps(buf, _mm_add_ps(d0, d1));
1772 d = buf[0] + buf[1] + buf[2] + buf[3];
1777 for( ; j <= n - 4; j += 4 )
1779 d += std::abs(a[j] - b[j]) + std::abs(a[j+1] - b[j+1]) +
1780 std::abs(a[j+2] - b[j+2]) + std::abs(a[j+3] - b[j+3]);
1785 d += std::abs(a[j] - b[j]);
1789 int normL1_(const uchar* a, const uchar* b, int n)
1795 __m128i d0 = _mm_setzero_si128();
1797 for( ; j <= n - 16; j += 16 )
1799 __m128i t0 = _mm_loadu_si128((const __m128i*)(a + j));
1800 __m128i t1 = _mm_loadu_si128((const __m128i*)(b + j));
1802 d0 = _mm_add_epi32(d0, _mm_sad_epu8(t0, t1));
1805 for( ; j <= n - 4; j += 4 )
1807 __m128i t0 = _mm_cvtsi32_si128(*(const int*)(a + j));
1808 __m128i t1 = _mm_cvtsi32_si128(*(const int*)(b + j));
1810 d0 = _mm_add_epi32(d0, _mm_sad_epu8(t0, t1));
1812 d = _mm_cvtsi128_si32(_mm_add_epi32(d0, _mm_unpackhi_epi64(d0, d0)));
1817 for( ; j <= n - 4; j += 4 )
1819 d += std::abs(a[j] - b[j]) + std::abs(a[j+1] - b[j+1]) +
1820 std::abs(a[j+2] - b[j+2]) + std::abs(a[j+3] - b[j+3]);
1824 d += std::abs(a[j] - b[j]);
1828 static const uchar popCountTable[] =
1830 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1831 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1832 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1833 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1834 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1835 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1836 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1837 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
1840 static const uchar popCountTable2[] =
1842 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
1843 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
1844 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4,
1845 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4,
1846 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4,
1847 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4,
1848 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4,
1849 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4
1852 static const uchar popCountTable4[] =
1854 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1855 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1856 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1857 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1858 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1859 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1860 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1861 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
1864 static int normHamming(const uchar* a, int n)
1866 int i = 0, result = 0;
1869 uint32x4_t bits = vmovq_n_u32(0);
1870 for (; i <= n - 16; i += 16) {
1871 uint8x16_t A_vec = vld1q_u8 (a + i);
1872 uint8x16_t bitsSet = vcntq_u8 (A_vec);
1873 uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet);
1874 uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8);
1875 bits = vaddq_u32(bits, bitSet4);
1877 uint64x2_t bitSet2 = vpaddlq_u32 (bits);
1878 result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0);
1879 result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2);
1882 for( ; i <= n - 4; i += 4 )
1883 result += popCountTable[a[i]] + popCountTable[a[i+1]] +
1884 popCountTable[a[i+2]] + popCountTable[a[i+3]];
1886 result += popCountTable[a[i]];
1890 int normHamming(const uchar* a, const uchar* b, int n)
1892 int i = 0, result = 0;
1895 uint32x4_t bits = vmovq_n_u32(0);
1896 for (; i <= n - 16; i += 16) {
1897 uint8x16_t A_vec = vld1q_u8 (a + i);
1898 uint8x16_t B_vec = vld1q_u8 (b + i);
1899 uint8x16_t AxorB = veorq_u8 (A_vec, B_vec);
1900 uint8x16_t bitsSet = vcntq_u8 (AxorB);
1901 uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet);
1902 uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8);
1903 bits = vaddq_u32(bits, bitSet4);
1905 uint64x2_t bitSet2 = vpaddlq_u32 (bits);
1906 result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0);
1907 result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2);
1910 for( ; i <= n - 4; i += 4 )
1911 result += popCountTable[a[i] ^ b[i]] + popCountTable[a[i+1] ^ b[i+1]] +
1912 popCountTable[a[i+2] ^ b[i+2]] + popCountTable[a[i+3] ^ b[i+3]];
1914 result += popCountTable[a[i] ^ b[i]];
1918 static int normHamming(const uchar* a, int n, int cellSize)
1921 return normHamming(a, n);
1922 const uchar* tab = 0;
1924 tab = popCountTable2;
1925 else if( cellSize == 4 )
1926 tab = popCountTable4;
1928 CV_Error( CV_StsBadSize, "bad cell size (not 1, 2 or 4) in normHamming" );
1929 int i = 0, result = 0;
1930 #if CV_ENABLE_UNROLLED
1931 for( ; i <= n - 4; i += 4 )
1932 result += tab[a[i]] + tab[a[i+1]] + tab[a[i+2]] + tab[a[i+3]];
1935 result += tab[a[i]];
1939 int normHamming(const uchar* a, const uchar* b, int n, int cellSize)
1942 return normHamming(a, b, n);
1943 const uchar* tab = 0;
1945 tab = popCountTable2;
1946 else if( cellSize == 4 )
1947 tab = popCountTable4;
1949 CV_Error( CV_StsBadSize, "bad cell size (not 1, 2 or 4) in normHamming" );
1950 int i = 0, result = 0;
1951 #if CV_ENABLE_UNROLLED
1952 for( ; i <= n - 4; i += 4 )
1953 result += tab[a[i] ^ b[i]] + tab[a[i+1] ^ b[i+1]] +
1954 tab[a[i+2] ^ b[i+2]] + tab[a[i+3] ^ b[i+3]];
1957 result += tab[a[i] ^ b[i]];
1962 template<typename T, typename ST> int
1963 normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
1965 ST result = *_result;
1968 result = std::max(result, normInf<T, ST>(src, len*cn));
1972 for( int i = 0; i < len; i++, src += cn )
1975 for( int k = 0; k < cn; k++ )
1976 result = std::max(result, ST(std::abs(src[k])));
1983 template<typename T, typename ST> int
1984 normL1_(const T* src, const uchar* mask, ST* _result, int len, int cn)
1986 ST result = *_result;
1989 result += normL1<T, ST>(src, len*cn);
1993 for( int i = 0; i < len; i++, src += cn )
1996 for( int k = 0; k < cn; k++ )
1997 result += std::abs(src[k]);
2004 template<typename T, typename ST> int
2005 normL2_(const T* src, const uchar* mask, ST* _result, int len, int cn)
2007 ST result = *_result;
2010 result += normL2Sqr<T, ST>(src, len*cn);
2014 for( int i = 0; i < len; i++, src += cn )
2017 for( int k = 0; k < cn; k++ )
2028 template<typename T, typename ST> int
2029 normDiffInf_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn)
2031 ST result = *_result;
2034 result = std::max(result, normInf<T, ST>(src1, src2, len*cn));
2038 for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
2041 for( int k = 0; k < cn; k++ )
2042 result = std::max(result, (ST)std::abs(src1[k] - src2[k]));
2049 template<typename T, typename ST> int
2050 normDiffL1_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn)
2052 ST result = *_result;
2055 result += normL1<T, ST>(src1, src2, len*cn);
2059 for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
2062 for( int k = 0; k < cn; k++ )
2063 result += std::abs(src1[k] - src2[k]);
2070 template<typename T, typename ST> int
2071 normDiffL2_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn)
2073 ST result = *_result;
2076 result += normL2Sqr<T, ST>(src1, src2, len*cn);
2080 for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
2083 for( int k = 0; k < cn; k++ )
2085 ST v = src1[k] - src2[k];
2095 #define CV_DEF_NORM_FUNC(L, suffix, type, ntype) \
2096 static int norm##L##_##suffix(const type* src, const uchar* mask, ntype* r, int len, int cn) \
2097 { return norm##L##_(src, mask, r, len, cn); } \
2098 static int normDiff##L##_##suffix(const type* src1, const type* src2, \
2099 const uchar* mask, ntype* r, int len, int cn) \
2100 { return normDiff##L##_(src1, src2, mask, r, (int)len, cn); }
2102 #define CV_DEF_NORM_ALL(suffix, type, inftype, l1type, l2type) \
2103 CV_DEF_NORM_FUNC(Inf, suffix, type, inftype) \
2104 CV_DEF_NORM_FUNC(L1, suffix, type, l1type) \
2105 CV_DEF_NORM_FUNC(L2, suffix, type, l2type)
2107 CV_DEF_NORM_ALL(8u, uchar, int, int, int)
2108 CV_DEF_NORM_ALL(8s, schar, int, int, int)
2109 CV_DEF_NORM_ALL(16u, ushort, int, int, double)
2110 CV_DEF_NORM_ALL(16s, short, int, int, double)
2111 CV_DEF_NORM_ALL(32s, int, int, double, double)
2112 CV_DEF_NORM_ALL(32f, float, float, double, double)
2113 CV_DEF_NORM_ALL(64f, double, double, double, double)
2116 typedef int (*NormFunc)(const uchar*, const uchar*, uchar*, int, int);
2117 typedef int (*NormDiffFunc)(const uchar*, const uchar*, const uchar*, uchar*, int, int);
2119 static NormFunc getNormFunc(int normType, int depth)
2121 static NormFunc normTab[3][8] =
2124 (NormFunc)GET_OPTIMIZED(normInf_8u), (NormFunc)GET_OPTIMIZED(normInf_8s), (NormFunc)GET_OPTIMIZED(normInf_16u), (NormFunc)GET_OPTIMIZED(normInf_16s),
2125 (NormFunc)GET_OPTIMIZED(normInf_32s), (NormFunc)GET_OPTIMIZED(normInf_32f), (NormFunc)normInf_64f, 0
2128 (NormFunc)GET_OPTIMIZED(normL1_8u), (NormFunc)GET_OPTIMIZED(normL1_8s), (NormFunc)GET_OPTIMIZED(normL1_16u), (NormFunc)GET_OPTIMIZED(normL1_16s),
2129 (NormFunc)GET_OPTIMIZED(normL1_32s), (NormFunc)GET_OPTIMIZED(normL1_32f), (NormFunc)normL1_64f, 0
2132 (NormFunc)GET_OPTIMIZED(normL2_8u), (NormFunc)GET_OPTIMIZED(normL2_8s), (NormFunc)GET_OPTIMIZED(normL2_16u), (NormFunc)GET_OPTIMIZED(normL2_16s),
2133 (NormFunc)GET_OPTIMIZED(normL2_32s), (NormFunc)GET_OPTIMIZED(normL2_32f), (NormFunc)normL2_64f, 0
2137 return normTab[normType][depth];
2140 static NormDiffFunc getNormDiffFunc(int normType, int depth)
2142 static NormDiffFunc normDiffTab[3][8] =
2145 (NormDiffFunc)GET_OPTIMIZED(normDiffInf_8u), (NormDiffFunc)normDiffInf_8s,
2146 (NormDiffFunc)normDiffInf_16u, (NormDiffFunc)normDiffInf_16s,
2147 (NormDiffFunc)normDiffInf_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffInf_32f),
2148 (NormDiffFunc)normDiffInf_64f, 0
2151 (NormDiffFunc)GET_OPTIMIZED(normDiffL1_8u), (NormDiffFunc)normDiffL1_8s,
2152 (NormDiffFunc)normDiffL1_16u, (NormDiffFunc)normDiffL1_16s,
2153 (NormDiffFunc)normDiffL1_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffL1_32f),
2154 (NormDiffFunc)normDiffL1_64f, 0
2157 (NormDiffFunc)GET_OPTIMIZED(normDiffL2_8u), (NormDiffFunc)normDiffL2_8s,
2158 (NormDiffFunc)normDiffL2_16u, (NormDiffFunc)normDiffL2_16s,
2159 (NormDiffFunc)normDiffL2_32s, (NormDiffFunc)GET_OPTIMIZED(normDiffL2_32f),
2160 (NormDiffFunc)normDiffL2_64f, 0
2164 return normDiffTab[normType][depth];
2169 static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & result )
2171 const ocl::Device & d = ocl::Device::getDefault();
2172 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
2173 bool doubleSupport = d.doubleFPConfig() > 0,
2174 haveMask = _mask.kind() != _InputArray::NONE;
2176 if ( !(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR) ||
2177 (!doubleSupport && depth == CV_64F))
2180 UMat src = _src.getUMat();
2182 if (normType == NORM_INF)
2184 if (cn == 1 || !haveMask)
2185 ocl_minMaxIdx(_src, NULL, &result, NULL, NULL, _mask,
2186 std::max(depth, CV_32S), depth != CV_8U && depth != CV_16U);
2189 int dbsize = d.maxComputeUnits();
2190 size_t wgs = d.maxWorkGroupSize();
2192 int wgs2_aligned = 1;
2193 while (wgs2_aligned < (int)wgs)
2197 ocl::Kernel k("reduce", ocl::core::reduce_oclsrc,
2198 format("-D OP_NORM_INF_MASK -D HAVE_MASK -D DEPTH_%d"
2199 " -D srcT=%s -D srcT1=%s -D WGS=%d -D cn=%d -D WGS2_ALIGNED=%d%s%s%s",
2200 depth, ocl::typeToStr(type), ocl::typeToStr(depth),
2201 wgs, cn, wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
2202 src.isContinuous() ? " -D HAVE_CONT_SRC" : "",
2203 _mask.isContinuous() ? " -D HAVE_MASK_CONT" : ""));
2207 UMat db(1, dbsize, type), mask = _mask.getUMat();
2208 k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
2209 dbsize, ocl::KernelArg::PtrWriteOnly(db), ocl::KernelArg::ReadOnlyNoSize(mask));
2211 size_t globalsize = dbsize * wgs;
2212 if (!k.run(1, &globalsize, &wgs, true))
2215 minMaxIdx(db.getMat(ACCESS_READ), NULL, &result, NULL, NULL, noArray());
2218 else if (normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR)
2221 bool unstype = depth == CV_8U || depth == CV_16U;
2223 if ( !ocl_sum(haveMask ? src : src.reshape(1), sc, normType == NORM_L2 || normType == NORM_L2SQR ?
2224 OCL_OP_SUM_SQR : (unstype ? OCL_OP_SUM : OCL_OP_SUM_ABS), _mask) )
2231 for (int i = 0; i < cn; ++i)
2234 result = normType == NORM_L1 || normType == NORM_L2SQR ? s : std::sqrt(s);
2244 double cv::norm( InputArray _src, int normType, InputArray _mask )
2246 normType &= NORM_TYPE_MASK;
2247 CV_Assert( normType == NORM_INF || normType == NORM_L1 ||
2248 normType == NORM_L2 || normType == NORM_L2SQR ||
2249 ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && _src.type() == CV_8U) );
2253 CV_OCL_RUN_(_src.isUMat() && _src.dims() <= 2,
2254 ocl_norm(_src, normType, _mask, _result),
2258 Mat src = _src.getMat(), mask = _mask.getMat();
2259 int depth = src.depth(), cn = src.channels();
2261 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
2262 size_t total_size = src.total();
2263 int rows = src.size[0], cols = (int)(total_size/rows);
2265 if( (src.dims == 2 || (src.isContinuous() && mask.isContinuous()))
2266 && cols > 0 && (size_t)rows*cols == total_size
2267 && (normType == NORM_INF || normType == NORM_L1 ||
2268 normType == NORM_L2 || normType == NORM_L2SQR) )
2270 IppiSize sz = { cols, rows };
2271 int type = src.type();
2274 typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *);
2275 ippiMaskNormFuncC1 ippFuncC1 =
2276 normType == NORM_INF ?
2277 (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8u_C1MR :
2278 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8s_C1MR :
2279 // type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_16u_C1MR :
2280 type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_32f_C1MR :
2282 normType == NORM_L1 ?
2283 (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8u_C1MR :
2284 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8s_C1MR :
2285 type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_16u_C1MR :
2286 type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_32f_C1MR :
2288 normType == NORM_L2 || normType == NORM_L2SQR ?
2289 (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8u_C1MR :
2290 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8s_C1MR :
2291 type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_16u_C1MR :
2292 type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_32f_C1MR :
2297 if( ippFuncC1(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, &norm) >= 0 )
2298 return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm;
2300 setIppErrorStatus();
2302 typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *);
2303 ippiMaskNormFuncC3 ippFuncC3 =
2304 normType == NORM_INF ?
2305 (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_8u_C3CMR :
2306 type == CV_8SC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_8s_C3CMR :
2307 type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_16u_C3CMR :
2308 type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_32f_C3CMR :
2310 normType == NORM_L1 ?
2311 (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_8u_C3CMR :
2312 type == CV_8SC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_8s_C3CMR :
2313 type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_16u_C3CMR :
2314 type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_32f_C3CMR :
2316 normType == NORM_L2 || normType == NORM_L2SQR ?
2317 (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_8u_C3CMR :
2318 type == CV_8SC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_8s_C3CMR :
2319 type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_16u_C3CMR :
2320 type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_32f_C3CMR :
2324 Ipp64f norm1, norm2, norm3;
2325 if( ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 &&
2326 ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 &&
2327 ippFuncC3(src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0)
2330 normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) :
2331 normType == NORM_L1 ? norm1 + norm2 + norm3 :
2332 normType == NORM_L2 || normType == NORM_L2SQR ? std::sqrt(norm1 * norm1 + norm2 * norm2 + norm3 * norm3) :
2334 return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm;
2336 setIppErrorStatus();
2341 typedef IppStatus (CV_STDCALL* ippiNormFuncHint)(const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint);
2342 typedef IppStatus (CV_STDCALL* ippiNormFuncNoHint)(const void *, int, IppiSize, Ipp64f *);
2343 ippiNormFuncHint ippFuncHint =
2344 normType == NORM_L1 ?
2345 (type == CV_32FC1 ? (ippiNormFuncHint)ippiNorm_L1_32f_C1R :
2346 type == CV_32FC3 ? (ippiNormFuncHint)ippiNorm_L1_32f_C3R :
2347 type == CV_32FC4 ? (ippiNormFuncHint)ippiNorm_L1_32f_C4R :
2349 normType == NORM_L2 || normType == NORM_L2SQR ?
2350 (type == CV_32FC1 ? (ippiNormFuncHint)ippiNorm_L2_32f_C1R :
2351 type == CV_32FC3 ? (ippiNormFuncHint)ippiNorm_L2_32f_C3R :
2352 type == CV_32FC4 ? (ippiNormFuncHint)ippiNorm_L2_32f_C4R :
2354 ippiNormFuncNoHint ippFuncNoHint =
2355 normType == NORM_INF ?
2356 (type == CV_8UC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_8u_C1R :
2357 type == CV_8UC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_8u_C3R :
2358 type == CV_8UC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_8u_C4R :
2359 type == CV_16UC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C1R :
2360 type == CV_16UC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C3R :
2361 type == CV_16UC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C4R :
2362 type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C1R :
2363 #if (IPP_VERSION_X100 >= 801)
2364 type == CV_16SC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768
2365 type == CV_16SC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768
2367 type == CV_32FC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_32f_C1R :
2368 type == CV_32FC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_32f_C3R :
2369 type == CV_32FC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_32f_C4R :
2371 normType == NORM_L1 ?
2372 (type == CV_8UC1 ? (ippiNormFuncNoHint)ippiNorm_L1_8u_C1R :
2373 type == CV_8UC3 ? (ippiNormFuncNoHint)ippiNorm_L1_8u_C3R :
2374 type == CV_8UC4 ? (ippiNormFuncNoHint)ippiNorm_L1_8u_C4R :
2375 type == CV_16UC1 ? (ippiNormFuncNoHint)ippiNorm_L1_16u_C1R :
2376 type == CV_16UC3 ? (ippiNormFuncNoHint)ippiNorm_L1_16u_C3R :
2377 type == CV_16UC4 ? (ippiNormFuncNoHint)ippiNorm_L1_16u_C4R :
2378 type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_L1_16s_C1R :
2379 type == CV_16SC3 ? (ippiNormFuncNoHint)ippiNorm_L1_16s_C3R :
2380 type == CV_16SC4 ? (ippiNormFuncNoHint)ippiNorm_L1_16s_C4R :
2382 normType == NORM_L2 || normType == NORM_L2SQR ?
2383 (type == CV_8UC1 ? (ippiNormFuncNoHint)ippiNorm_L2_8u_C1R :
2384 type == CV_8UC3 ? (ippiNormFuncNoHint)ippiNorm_L2_8u_C3R :
2385 type == CV_8UC4 ? (ippiNormFuncNoHint)ippiNorm_L2_8u_C4R :
2386 type == CV_16UC1 ? (ippiNormFuncNoHint)ippiNorm_L2_16u_C1R :
2387 type == CV_16UC3 ? (ippiNormFuncNoHint)ippiNorm_L2_16u_C3R :
2388 type == CV_16UC4 ? (ippiNormFuncNoHint)ippiNorm_L2_16u_C4R :
2389 type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_L2_16s_C1R :
2390 type == CV_16SC3 ? (ippiNormFuncNoHint)ippiNorm_L2_16s_C3R :
2391 type == CV_16SC4 ? (ippiNormFuncNoHint)ippiNorm_L2_16s_C4R :
2393 // Make sure only zero or one version of the function pointer is valid
2394 CV_Assert(!ippFuncHint || !ippFuncNoHint);
2395 if( ippFuncHint || ippFuncNoHint )
2397 Ipp64f norm_array[4];
2398 IppStatus ret = ippFuncHint ? ippFuncHint(src.data, (int)src.step[0], sz, norm_array, ippAlgHintAccurate) :
2399 ippFuncNoHint(src.data, (int)src.step[0], sz, norm_array);
2402 Ipp64f norm = (normType == NORM_L2 || normType == NORM_L2SQR) ? norm_array[0] * norm_array[0] : norm_array[0];
2403 for( int i = 1; i < cn; i++ )
2406 normType == NORM_INF ? std::max(norm, norm_array[i]) :
2407 normType == NORM_L1 ? norm + norm_array[i] :
2408 normType == NORM_L2 || normType == NORM_L2SQR ? norm + norm_array[i] * norm_array[i] :
2411 return normType == NORM_L2 ? (double)std::sqrt(norm) : (double)norm;
2413 setIppErrorStatus();
2419 if( src.isContinuous() && mask.empty() )
2421 size_t len = src.total()*cn;
2422 if( len == (size_t)(int)len )
2424 if( depth == CV_32F )
2426 const float* data = src.ptr<float>();
2428 if( normType == NORM_L2 )
2431 GET_OPTIMIZED(normL2_32f)(data, 0, &result, (int)len, 1);
2432 return std::sqrt(result);
2434 if( normType == NORM_L2SQR )
2437 GET_OPTIMIZED(normL2_32f)(data, 0, &result, (int)len, 1);
2440 if( normType == NORM_L1 )
2443 GET_OPTIMIZED(normL1_32f)(data, 0, &result, (int)len, 1);
2446 if( normType == NORM_INF )
2449 GET_OPTIMIZED(normInf_32f)(data, 0, &result, (int)len, 1);
2453 if( depth == CV_8U )
2455 const uchar* data = src.ptr<uchar>();
2457 if( normType == NORM_HAMMING )
2458 return normHamming(data, (int)len);
2460 if( normType == NORM_HAMMING2 )
2461 return normHamming(data, (int)len, 2);
2466 CV_Assert( mask.empty() || mask.type() == CV_8U );
2468 if( normType == NORM_HAMMING || normType == NORM_HAMMING2 )
2473 bitwise_and(src, mask, temp);
2474 return norm(temp, normType);
2476 int cellSize = normType == NORM_HAMMING ? 1 : 2;
2478 const Mat* arrays[] = {&src, 0};
2480 NAryMatIterator it(arrays, ptrs);
2481 int total = (int)it.size;
2484 for( size_t i = 0; i < it.nplanes; i++, ++it )
2485 result += normHamming(ptrs[0], total, cellSize);
2490 NormFunc func = getNormFunc(normType >> 1, depth);
2491 CV_Assert( func != 0 );
2493 const Mat* arrays[] = {&src, &mask, 0};
2503 NAryMatIterator it(arrays, ptrs);
2504 int j, total = (int)it.size, blockSize = total, intSumBlockSize = 0, count = 0;
2505 bool blockSum = (normType == NORM_L1 && depth <= CV_16S) ||
2506 ((normType == NORM_L2 || normType == NORM_L2SQR) && depth <= CV_8S);
2508 int *ibuf = &result.i;
2513 intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
2514 blockSize = std::min(blockSize, intSumBlockSize);
2516 esz = src.elemSize();
2519 for( size_t i = 0; i < it.nplanes; i++, ++it )
2521 for( j = 0; j < total; j += blockSize )
2523 int bsz = std::min(total - j, blockSize);
2524 func( ptrs[0], ptrs[1], (uchar*)ibuf, bsz, cn );
2526 if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
2538 if( normType == NORM_INF )
2540 if( depth == CV_64F )
2542 else if( depth == CV_32F )
2543 result.d = result.f;
2545 result.d = result.i;
2547 else if( normType == NORM_L2 )
2548 result.d = std::sqrt(result.d);
2557 static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask, double & result )
2560 int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
2561 bool relative = (normType & NORM_RELATIVE) != 0;
2562 normType &= ~NORM_RELATIVE;
2563 bool normsum = normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR;
2565 if ( !(normType == NORM_INF || normsum) )
2570 if (!ocl_sum(_src1, sc1, normType == NORM_L2 || normType == NORM_L2SQR ?
2571 OCL_OP_SUM_SQR : OCL_OP_SUM, _mask, _src2, relative, sc2))
2576 if (!ocl_minMaxIdx(_src1, NULL, &sc1[0], NULL, NULL, _mask, std::max(CV_32S, depth),
2577 false, _src2, relative ? &sc2[0] : NULL))
2583 for (int i = 0; i < cn; ++i)
2590 if (normType == NORM_L2)
2592 result = std::sqrt(result);
2598 result /= (s2 + DBL_EPSILON);
2607 double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
2609 CV_Assert( _src1.sameSize(_src2) && _src1.type() == _src2.type() );
2613 CV_OCL_RUN_(_src1.isUMat(),
2614 ocl_norm(_src1, _src2, normType, _mask, _result),
2618 if( normType & CV_RELATIVE )
2620 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
2621 Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
2623 normType &= NORM_TYPE_MASK;
2624 CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR ||
2625 ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && src1.type() == CV_8U) );
2626 size_t total_size = src1.total();
2627 int rows = src1.size[0], cols = (int)(total_size/rows);
2628 if( (src1.dims == 2 || (src1.isContinuous() && src2.isContinuous() && mask.isContinuous()))
2629 && cols > 0 && (size_t)rows*cols == total_size
2630 && (normType == NORM_INF || normType == NORM_L1 ||
2631 normType == NORM_L2 || normType == NORM_L2SQR) )
2633 IppiSize sz = { cols, rows };
2634 int type = src1.type();
2637 typedef IppStatus (CV_STDCALL* ippiMaskNormRelFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *);
2638 ippiMaskNormRelFuncC1 ippFuncC1 =
2639 normType == NORM_INF ?
2640 (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8u_C1MR :
2641 type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8s_C1MR :
2642 type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_16u_C1MR :
2643 type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_32f_C1MR :
2645 normType == NORM_L1 ?
2646 (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_8u_C1MR :
2647 type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_8s_C1MR :
2648 type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_16u_C1MR :
2649 type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_32f_C1MR :
2651 normType == NORM_L2 || normType == NORM_L2SQR ?
2652 (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_8u_C1MR :
2653 type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_8s_C1MR :
2654 type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_16u_C1MR :
2655 type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_32f_C1MR :
2660 if( ippFuncC1(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, &norm) >= 0 )
2661 return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm;
2662 setIppErrorStatus();
2667 typedef IppStatus (CV_STDCALL* ippiNormRelFuncNoHint)(const void *, int, const void *, int, IppiSize, Ipp64f *);
2668 typedef IppStatus (CV_STDCALL* ippiNormRelFuncHint)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint);
2669 ippiNormRelFuncNoHint ippFuncNoHint =
2670 normType == NORM_INF ?
2671 (type == CV_8UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_8u_C1R :
2672 type == CV_16UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_16u_C1R :
2673 type == CV_16SC1 ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_16s_C1R :
2674 type == CV_32FC1 ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_32f_C1R :
2676 normType == NORM_L1 ?
2677 (type == CV_8UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L1_8u_C1R :
2678 type == CV_16UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L1_16u_C1R :
2679 type == CV_16SC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L1_16s_C1R :
2681 normType == NORM_L2 || normType == NORM_L2SQR ?
2682 (type == CV_8UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L2_8u_C1R :
2683 type == CV_16UC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L2_16u_C1R :
2684 type == CV_16SC1 ? (ippiNormRelFuncNoHint)ippiNormRel_L2_16s_C1R :
2686 ippiNormRelFuncHint ippFuncHint =
2687 normType == NORM_L1 ?
2688 (type == CV_32FC1 ? (ippiNormRelFuncHint)ippiNormRel_L1_32f_C1R :
2690 normType == NORM_L2 || normType == NORM_L2SQR ?
2691 (type == CV_32FC1 ? (ippiNormRelFuncHint)ippiNormRel_L2_32f_C1R :
2696 if( ippFuncNoHint(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], sz, &norm) >= 0 )
2697 return (double)norm;
2698 setIppErrorStatus();
2703 if( ippFuncHint(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], sz, &norm, ippAlgHintAccurate) >= 0 )
2704 return (double)norm;
2705 setIppErrorStatus();
2710 return norm(_src1, _src2, normType & ~CV_RELATIVE, _mask)/(norm(_src2, normType, _mask) + DBL_EPSILON);
2713 Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
2714 int depth = src1.depth(), cn = src1.channels();
2717 CV_Assert( normType == NORM_INF || normType == NORM_L1 ||
2718 normType == NORM_L2 || normType == NORM_L2SQR ||
2719 ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && src1.type() == CV_8U) );
2721 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
2722 size_t total_size = src1.total();
2723 int rows = src1.size[0], cols = (int)(total_size/rows);
2724 if( (src1.dims == 2 || (src1.isContinuous() && src2.isContinuous() && mask.isContinuous()))
2725 && cols > 0 && (size_t)rows*cols == total_size
2726 && (normType == NORM_INF || normType == NORM_L1 ||
2727 normType == NORM_L2 || normType == NORM_L2SQR) )
2729 IppiSize sz = { cols, rows };
2730 int type = src1.type();
2733 typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *);
2734 ippiMaskNormDiffFuncC1 ippFuncC1 =
2735 normType == NORM_INF ?
2736 (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8u_C1MR :
2737 type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8s_C1MR :
2738 type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_16u_C1MR :
2739 type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_32f_C1MR :
2741 normType == NORM_L1 ?
2742 (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8u_C1MR :
2743 type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8s_C1MR :
2744 type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_16u_C1MR :
2745 type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_32f_C1MR :
2747 normType == NORM_L2 || normType == NORM_L2SQR ?
2748 (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8u_C1MR :
2749 type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8s_C1MR :
2750 type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_16u_C1MR :
2751 type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_32f_C1MR :
2756 if( ippFuncC1(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, &norm) >= 0 )
2757 return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm;
2758 setIppErrorStatus();
2760 typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC3)(const void *, int, const void *, int, const void *, int, IppiSize, int, Ipp64f *);
2761 ippiMaskNormDiffFuncC3 ippFuncC3 =
2762 normType == NORM_INF ?
2763 (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8u_C3CMR :
2764 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8s_C3CMR :
2765 type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_16u_C3CMR :
2766 type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_32f_C3CMR :
2768 normType == NORM_L1 ?
2769 (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8u_C3CMR :
2770 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8s_C3CMR :
2771 type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_16u_C3CMR :
2772 type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_32f_C3CMR :
2774 normType == NORM_L2 || normType == NORM_L2SQR ?
2775 (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8u_C3CMR :
2776 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8s_C3CMR :
2777 type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_16u_C3CMR :
2778 type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_32f_C3CMR :
2782 Ipp64f norm1, norm2, norm3;
2783 if( ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 &&
2784 ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 &&
2785 ippFuncC3(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0)
2788 normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) :
2789 normType == NORM_L1 ? norm1 + norm2 + norm3 :
2790 normType == NORM_L2 || normType == NORM_L2SQR ? std::sqrt(norm1 * norm1 + norm2 * norm2 + norm3 * norm3) :
2792 return normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm;
2794 setIppErrorStatus();
2799 typedef IppStatus (CV_STDCALL* ippiNormDiffFuncHint)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint);
2800 typedef IppStatus (CV_STDCALL* ippiNormDiffFuncNoHint)(const void *, int, const void *, int, IppiSize, Ipp64f *);
2801 ippiNormDiffFuncHint ippFuncHint =
2802 normType == NORM_L1 ?
2803 (type == CV_32FC1 ? (ippiNormDiffFuncHint)ippiNormDiff_L1_32f_C1R :
2804 type == CV_32FC3 ? (ippiNormDiffFuncHint)ippiNormDiff_L1_32f_C3R :
2805 type == CV_32FC4 ? (ippiNormDiffFuncHint)ippiNormDiff_L1_32f_C4R :
2807 normType == NORM_L2 || normType == NORM_L2SQR ?
2808 (type == CV_32FC1 ? (ippiNormDiffFuncHint)ippiNormDiff_L2_32f_C1R :
2809 type == CV_32FC3 ? (ippiNormDiffFuncHint)ippiNormDiff_L2_32f_C3R :
2810 type == CV_32FC4 ? (ippiNormDiffFuncHint)ippiNormDiff_L2_32f_C4R :
2812 ippiNormDiffFuncNoHint ippFuncNoHint =
2813 normType == NORM_INF ?
2814 (type == CV_8UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_8u_C1R :
2815 type == CV_8UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_8u_C3R :
2816 type == CV_8UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_8u_C4R :
2817 type == CV_16UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C1R :
2818 type == CV_16UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C3R :
2819 type == CV_16UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C4R :
2820 type == CV_16SC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C1R :
2821 #if (IPP_VERSION_X100 >= 801)
2822 type == CV_16SC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768
2823 type == CV_16SC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768
2825 type == CV_32FC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_32f_C1R :
2826 type == CV_32FC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_32f_C3R :
2827 type == CV_32FC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_32f_C4R :
2829 normType == NORM_L1 ?
2830 (type == CV_8UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_8u_C1R :
2831 type == CV_8UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_8u_C3R :
2832 type == CV_8UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_8u_C4R :
2833 type == CV_16UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C1R :
2834 type == CV_16UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C3R :
2835 type == CV_16UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C4R :
2836 type == CV_16SC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C1R :
2837 type == CV_16SC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C3R :
2838 type == CV_16SC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C4R :
2840 normType == NORM_L2 || normType == NORM_L2SQR ?
2841 (type == CV_8UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_8u_C1R :
2842 type == CV_8UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_8u_C3R :
2843 type == CV_8UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_8u_C4R :
2844 type == CV_16UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16u_C1R :
2845 type == CV_16UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16u_C3R :
2846 type == CV_16UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16u_C4R :
2847 type == CV_16SC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16s_C1R :
2848 type == CV_16SC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16s_C3R :
2849 type == CV_16SC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16s_C4R :
2851 // Make sure only zero or one version of the function pointer is valid
2852 CV_Assert(!ippFuncHint || !ippFuncNoHint);
2853 if( ippFuncHint || ippFuncNoHint )
2855 Ipp64f norm_array[4];
2856 IppStatus ret = ippFuncHint ? ippFuncHint(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], sz, norm_array, ippAlgHintAccurate) :
2857 ippFuncNoHint(src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], sz, norm_array);
2860 Ipp64f norm = (normType == NORM_L2 || normType == NORM_L2SQR) ? norm_array[0] * norm_array[0] : norm_array[0];
2861 for( int i = 1; i < src1.channels(); i++ )
2864 normType == NORM_INF ? std::max(norm, norm_array[i]) :
2865 normType == NORM_L1 ? norm + norm_array[i] :
2866 normType == NORM_L2 || normType == NORM_L2SQR ? norm + norm_array[i] * norm_array[i] :
2869 return normType == NORM_L2 ? (double)std::sqrt(norm) : (double)norm;
2871 setIppErrorStatus();
2877 if( src1.isContinuous() && src2.isContinuous() && mask.empty() )
2879 size_t len = src1.total()*src1.channels();
2880 if( len == (size_t)(int)len )
2882 if( src1.depth() == CV_32F )
2884 const float* data1 = src1.ptr<float>();
2885 const float* data2 = src2.ptr<float>();
2887 if( normType == NORM_L2 )
2890 GET_OPTIMIZED(normDiffL2_32f)(data1, data2, 0, &result, (int)len, 1);
2891 return std::sqrt(result);
2893 if( normType == NORM_L2SQR )
2896 GET_OPTIMIZED(normDiffL2_32f)(data1, data2, 0, &result, (int)len, 1);
2899 if( normType == NORM_L1 )
2902 GET_OPTIMIZED(normDiffL1_32f)(data1, data2, 0, &result, (int)len, 1);
2905 if( normType == NORM_INF )
2908 GET_OPTIMIZED(normDiffInf_32f)(data1, data2, 0, &result, (int)len, 1);
2915 CV_Assert( mask.empty() || mask.type() == CV_8U );
2917 if( normType == NORM_HAMMING || normType == NORM_HAMMING2 )
2922 bitwise_xor(src1, src2, temp);
2923 bitwise_and(temp, mask, temp);
2924 return norm(temp, normType);
2926 int cellSize = normType == NORM_HAMMING ? 1 : 2;
2928 const Mat* arrays[] = {&src1, &src2, 0};
2930 NAryMatIterator it(arrays, ptrs);
2931 int total = (int)it.size;
2934 for( size_t i = 0; i < it.nplanes; i++, ++it )
2935 result += normHamming(ptrs[0], ptrs[1], total, cellSize);
2940 NormDiffFunc func = getNormDiffFunc(normType >> 1, depth);
2941 CV_Assert( func != 0 );
2943 const Mat* arrays[] = {&src1, &src2, &mask, 0};
2954 NAryMatIterator it(arrays, ptrs);
2955 int j, total = (int)it.size, blockSize = total, intSumBlockSize = 0, count = 0;
2956 bool blockSum = (normType == NORM_L1 && depth <= CV_16S) ||
2957 ((normType == NORM_L2 || normType == NORM_L2SQR) && depth <= CV_8S);
2959 unsigned *ibuf = &result.u;
2964 intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15);
2965 blockSize = std::min(blockSize, intSumBlockSize);
2967 esz = src1.elemSize();
2970 for( size_t i = 0; i < it.nplanes; i++, ++it )
2972 for( j = 0; j < total; j += blockSize )
2974 int bsz = std::min(total - j, blockSize);
2975 func( ptrs[0], ptrs[1], ptrs[2], (uchar*)ibuf, bsz, cn );
2977 if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
2990 if( normType == NORM_INF )
2992 if( depth == CV_64F )
2994 else if( depth == CV_32F )
2995 result.d = result.f;
2997 result.d = result.u;
2999 else if( normType == NORM_L2 )
3000 result.d = std::sqrt(result.d);
3006 ///////////////////////////////////// batch distance ///////////////////////////////////////
3011 template<typename _Tp, typename _Rt>
3012 void batchDistL1_(const _Tp* src1, const _Tp* src2, size_t step2,
3013 int nvecs, int len, _Rt* dist, const uchar* mask)
3015 step2 /= sizeof(src2[0]);
3018 for( int i = 0; i < nvecs; i++ )
3019 dist[i] = normL1<_Tp, _Rt>(src1, src2 + step2*i, len);
3023 _Rt val0 = std::numeric_limits<_Rt>::max();
3024 for( int i = 0; i < nvecs; i++ )
3025 dist[i] = mask[i] ? normL1<_Tp, _Rt>(src1, src2 + step2*i, len) : val0;
3029 template<typename _Tp, typename _Rt>
3030 void batchDistL2Sqr_(const _Tp* src1, const _Tp* src2, size_t step2,
3031 int nvecs, int len, _Rt* dist, const uchar* mask)
3033 step2 /= sizeof(src2[0]);
3036 for( int i = 0; i < nvecs; i++ )
3037 dist[i] = normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len);
3041 _Rt val0 = std::numeric_limits<_Rt>::max();
3042 for( int i = 0; i < nvecs; i++ )
3043 dist[i] = mask[i] ? normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len) : val0;
3047 template<typename _Tp, typename _Rt>
3048 void batchDistL2_(const _Tp* src1, const _Tp* src2, size_t step2,
3049 int nvecs, int len, _Rt* dist, const uchar* mask)
3051 step2 /= sizeof(src2[0]);
3054 for( int i = 0; i < nvecs; i++ )
3055 dist[i] = std::sqrt(normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len));
3059 _Rt val0 = std::numeric_limits<_Rt>::max();
3060 for( int i = 0; i < nvecs; i++ )
3061 dist[i] = mask[i] ? std::sqrt(normL2Sqr<_Tp, _Rt>(src1, src2 + step2*i, len)) : val0;
3065 static void batchDistHamming(const uchar* src1, const uchar* src2, size_t step2,
3066 int nvecs, int len, int* dist, const uchar* mask)
3068 step2 /= sizeof(src2[0]);
3071 for( int i = 0; i < nvecs; i++ )
3072 dist[i] = normHamming(src1, src2 + step2*i, len);
3077 for( int i = 0; i < nvecs; i++ )
3078 dist[i] = mask[i] ? normHamming(src1, src2 + step2*i, len) : val0;
3082 static void batchDistHamming2(const uchar* src1, const uchar* src2, size_t step2,
3083 int nvecs, int len, int* dist, const uchar* mask)
3085 step2 /= sizeof(src2[0]);
3088 for( int i = 0; i < nvecs; i++ )
3089 dist[i] = normHamming(src1, src2 + step2*i, len, 2);
3094 for( int i = 0; i < nvecs; i++ )
3095 dist[i] = mask[i] ? normHamming(src1, src2 + step2*i, len, 2) : val0;
3099 static void batchDistL1_8u32s(const uchar* src1, const uchar* src2, size_t step2,
3100 int nvecs, int len, int* dist, const uchar* mask)
3102 batchDistL1_<uchar, int>(src1, src2, step2, nvecs, len, dist, mask);
3105 static void batchDistL1_8u32f(const uchar* src1, const uchar* src2, size_t step2,
3106 int nvecs, int len, float* dist, const uchar* mask)
3108 batchDistL1_<uchar, float>(src1, src2, step2, nvecs, len, dist, mask);
3111 static void batchDistL2Sqr_8u32s(const uchar* src1, const uchar* src2, size_t step2,
3112 int nvecs, int len, int* dist, const uchar* mask)
3114 batchDistL2Sqr_<uchar, int>(src1, src2, step2, nvecs, len, dist, mask);
3117 static void batchDistL2Sqr_8u32f(const uchar* src1, const uchar* src2, size_t step2,
3118 int nvecs, int len, float* dist, const uchar* mask)
3120 batchDistL2Sqr_<uchar, float>(src1, src2, step2, nvecs, len, dist, mask);
3123 static void batchDistL2_8u32f(const uchar* src1, const uchar* src2, size_t step2,
3124 int nvecs, int len, float* dist, const uchar* mask)
3126 batchDistL2_<uchar, float>(src1, src2, step2, nvecs, len, dist, mask);
3129 static void batchDistL1_32f(const float* src1, const float* src2, size_t step2,
3130 int nvecs, int len, float* dist, const uchar* mask)
3132 batchDistL1_<float, float>(src1, src2, step2, nvecs, len, dist, mask);
3135 static void batchDistL2Sqr_32f(const float* src1, const float* src2, size_t step2,
3136 int nvecs, int len, float* dist, const uchar* mask)
3138 batchDistL2Sqr_<float, float>(src1, src2, step2, nvecs, len, dist, mask);
3141 static void batchDistL2_32f(const float* src1, const float* src2, size_t step2,
3142 int nvecs, int len, float* dist, const uchar* mask)
3144 batchDistL2_<float, float>(src1, src2, step2, nvecs, len, dist, mask);
3147 typedef void (*BatchDistFunc)(const uchar* src1, const uchar* src2, size_t step2,
3148 int nvecs, int len, uchar* dist, const uchar* mask);
3151 struct BatchDistInvoker : public ParallelLoopBody
3153 BatchDistInvoker( const Mat& _src1, const Mat& _src2,
3154 Mat& _dist, Mat& _nidx, int _K,
3155 const Mat& _mask, int _update,
3156 BatchDistFunc _func)
3168 void operator()(const Range& range) const
3170 AutoBuffer<int> buf(src2->rows);
3173 for( int i = range.start; i < range.end; i++ )
3175 func(src1->ptr(i), src2->ptr(), src2->step, src2->rows, src2->cols,
3176 K > 0 ? (uchar*)bufptr : dist->ptr(i), mask->data ? mask->ptr(i) : 0);
3180 int* nidxptr = nidx->ptr<int>(i);
3181 // since positive float's can be compared just like int's,
3182 // we handle both CV_32S and CV_32F cases with a single branch
3183 int* distptr = (int*)dist->ptr(i);
3187 for( j = 0; j < src2->rows; j++ )
3190 if( d < distptr[K-1] )
3192 for( k = K-2; k >= 0 && distptr[k] > d; k-- )
3194 nidxptr[k+1] = nidxptr[k];
3195 distptr[k+1] = distptr[k];
3197 nidxptr[k+1] = j + update;
3217 void cv::batchDistance( InputArray _src1, InputArray _src2,
3218 OutputArray _dist, int dtype, OutputArray _nidx,
3219 int normType, int K, InputArray _mask,
3220 int update, bool crosscheck )
3222 Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
3223 int type = src1.type();
3224 CV_Assert( type == src2.type() && src1.cols == src2.cols &&
3225 (type == CV_32F || type == CV_8U));
3226 CV_Assert( _nidx.needed() == (K > 0) );
3230 dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 ? CV_32S : CV_32F;
3232 CV_Assert( (type == CV_8U && dtype == CV_32S) || dtype == CV_32F);
3234 K = std::min(K, src2.rows);
3236 _dist.create(src1.rows, (K > 0 ? K : src2.rows), dtype);
3237 Mat dist = _dist.getMat(), nidx;
3238 if( _nidx.needed() )
3240 _nidx.create(dist.size(), CV_32S);
3241 nidx = _nidx.getMat();
3244 if( update == 0 && K > 0 )
3246 dist = Scalar::all(dtype == CV_32S ? (double)INT_MAX : (double)FLT_MAX);
3247 nidx = Scalar::all(-1);
3252 CV_Assert( K == 1 && update == 0 && mask.empty() );
3254 batchDistance(src2, src1, tdist, dtype, tidx, normType, K, mask, 0, false);
3256 // if an idx-th element from src1 appeared to be the nearest to i-th element of src2,
3257 // we update the minimum mutual distance between idx-th element of src1 and the whole src2 set.
3258 // As a result, if nidx[idx] = i*, it means that idx-th element of src1 is the nearest
3259 // to i*-th element of src2 and i*-th element of src2 is the closest to idx-th element of src1.
3260 // If nidx[idx] = -1, it means that there is no such ideal couple for it in src2.
3261 // This O(N) procedure is called cross-check and it helps to eliminate some false matches.
3262 if( dtype == CV_32S )
3264 for( int i = 0; i < tdist.rows; i++ )
3266 int idx = tidx.at<int>(i);
3267 int d = tdist.at<int>(i), d0 = dist.at<int>(idx);
3270 dist.at<int>(idx) = d;
3271 nidx.at<int>(idx) = i + update;
3277 for( int i = 0; i < tdist.rows; i++ )
3279 int idx = tidx.at<int>(i);
3280 float d = tdist.at<float>(i), d0 = dist.at<float>(idx);
3283 dist.at<float>(idx) = d;
3284 nidx.at<int>(idx) = i + update;
3291 BatchDistFunc func = 0;
3294 if( normType == NORM_L1 && dtype == CV_32S )
3295 func = (BatchDistFunc)batchDistL1_8u32s;
3296 else if( normType == NORM_L1 && dtype == CV_32F )
3297 func = (BatchDistFunc)batchDistL1_8u32f;
3298 else if( normType == NORM_L2SQR && dtype == CV_32S )
3299 func = (BatchDistFunc)batchDistL2Sqr_8u32s;
3300 else if( normType == NORM_L2SQR && dtype == CV_32F )
3301 func = (BatchDistFunc)batchDistL2Sqr_8u32f;
3302 else if( normType == NORM_L2 && dtype == CV_32F )
3303 func = (BatchDistFunc)batchDistL2_8u32f;
3304 else if( normType == NORM_HAMMING && dtype == CV_32S )
3305 func = (BatchDistFunc)batchDistHamming;
3306 else if( normType == NORM_HAMMING2 && dtype == CV_32S )
3307 func = (BatchDistFunc)batchDistHamming2;
3309 else if( type == CV_32F && dtype == CV_32F )
3311 if( normType == NORM_L1 )
3312 func = (BatchDistFunc)batchDistL1_32f;
3313 else if( normType == NORM_L2SQR )
3314 func = (BatchDistFunc)batchDistL2Sqr_32f;
3315 else if( normType == NORM_L2 )
3316 func = (BatchDistFunc)batchDistL2_32f;
3320 CV_Error_(CV_StsUnsupportedFormat,
3321 ("The combination of type=%d, dtype=%d and normType=%d is not supported",
3322 type, dtype, normType));
3324 parallel_for_(Range(0, src1.rows),
3325 BatchDistInvoker(src1, src2, dist, nidx, K, mask, update, func));
3329 void cv::findNonZero( InputArray _src, OutputArray _idx )
3331 Mat src = _src.getMat();
3332 CV_Assert( src.type() == CV_8UC1 );
3333 int n = countNonZero(src);
3334 if( _idx.kind() == _InputArray::MAT && !_idx.getMatRef().isContinuous() )
3336 _idx.create(n, 1, CV_32SC2);
3337 Mat idx = _idx.getMat();
3338 CV_Assert(idx.isContinuous());
3339 Point* idx_ptr = (Point*)idx.data;
3341 for( int i = 0; i < src.rows; i++ )
3343 const uchar* bin_ptr = src.ptr(i);
3344 for( int j = 0; j < src.cols; j++ )
3346 *idx_ptr++ = Point(j, i);
3350 double cv::PSNR(InputArray _src1, InputArray _src2)
3352 CV_Assert( _src1.depth() == CV_8U );
3353 double diff = std::sqrt(norm(_src1, _src2, NORM_L2SQR)/(_src1.total()*_src1.channels()));
3354 return 20*log10(255./(diff+DBL_EPSILON));
3358 CV_IMPL CvScalar cvSum( const CvArr* srcarr )
3360 cv::Scalar sum = cv::sum(cv::cvarrToMat(srcarr, false, true, 1));
3361 if( CV_IS_IMAGE(srcarr) )
3363 int coi = cvGetImageCOI((IplImage*)srcarr);
3366 CV_Assert( 0 < coi && coi <= 4 );
3367 sum = cv::Scalar(sum[coi-1]);
3373 CV_IMPL int cvCountNonZero( const CvArr* imgarr )
3375 cv::Mat img = cv::cvarrToMat(imgarr, false, true, 1);
3376 if( img.channels() > 1 )
3377 cv::extractImageCOI(imgarr, img);
3378 return countNonZero(img);
3383 cvAvg( const void* imgarr, const void* maskarr )
3385 cv::Mat img = cv::cvarrToMat(imgarr, false, true, 1);
3386 cv::Scalar mean = !maskarr ? cv::mean(img) : cv::mean(img, cv::cvarrToMat(maskarr));
3387 if( CV_IS_IMAGE(imgarr) )
3389 int coi = cvGetImageCOI((IplImage*)imgarr);
3392 CV_Assert( 0 < coi && coi <= 4 );
3393 mean = cv::Scalar(mean[coi-1]);
3401 cvAvgSdv( const CvArr* imgarr, CvScalar* _mean, CvScalar* _sdv, const void* maskarr )
3403 cv::Scalar mean, sdv;
3407 mask = cv::cvarrToMat(maskarr);
3409 cv::meanStdDev(cv::cvarrToMat(imgarr, false, true, 1), mean, sdv, mask );
3411 if( CV_IS_IMAGE(imgarr) )
3413 int coi = cvGetImageCOI((IplImage*)imgarr);
3416 CV_Assert( 0 < coi && coi <= 4 );
3417 mean = cv::Scalar(mean[coi-1]);
3418 sdv = cv::Scalar(sdv[coi-1]);
3423 *(cv::Scalar*)_mean = mean;
3425 *(cv::Scalar*)_sdv = sdv;
3430 cvMinMaxLoc( const void* imgarr, double* _minVal, double* _maxVal,
3431 CvPoint* _minLoc, CvPoint* _maxLoc, const void* maskarr )
3433 cv::Mat mask, img = cv::cvarrToMat(imgarr, false, true, 1);
3435 mask = cv::cvarrToMat(maskarr);
3436 if( img.channels() > 1 )
3437 cv::extractImageCOI(imgarr, img);
3439 cv::minMaxLoc( img, _minVal, _maxVal,
3440 (cv::Point*)_minLoc, (cv::Point*)_maxLoc, mask );
3445 cvNorm( const void* imgA, const void* imgB, int normType, const void* maskarr )
3454 a = cv::cvarrToMat(imgA, false, true, 1);
3456 mask = cv::cvarrToMat(maskarr);
3458 if( a.channels() > 1 && CV_IS_IMAGE(imgA) && cvGetImageCOI((const IplImage*)imgA) > 0 )
3459 cv::extractImageCOI(imgA, a);
3462 return !maskarr ? cv::norm(a, normType) : cv::norm(a, normType, mask);
3464 cv::Mat b = cv::cvarrToMat(imgB, false, true, 1);
3465 if( b.channels() > 1 && CV_IS_IMAGE(imgB) && cvGetImageCOI((const IplImage*)imgB) > 0 )
3466 cv::extractImageCOI(imgB, b);
3468 return !maskarr ? cv::norm(a, b, normType) : cv::norm(a, b, normType, mask);