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, 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.
48 template<typename T> static inline Scalar rawToScalar(const T& v)
51 typedef typename DataType<T>::channel_type T1;
52 int i, n = DataType<T>::channels;
53 for( i = 0; i < n; i++ )
54 s.val[i] = ((T1*)&v)[i];
58 /****************************************************************************************\
60 \****************************************************************************************/
62 template<typename T, typename WT, typename ST, int BLOCK_SIZE>
63 static Scalar sumBlock_( const Mat& srcmat )
65 assert( DataType<T>::type == srcmat.type() );
66 Size size = getContinuousSize( srcmat );
69 int y, remaining = BLOCK_SIZE;
71 for( y = 0; y < size.height; y++ )
73 const T* src = (const T*)(srcmat.data + srcmat.step*y);
75 while( x < size.width )
77 int limit = std::min( remaining, size.width - x );
80 for( ; x <= limit - 4; x += 4 )
87 for( ; x < limit; x++ )
89 if( remaining == 0 || (x == size.width && y == size.height-1) )
93 remaining = BLOCK_SIZE;
97 return rawToScalar(s0);
100 template<typename T, typename ST>
101 static Scalar sum_( const Mat& srcmat )
103 assert( DataType<T>::type == srcmat.type() );
104 Size size = getContinuousSize( srcmat );
107 for( int y = 0; y < size.height; y++ )
109 const T* src = (const T*)(srcmat.data + srcmat.step*y);
111 for( ; x <= size.width - 4; x += 4 )
118 for( ; x < size.width; x++ )
121 return rawToScalar(s);
124 typedef Scalar (*SumFunc)(const Mat& src);
126 Scalar sum( const Mat& m )
128 static SumFunc tab[]=
130 sumBlock_<uchar, unsigned, double, 1<<24>, 0,
131 sumBlock_<ushort, unsigned, double, 1<<16>,
132 sumBlock_<short, int, double, 1<<16>,
135 sum_<double, double>, 0,
137 sumBlock_<Vec<uchar, 2>, Vec<unsigned, 2>, Vec<double, 2>, 1<<24>, 0,
138 sumBlock_<Vec<ushort, 2>, Vec<unsigned, 2>, Vec<double, 2>, 1<<16>,
139 sumBlock_<Vec<short, 2>, Vec<int, 2>, Vec<double, 2>, 1<<16>,
140 sum_<Vec<int, 2>, Vec<double, 2> >,
141 sum_<Vec<float, 2>, Vec<double, 2> >,
142 sum_<Vec<double, 2>, Vec<double, 2> >, 0,
144 sumBlock_<Vec<uchar, 3>, Vec<unsigned, 3>, Vec<double, 3>, 1<<24>, 0,
145 sumBlock_<Vec<ushort, 3>, Vec<unsigned, 3>, Vec<double, 3>, 1<<16>,
146 sumBlock_<Vec<short, 3>, Vec<int, 3>, Vec<double, 3>, 1<<16>,
147 sum_<Vec<int, 3>, Vec<double, 3> >,
148 sum_<Vec<float, 3>, Vec<double, 3> >,
149 sum_<Vec<double, 3>, Vec<double, 3> >, 0,
151 sumBlock_<Vec<uchar, 4>, Vec<unsigned, 4>, Vec<double, 4>, 1<<24>, 0,
152 sumBlock_<Vec<ushort, 4>, Vec<unsigned, 4>, Vec<double, 4>, 1<<16>,
153 sumBlock_<Vec<short, 4>, Vec<int, 4>, Vec<double, 4>, 1<<16>,
154 sum_<Vec<int, 4>, Vec<double, 4> >,
155 sum_<Vec<float, 4>, Vec<double, 4> >,
156 sum_<Vec<double, 4>, Vec<double, 4> >, 0
159 Size size = m.size();
162 CV_Assert( m.channels() <= 4 );
164 func = tab[m.type()];
165 CV_Assert( func != 0 );
170 /****************************************************************************************\
172 \****************************************************************************************/
175 static int countNonZero_( const Mat& srcmat )
177 //assert( DataType<T>::type == srcmat.type() );
178 const T* src = (const T*)srcmat.data;
179 size_t step = srcmat.step/sizeof(src[0]);
180 Size size = getContinuousSize( srcmat );
183 for( ; size.height--; src += step )
186 for( ; x <= size.width - 4; x += 4 )
187 nz += (src[x] != 0) + (src[x+1] != 0) + (src[x+2] != 0) + (src[x+3] != 0);
188 for( ; x < size.width; x++ )
194 typedef int (*CountNonZeroFunc)(const Mat& src);
196 int countNonZero( const Mat& m )
198 static CountNonZeroFunc tab[] =
200 countNonZero_<uchar>, countNonZero_<uchar>, countNonZero_<ushort>,
201 countNonZero_<ushort>, countNonZero_<int>, countNonZero_<float>,
202 countNonZero_<double>, 0
205 CountNonZeroFunc func = tab[m.depth()];
206 CV_Assert( m.channels() == 1 && func != 0 );
211 /****************************************************************************************\
213 \****************************************************************************************/
215 template<typename T, typename WT, typename ST, int BLOCK_SIZE>
216 static Scalar meanBlock_( const Mat& srcmat, const Mat& maskmat )
218 assert( DataType<T>::type == srcmat.type() &&
219 CV_8U == maskmat.type() && srcmat.size() == maskmat.size() );
220 Size size = getContinuousSize( srcmat, maskmat );
223 int y, remaining = BLOCK_SIZE, pix = 0;
225 for( y = 0; y < size.height; y++ )
227 const T* src = (const T*)(srcmat.data + srcmat.step*y);
228 const uchar* mask = maskmat.data + maskmat.step*y;
230 while( x < size.width )
232 int limit = std::min( remaining, size.width - x );
235 for( ; x < limit; x++ )
238 if( remaining == 0 || (x == size.width && y == size.height-1) )
242 remaining = BLOCK_SIZE;
246 return rawToScalar(s0)*(1./std::max(pix, 1));
250 template<typename T, typename ST>
251 static Scalar mean_( const Mat& srcmat, const Mat& maskmat )
253 assert( DataType<T>::type == srcmat.type() &&
254 CV_8U == maskmat.type() && srcmat.size() == maskmat.size() );
255 Size size = getContinuousSize( srcmat, maskmat );
259 for( y = 0; y < size.height; y++ )
261 const T* src = (const T*)(srcmat.data + srcmat.step*y);
262 const uchar* mask = maskmat.data + maskmat.step*y;
263 for( int x = 0; x < size.width; x++ )
267 return rawToScalar(s)*(1./std::max(pix, 1));
270 typedef Scalar (*MeanMaskFunc)(const Mat& src, const Mat& mask);
272 Scalar mean(const Mat& m)
274 return sum(m)*(1./std::max(m.rows*m.cols, 1));
277 Scalar mean( const Mat& m, const Mat& mask )
279 static MeanMaskFunc tab[]=
281 meanBlock_<uchar, unsigned, double, 1<<24>, 0,
282 meanBlock_<ushort, unsigned, double, 1<<16>,
283 meanBlock_<short, int, double, 1<<16>,
285 mean_<float, double>,
286 mean_<double, double>, 0,
288 meanBlock_<Vec<uchar, 2>, Vec<unsigned, 2>, Vec<double, 2>, 1<<24>, 0,
289 meanBlock_<Vec<ushort, 2>, Vec<unsigned, 2>, Vec<double, 2>, 1<<16>,
290 meanBlock_<Vec<short, 2>, Vec<int, 2>, Vec<double, 2>, 1<<16>,
291 mean_<Vec<int, 2>, Vec<double, 2> >,
292 mean_<Vec<float, 2>, Vec<double, 2> >,
293 mean_<Vec<double, 2>, Vec<double, 2> >, 0,
295 meanBlock_<Vec<uchar, 3>, Vec<unsigned, 3>, Vec<double, 3>, 1<<24>, 0,
296 meanBlock_<Vec<ushort, 3>, Vec<unsigned, 3>, Vec<double, 3>, 1<<16>,
297 meanBlock_<Vec<short, 3>, Vec<int, 3>, Vec<double, 3>, 1<<16>,
298 mean_<Vec<int, 3>, Vec<double, 3> >,
299 mean_<Vec<float, 3>, Vec<double, 3> >,
300 mean_<Vec<double, 3>, Vec<double, 3> >, 0,
302 meanBlock_<Vec<uchar, 4>, Vec<unsigned, 4>, Vec<double, 4>, 1<<24>, 0,
303 meanBlock_<Vec<ushort, 4>, Vec<unsigned, 4>, Vec<double, 4>, 1<<16>,
304 meanBlock_<Vec<short, 4>, Vec<int, 4>, Vec<double, 4>, 1<<16>,
305 mean_<Vec<int, 4>, Vec<double, 4> >,
306 mean_<Vec<float, 4>, Vec<double, 4> >,
307 mean_<Vec<double, 4>, Vec<double, 4> >, 0
313 CV_Assert( m.channels() <= 4 && m.size() == mask.size() && mask.type() == CV_8U );
315 MeanMaskFunc func = tab[m.type()];
316 CV_Assert( func != 0 );
318 return func( m, mask );
321 /****************************************************************************************\
323 \****************************************************************************************/
325 template<typename T, typename SqT> struct SqrC1
329 rtype operator()(type1 x) const { return (SqT)x*x; }
332 template<typename T, typename SqT> struct SqrC2
334 typedef Vec<T, 2> type1;
335 typedef Vec<SqT, 2> rtype;
336 rtype operator()(const type1& x) const { return rtype((SqT)x[0]*x[0], (SqT)x[1]*x[1]); }
339 template<typename T, typename SqT> struct SqrC3
341 typedef Vec<T, 3> type1;
342 typedef Vec<SqT, 3> rtype;
343 rtype operator()(const type1& x) const
344 { return rtype((SqT)x[0]*x[0], (SqT)x[1]*x[1], (SqT)x[2]*x[2]); }
347 template<typename T, typename SqT> struct SqrC4
349 typedef Vec<T, 4> type1;
350 typedef Vec<SqT, 4> rtype;
351 rtype operator()(const type1& x) const
352 { return rtype((SqT)x[0]*x[0], (SqT)x[1]*x[1], (SqT)x[2]*x[2], (SqT)x[3]*x[3]); }
355 template<> inline double SqrC1<uchar, double>::operator()(uchar x) const
356 { return CV_SQR_8U(x); }
358 template<> inline Vec<double, 2> SqrC2<uchar, double>::operator()(const Vec<uchar, 2>& x) const
359 { return Vec<double, 2>(CV_SQR_8U(x[0]), CV_SQR_8U(x[1])); }
361 template<> inline Vec<double, 3> SqrC3<uchar, double>::operator() (const Vec<uchar, 3>& x) const
362 { return Vec<double, 3>(CV_SQR_8U(x[0]), CV_SQR_8U(x[1]), CV_SQR_8U(x[2])); }
364 template<> inline Vec<double, 4> SqrC4<uchar, double>::operator() (const Vec<uchar, 4>& x) const
365 { return Vec<double, 4>(CV_SQR_8U(x[0]), CV_SQR_8U(x[1]), CV_SQR_8U(x[2]), CV_SQR_8U(x[3])); }
368 template<class SqrOp> static void
369 meanStdDev_( const Mat& srcmat, Scalar& _mean, Scalar& _stddev )
372 typedef typename SqrOp::type1 T;
373 typedef typename SqrOp::rtype ST;
374 typedef typename DataType<ST>::channel_type ST1;
376 assert( DataType<T>::type == srcmat.type() );
377 Size size = getContinuousSize( srcmat );
380 for( int y = 0; y < size.height; y++ )
382 const T* src = (const T*)(srcmat.data + srcmat.step*y);
383 for( int x = 0; x < size.width; x++ )
391 _mean = _stddev = Scalar();
392 double scale = 1./std::max(size.width*size.height, 1);
393 for( int i = 0; i < DataType<ST>::channels; i++ )
395 double t = ((ST1*)&s)[i]*scale;
397 _stddev.val[i] = std::sqrt(std::max(((ST1*)&sq)[i]*scale - t*t, 0.));
401 template<class SqrOp> static void
402 meanStdDevMask_( const Mat& srcmat, const Mat& maskmat,
403 Scalar& _mean, Scalar& _stddev )
406 typedef typename SqrOp::type1 T;
407 typedef typename SqrOp::rtype ST;
408 typedef typename DataType<ST>::channel_type ST1;
410 assert( DataType<T>::type == srcmat.type() &&
411 CV_8U == maskmat.type() &&
412 srcmat.size() == maskmat.size() );
413 Size size = getContinuousSize( srcmat, maskmat );
417 for( int y = 0; y < size.height; y++ )
419 const T* src = (const T*)(srcmat.data + srcmat.step*y);
420 const uchar* mask = maskmat.data + maskmat.step*y;
421 for( int x = 0; x < size.width; x++ )
430 _mean = _stddev = Scalar();
431 double scale = 1./std::max(pix, 1);
432 for( int i = 0; i < DataType<ST>::channels; i++ )
434 double t = ((ST1*)&s)[i]*scale;
436 _stddev.val[i] = std::sqrt(std::max(((ST1*)&sq)[i]*scale - t*t, 0.));
440 typedef void (*MeanStdDevFunc)(const Mat& src, Scalar& mean, Scalar& stddev);
442 typedef void (*MeanStdDevMaskFunc)(const Mat& src, const Mat& mask,
443 Scalar& mean, Scalar& stddev);
445 void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask )
447 static MeanStdDevFunc tab[]=
449 meanStdDev_<SqrC1<uchar, double> >, 0,
450 meanStdDev_<SqrC1<ushort, double> >,
451 meanStdDev_<SqrC1<short, double> >,
452 meanStdDev_<SqrC1<int, double> >,
453 meanStdDev_<SqrC1<float, double> >,
454 meanStdDev_<SqrC1<double, double> >, 0,
456 meanStdDev_<SqrC2<uchar, double> >, 0,
457 meanStdDev_<SqrC2<ushort, double> >,
458 meanStdDev_<SqrC2<short, double> >,
459 meanStdDev_<SqrC2<int, double> >,
460 meanStdDev_<SqrC2<float, double> >,
461 meanStdDev_<SqrC2<double, double> >, 0,
463 meanStdDev_<SqrC3<uchar, double> >, 0,
464 meanStdDev_<SqrC3<ushort, double> >,
465 meanStdDev_<SqrC3<short, double> >,
466 meanStdDev_<SqrC3<int, double> >,
467 meanStdDev_<SqrC3<float, double> >,
468 meanStdDev_<SqrC3<double, double> >, 0,
470 meanStdDev_<SqrC4<uchar, double> >, 0,
471 meanStdDev_<SqrC4<ushort, double> >,
472 meanStdDev_<SqrC4<short, double> >,
473 meanStdDev_<SqrC4<int, double> >,
474 meanStdDev_<SqrC4<float, double> >,
475 meanStdDev_<SqrC4<double, double> >, 0
478 static MeanStdDevMaskFunc mtab[]=
480 meanStdDevMask_<SqrC1<uchar, double> >, 0,
481 meanStdDevMask_<SqrC1<ushort, double> >,
482 meanStdDevMask_<SqrC1<short, double> >,
483 meanStdDevMask_<SqrC1<int, double> >,
484 meanStdDevMask_<SqrC1<float, double> >,
485 meanStdDevMask_<SqrC1<double, double> >, 0,
487 meanStdDevMask_<SqrC2<uchar, double> >, 0,
488 meanStdDevMask_<SqrC2<ushort, double> >,
489 meanStdDevMask_<SqrC2<short, double> >,
490 meanStdDevMask_<SqrC2<int, double> >,
491 meanStdDevMask_<SqrC2<float, double> >,
492 meanStdDevMask_<SqrC2<double, double> >, 0,
494 meanStdDevMask_<SqrC3<uchar, double> >, 0,
495 meanStdDevMask_<SqrC3<ushort, double> >,
496 meanStdDevMask_<SqrC3<short, double> >,
497 meanStdDevMask_<SqrC3<int, double> >,
498 meanStdDevMask_<SqrC3<float, double> >,
499 meanStdDevMask_<SqrC3<double, double> >, 0,
501 meanStdDevMask_<SqrC4<uchar, double> >, 0,
502 meanStdDevMask_<SqrC4<ushort, double> >,
503 meanStdDevMask_<SqrC4<short, double> >,
504 meanStdDevMask_<SqrC4<int, double> >,
505 meanStdDevMask_<SqrC4<float, double> >,
506 meanStdDevMask_<SqrC4<double, double> >, 0
509 CV_Assert( m.channels() <= 4 );
513 MeanStdDevFunc func = tab[m.type()];
514 CV_Assert( func != 0 );
515 func( m, mean, stddev );
519 MeanStdDevMaskFunc func = mtab[m.type()];
520 CV_Assert( mask.size() == m.size() && mask.type() == CV_8U && func != 0 );
521 func( m, mask, mean, stddev );
526 /****************************************************************************************\
528 \****************************************************************************************/
530 template<typename T> static void
531 minMaxIndx_( const Mat& srcmat, double* minVal, double* maxVal, int* minLoc, int* maxLoc )
533 assert( DataType<T>::type == srcmat.type() );
534 const T* src = (const T*)srcmat.data;
535 size_t step = srcmat.step/sizeof(src[0]);
536 T min_val = src[0], max_val = min_val;
537 int min_loc = 0, max_loc = 0;
539 Size size = getContinuousSize( srcmat );
541 for( ; size.height--; src += step, loc += size.width )
543 for( x = 0; x < size.width; x++ )
551 else if( val > max_val )
566 template<typename T> static void
567 minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat,
568 double* minVal, double* maxVal, int* minLoc, int* maxLoc )
570 assert( DataType<T>::type == srcmat.type() &&
571 CV_8U == maskmat.type() &&
572 srcmat.size() == maskmat.size() );
573 const T* src = (const T*)srcmat.data;
574 const uchar* mask = maskmat.data;
575 size_t step = srcmat.step/sizeof(src[0]);
576 size_t maskstep = maskmat.step;
577 T min_val = 0, max_val = 0;
578 int min_loc = -1, max_loc = -1;
579 int x = 0, y, loc = 0;
580 Size size = getContinuousSize( srcmat, maskmat );
582 for( y = 0; y < size.height; y++, src += step, mask += maskstep, loc += size.width )
584 for( x = 0; x < size.width; x++ )
587 min_loc = max_loc = loc + x;
588 min_val = max_val = src[x];
595 for( ; y < size.height; x = 0, y++, src += step, mask += maskstep, loc += size.width )
597 for( ; x < size.width; x++ )
602 if( val < min_val && m )
607 else if( val > max_val && m )
621 typedef void (*MinMaxIndxFunc)(const Mat&, double*, double*, int*, int*);
623 typedef void (*MinMaxIndxMaskFunc)(const Mat&, const Mat&,
624 double*, double*, int*, int*);
626 void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
627 Point* minLoc, Point* maxLoc, const Mat& mask )
629 static MinMaxIndxFunc tab[] =
630 {minMaxIndx_<uchar>, 0, minMaxIndx_<ushort>, minMaxIndx_<short>,
631 minMaxIndx_<int>, minMaxIndx_<float>, minMaxIndx_<double>, 0};
632 static MinMaxIndxMaskFunc tabm[] =
633 {minMaxIndxMask_<uchar>, 0, minMaxIndxMask_<ushort>, minMaxIndxMask_<short>,
634 minMaxIndxMask_<int>, minMaxIndxMask_<float>, minMaxIndxMask_<double>, 0};
636 int depth = img.depth();
637 double minval=0, maxval=0;
638 int minloc=0, maxloc=0;
640 CV_Assert( img.channels() == 1 );
644 MinMaxIndxFunc func = tab[depth];
645 CV_Assert( func != 0 );
646 func( img, &minval, &maxval, &minloc, &maxloc );
650 CV_Assert( img.size() == mask.size() && mask.type() == CV_8U );
651 MinMaxIndxMaskFunc func = tabm[depth];
652 CV_Assert( func != 0 );
653 func( img, mask, &minval, &maxval, &minloc, &maxloc );
664 minLoc->y = minloc/img.cols;
665 minLoc->x = minloc - minLoc->y*img.cols;
668 minLoc->x = minLoc->y = -1;
674 maxLoc->y = maxloc/img.cols;
675 maxLoc->x = maxloc - maxLoc->y*img.cols;
678 maxLoc->x = maxLoc->y = -1;
682 /****************************************************************************************\
684 \****************************************************************************************/
686 template<typename T, typename WT=T> struct OpAbs
690 rtype operator()(type1 x) const { return (WT)std::abs(x); }
693 template<> inline uchar OpAbs<uchar, uchar>::operator()(uchar x) const { return x; }
694 template<> inline ushort OpAbs<ushort, ushort>::operator()(ushort x) const { return x; }
696 template<class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
697 static double normBlock_( const Mat& srcmat )
701 GlobUpdateFunc globUpdate;
702 typedef typename ElemFunc::type1 T;
703 typedef typename UpdateFunc::rtype WT;
704 typedef typename GlobUpdateFunc::rtype ST;
706 assert( DataType<T>::depth == srcmat.depth() );
707 Size size = getContinuousSize( srcmat, srcmat.channels() );
708 ST s0 = 0; // luckily, 0 is the correct starting value for both + and max update operations
710 int y, remaining = BLOCK_SIZE;
712 for( y = 0; y < size.height; y++ )
714 const T* src = (const T*)(srcmat.data + srcmat.step*y);
716 while( x < size.width )
718 int limit = std::min( remaining, size.width - x );
721 for( ; x <= limit - 4; x += 4 )
723 s = update(s, (WT)f(src[x]));
724 s = update(s, (WT)f(src[x+1]));
725 s = update(s, (WT)f(src[x+2]));
726 s = update(s, (WT)f(src[x+3]));
728 for( ; x < limit; x++ )
729 s = update(s, (WT)f(src[x]));
730 if( remaining == 0 || (x == size.width && y == size.height-1) )
732 s0 = globUpdate(s0, (ST)s);
734 remaining = BLOCK_SIZE;
741 template<class ElemFunc, class UpdateFunc>
742 static double norm_( const Mat& srcmat )
746 typedef typename ElemFunc::type1 T;
747 typedef typename UpdateFunc::rtype ST;
749 assert( DataType<T>::depth == srcmat.depth() );
750 Size size = getContinuousSize( srcmat, srcmat.channels() );
753 for( int y = 0; y < size.height; y++ )
755 const T* src = (const T*)(srcmat.data + srcmat.step*y);
757 for( ; x <= size.width - 4; x += 4 )
759 s = update(s, (ST)f(src[x]));
760 s = update(s, (ST)f(src[x+1]));
761 s = update(s, (ST)f(src[x+2]));
762 s = update(s, (ST)f(src[x+3]));
764 for( ; x < size.width; x++ )
765 s = update(s, (ST)f(src[x]));
770 template<class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
771 static double normMaskBlock_( const Mat& srcmat, const Mat& maskmat )
775 GlobUpdateFunc globUpdate;
776 typedef typename ElemFunc::type1 T;
777 typedef typename UpdateFunc::rtype WT;
778 typedef typename GlobUpdateFunc::rtype ST;
780 assert( DataType<T>::depth == srcmat.depth() );
781 Size size = getContinuousSize( srcmat, maskmat );
784 int y, remaining = BLOCK_SIZE;
786 for( y = 0; y < size.height; y++ )
788 const T* src = (const T*)(srcmat.data + srcmat.step*y);
789 const uchar* mask = maskmat.data + maskmat.step*y;
791 while( x < size.width )
793 int limit = std::min( remaining, size.width - x );
796 for( ; x <= limit - 4; x += 4 )
799 s = update(s, (WT)f(src[x]));
801 s = update(s, (WT)f(src[x+1]));
803 s = update(s, (WT)f(src[x+2]));
805 s = update(s, (WT)f(src[x+3]));
807 for( ; x < limit; x++ )
810 s = update(s, (WT)f(src[x]));
812 if( remaining == 0 || (x == size.width && y == size.height-1) )
814 s0 = globUpdate(s0, (ST)s);
816 remaining = BLOCK_SIZE;
823 template<class ElemFunc, class UpdateFunc>
824 static double normMask_( const Mat& srcmat, const Mat& maskmat )
828 typedef typename ElemFunc::type1 T;
829 typedef typename UpdateFunc::rtype ST;
831 assert( DataType<T>::depth == srcmat.depth() );
832 Size size = getContinuousSize( srcmat, maskmat );
835 for( int y = 0; y < size.height; y++ )
837 const T* src = (const T*)(srcmat.data + srcmat.step*y);
838 const uchar* mask = maskmat.data + maskmat.step*y;
840 for( ; x <= size.width - 4; x += 4 )
843 s = update(s, (ST)f(src[x]));
845 s = update(s, (ST)f(src[x+1]));
847 s = update(s, (ST)f(src[x+2]));
849 s = update(s, (ST)f(src[x+3]));
851 for( ; x < size.width; x++ )
854 s = update(s, (ST)f(src[x]));
860 template<typename T, class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
861 static double normDiffBlock_( const Mat& srcmat1, const Mat& srcmat2 )
865 GlobUpdateFunc globUpdate;
866 typedef typename UpdateFunc::rtype WT;
867 typedef typename GlobUpdateFunc::rtype ST;
869 assert( DataType<T>::depth == srcmat1.depth() );
870 Size size = getContinuousSize( srcmat1, srcmat2, srcmat1.channels() );
873 int y, remaining = BLOCK_SIZE;
875 for( y = 0; y < size.height; y++ )
877 const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y);
878 const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y);
880 while( x < size.width )
882 int limit = std::min( remaining, size.width - x );
885 for( ; x <= limit - 4; x += 4 )
887 s = update(s, (WT)f(src1[x] - src2[x]));
888 s = update(s, (WT)f(src1[x+1] - src2[x+1]));
889 s = update(s, (WT)f(src1[x+2] - src2[x+2]));
890 s = update(s, (WT)f(src1[x+3] - src2[x+3]));
892 for( ; x < limit; x++ )
893 s = update(s, (WT)f(src1[x] - src2[x]));
894 if( remaining == 0 || (x == size.width && y == size.height-1) )
896 s0 = globUpdate(s0, (ST)s);
898 remaining = BLOCK_SIZE;
905 template<typename T, class ElemFunc, class UpdateFunc>
906 static double normDiff_( const Mat& srcmat1, const Mat& srcmat2 )
910 typedef typename UpdateFunc::rtype ST;
912 assert( DataType<T>::depth == srcmat1.depth() );
913 Size size = getContinuousSize( srcmat1, srcmat2, srcmat1.channels() );
916 for( int y = 0; y < size.height; y++ )
918 const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y);
919 const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y);
921 for( ; x <= size.width - 4; x += 4 )
923 s = update(s, (ST)f(src1[x] - src2[x]));
924 s = update(s, (ST)f(src1[x+1] - src2[x+1]));
925 s = update(s, (ST)f(src1[x+2] - src2[x+2]));
926 s = update(s, (ST)f(src1[x+3] - src2[x+3]));
928 for( ; x < size.width; x++ )
929 s = update(s, (ST)f(src1[x] - src2[x]));
934 template<typename T, class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
935 static double normDiffMaskBlock_( const Mat& srcmat1, const Mat& srcmat2, const Mat& maskmat )
939 GlobUpdateFunc globUpdate;
940 typedef typename UpdateFunc::rtype WT;
941 typedef typename GlobUpdateFunc::rtype ST;
943 assert( DataType<T>::depth == srcmat1.depth() );
944 Size size = getContinuousSize( srcmat1, srcmat2, maskmat );
947 int y, remaining = BLOCK_SIZE;
949 for( y = 0; y < size.height; y++ )
951 const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y);
952 const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y);
953 const uchar* mask = maskmat.data + maskmat.step*y;
955 while( x < size.width )
957 int limit = std::min( remaining, size.width - x );
960 for( ; x <= limit - 4; x += 4 )
963 s = update(s, (WT)f(src1[x] - src2[x]));
965 s = update(s, (WT)f(src1[x+1] - src2[x+1]));
967 s = update(s, (WT)f(src1[x+2] - src2[x+2]));
969 s = update(s, (WT)f(src1[x+3] - src2[x+3]));
971 for( ; x < limit; x++ )
973 s = update(s, (WT)f(src1[x] - src2[x]));
974 if( remaining == 0 || (x == size.width && y == size.height-1) )
976 s0 = globUpdate(s0, (ST)s);
978 remaining = BLOCK_SIZE;
985 template<typename T, class ElemFunc, class UpdateFunc>
986 static double normDiffMask_( const Mat& srcmat1, const Mat& srcmat2, const Mat& maskmat )
990 typedef typename UpdateFunc::rtype ST;
992 assert( DataType<T>::depth == srcmat1.depth() );
993 Size size = getContinuousSize( srcmat1, srcmat2, maskmat );
996 for( int y = 0; y < size.height; y++ )
998 const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y);
999 const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y);
1000 const uchar* mask = maskmat.data + maskmat.step*y;
1002 for( ; x <= size.width - 4; x += 4 )
1005 s = update(s, (ST)f(src1[x] - src2[x]));
1007 s = update(s, (ST)f(src1[x+1] - src2[x+1]));
1009 s = update(s, (ST)f(src1[x+2] - src2[x+2]));
1011 s = update(s, (ST)f(src1[x+3] - src2[x+3]));
1013 for( ; x < size.width; x++ )
1015 s = update(s, (ST)f(src1[x] - src2[x]));
1021 typedef double (*NormFunc)(const Mat& src);
1022 typedef double (*NormDiffFunc)(const Mat& src1, const Mat& src2);
1023 typedef double (*NormMaskFunc)(const Mat& src1, const Mat& mask);
1024 typedef double (*NormDiffMaskFunc)(const Mat& src1, const Mat& src2, const Mat& mask);
1026 double norm( const Mat& a, int normType )
1028 static NormFunc tab[3][8] =
1031 norm_<OpAbs<uchar>, OpMax<int> >, 0,
1032 norm_<OpAbs<ushort>, OpMax<int> >,
1033 norm_<OpAbs<short, int>, OpMax<int> >,
1034 norm_<OpAbs<int>, OpMax<int> >,
1035 norm_<OpAbs<float>, OpMax<float> >,
1036 norm_<OpAbs<double>, OpMax<double> >
1040 normBlock_<OpAbs<uchar>, OpAdd<unsigned>, OpAdd<double>, 1<<24>, 0,
1041 normBlock_<OpAbs<ushort>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1042 normBlock_<OpAbs<short, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1043 norm_<OpAbs<int>, OpAdd<double> >,
1044 norm_<OpAbs<float>, OpAdd<double> >,
1045 norm_<OpAbs<double>, OpAdd<double> >
1049 normBlock_<SqrC1<uchar, unsigned>, OpAdd<unsigned>, OpAdd<double>, 1<<16>, 0,
1050 norm_<SqrC1<ushort, double>, OpAdd<double> >,
1051 norm_<SqrC1<short, double>, OpAdd<double> >,
1052 norm_<SqrC1<int, double>, OpAdd<double> >,
1053 norm_<SqrC1<float, double>, OpAdd<double> >,
1054 norm_<SqrC1<double, double>, OpAdd<double> >
1059 CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2);
1060 NormFunc func = tab[normType >> 1][a.depth()];
1061 CV_Assert(func != 0);
1063 return normType == NORM_L2 ? std::sqrt(r) : r;
1067 double norm( const Mat& a, int normType, const Mat& mask )
1069 static NormMaskFunc tab[3][8] =
1072 normMask_<OpAbs<uchar>, OpMax<int> >, 0,
1073 normMask_<OpAbs<ushort>, OpMax<int> >,
1074 normMask_<OpAbs<short, int>, OpMax<int> >,
1075 normMask_<OpAbs<int>, OpMax<int> >,
1076 normMask_<OpAbs<float>, OpMax<float> >,
1077 normMask_<OpAbs<double>, OpMax<double> >
1081 normMaskBlock_<OpAbs<uchar>, OpAdd<unsigned>, OpAdd<double>, 1<<24>, 0,
1082 normMaskBlock_<OpAbs<ushort>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1083 normMaskBlock_<OpAbs<short, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1084 normMask_<OpAbs<int>, OpAdd<double> >,
1085 normMask_<OpAbs<float>, OpAdd<double> >,
1086 normMask_<OpAbs<double>, OpAdd<double> >
1090 normMaskBlock_<SqrC1<uchar, unsigned>, OpAdd<unsigned>, OpAdd<double>, 1<<16>, 0,
1091 normMask_<SqrC1<ushort, double>, OpAdd<double> >,
1092 normMask_<SqrC1<short, double>, OpAdd<double> >,
1093 normMask_<SqrC1<int, double>, OpAdd<double> >,
1094 normMask_<SqrC1<float, double>, OpAdd<double> >,
1095 normMask_<SqrC1<double, double>, OpAdd<double> >
1100 return norm(a, normType);
1103 CV_Assert((normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) &&
1104 a.size() == mask.size() && mask.type() == CV_8U );
1105 NormMaskFunc func = tab[normType >> 1][a.depth()];
1106 CV_Assert(func != 0);
1107 double r = func(a, mask);
1108 return normType == NORM_L2 ? std::sqrt(r) : r;
1112 double norm( const Mat& a, const Mat& b, int normType )
1114 static NormDiffFunc tab[3][8] =
1117 normDiff_<uchar, OpAbs<int>, OpMax<int> >, 0,
1118 normDiff_<ushort, OpAbs<int>, OpMax<int> >,
1119 normDiff_<short, OpAbs<int>, OpMax<int> >,
1120 normDiff_<int, OpAbs<int>, OpMax<int> >,
1121 normDiff_<float, OpAbs<float>, OpMax<float> >,
1122 normDiff_<double, OpAbs<double>, OpMax<double> >
1126 normDiffBlock_<uchar, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<24>, 0,
1127 normDiffBlock_<ushort, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1128 normDiffBlock_<short, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1129 normDiff_<int, OpAbs<int>, OpAdd<double> >,
1130 normDiff_<float, OpAbs<float>, OpAdd<double> >,
1131 normDiff_<double, OpAbs<double>, OpAdd<double> >
1135 normDiffBlock_<uchar, SqrC1<int, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>, 0,
1136 normDiff_<ushort, SqrC1<int, double>, OpAdd<double> >,
1137 normDiff_<short, SqrC1<int, double>, OpAdd<double> >,
1138 normDiff_<int, SqrC1<int, double>, OpAdd<double> >,
1139 normDiff_<float, SqrC1<float, double>, OpAdd<double> >,
1140 normDiff_<double, SqrC1<double, double>, OpAdd<double> >
1144 CV_Assert( a.type() == b.type() && a.size() == b.size() );
1146 bool isRelative = (normType & NORM_RELATIVE) != 0;
1148 CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2);
1150 NormDiffFunc func = tab[normType >> 1][a.depth()];
1151 CV_Assert(func != 0);
1152 double r = func( a, b );
1153 if( normType == NORM_L2 )
1156 r /= norm(b, normType);
1160 double norm( const Mat& a, const Mat& b, int normType, const Mat& mask )
1162 static NormDiffMaskFunc tab[3][8] =
1165 normDiffMask_<uchar, OpAbs<int>, OpMax<int> >, 0,
1166 normDiffMask_<ushort, OpAbs<int>, OpMax<int> >,
1167 normDiffMask_<short, OpAbs<int>, OpMax<int> >,
1168 normDiffMask_<int, OpAbs<int>, OpMax<int> >,
1169 normDiffMask_<float, OpAbs<float>, OpMax<float> >,
1170 normDiffMask_<double, OpAbs<double>, OpMax<double> >
1174 normDiffMaskBlock_<uchar, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<24>, 0,
1175 normDiffMaskBlock_<ushort, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1176 normDiffMaskBlock_<short, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
1177 normDiffMask_<int, OpAbs<int>, OpAdd<double> >,
1178 normDiffMask_<float, OpAbs<float>, OpAdd<double> >,
1179 normDiffMask_<double, OpAbs<double>, OpAdd<double> >
1183 normDiffMaskBlock_<uchar, SqrC1<int, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>, 0,
1184 normDiffMask_<ushort, SqrC1<int, double>, OpAdd<double> >,
1185 normDiffMask_<short, SqrC1<int, double>, OpAdd<double> >,
1186 normDiffMask_<int, SqrC1<int, double>, OpAdd<double> >,
1187 normDiffMask_<float, SqrC1<float, double>, OpAdd<double> >,
1188 normDiffMask_<double, SqrC1<double, double>, OpAdd<double> >
1193 return norm(a, b, normType);
1195 CV_Assert( a.type() == b.type() && a.size() == b.size() &&
1196 a.size() == mask.size() && mask.type() == CV_8U );
1198 bool isRelative = (normType & NORM_RELATIVE) != 0;
1200 CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2);
1202 NormDiffMaskFunc func = tab[normType >> 1][a.depth()];
1203 CV_Assert(func != 0);
1204 double r = func( a, b, mask );
1205 if( normType == NORM_L2 )
1208 r /= std::max(norm(b, normType, mask), DBL_EPSILON);
1215 CV_IMPL CvScalar cvSum( const CvArr* srcarr )
1217 cv::Scalar sum = cv::sum(cv::cvarrToMat(srcarr, false, true, 1));
1218 if( CV_IS_IMAGE(srcarr) )
1220 int coi = cvGetImageCOI((IplImage*)srcarr);
1223 CV_Assert( 0 < coi && coi <= 4 );
1224 sum = cv::Scalar(sum[coi-1]);
1230 CV_IMPL int cvCountNonZero( const CvArr* imgarr )
1232 cv::Mat img = cv::cvarrToMat(imgarr, false, true, 1);
1233 if( img.channels() > 1 )
1234 cv::extractImageCOI(imgarr, img);
1235 return countNonZero(img);
1240 cvAvg( const void* imgarr, const void* maskarr )
1242 cv::Mat img = cv::cvarrToMat(imgarr, false, true, 1);
1243 cv::Scalar mean = !maskarr ? cv::mean(img) : cv::mean(img, cv::cvarrToMat(maskarr));
1244 if( CV_IS_IMAGE(imgarr) )
1246 int coi = cvGetImageCOI((IplImage*)imgarr);
1249 CV_Assert( 0 < coi && coi <= 4 );
1250 mean = cv::Scalar(mean[coi-1]);
1258 cvAvgSdv( const CvArr* imgarr, CvScalar* _mean, CvScalar* _sdv, const void* maskarr )
1260 cv::Scalar mean, sdv;
1264 mask = cv::cvarrToMat(maskarr);
1266 cv::meanStdDev(cv::cvarrToMat(imgarr, false, true, 1), mean, sdv, mask );
1268 if( CV_IS_IMAGE(imgarr) )
1270 int coi = cvGetImageCOI((IplImage*)imgarr);
1273 CV_Assert( 0 < coi && coi <= 4 );
1274 mean = cv::Scalar(mean[coi-1]);
1275 sdv = cv::Scalar(sdv[coi-1]);
1280 *(cv::Scalar*)_mean = mean;
1282 *(cv::Scalar*)_sdv = sdv;
1287 cvMinMaxLoc( const void* imgarr, double* _minVal, double* _maxVal,
1288 CvPoint* _minLoc, CvPoint* _maxLoc, const void* maskarr )
1290 cv::Mat mask, img = cv::cvarrToMat(imgarr, false, true, 1);
1292 mask = cv::cvarrToMat(maskarr);
1293 if( img.channels() > 1 )
1294 cv::extractImageCOI(imgarr, img);
1296 cv::minMaxLoc( img, _minVal, _maxVal,
1297 (cv::Point*)_minLoc, (cv::Point*)_maxLoc, mask );
1302 cvNorm( const void* imgA, const void* imgB, int normType, const void* maskarr )
1311 a = cv::cvarrToMat(imgA, false, true, 1);
1313 mask = cv::cvarrToMat(maskarr);
1315 if( a.channels() > 1 && CV_IS_IMAGE(imgA) && cvGetImageCOI((const IplImage*)imgA) > 0 )
1316 cv::extractImageCOI(imgA, a);
1319 return !maskarr ? cv::norm(a, normType) : cv::norm(a, normType, mask);
1321 cv::Mat b = cv::cvarrToMat(imgB, false, true, 1);
1322 if( b.channels() > 1 && CV_IS_IMAGE(imgB) && cvGetImageCOI((const IplImage*)imgB) > 0 )
1323 cv::extractImageCOI(imgB, b);
1325 return !maskarr ? cv::norm(a, b, normType) : cv::norm(a, b, normType, mask);