2010-05-12 01:44:00 +08:00
|
|
|
/*M///////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
|
|
//
|
|
|
|
// By downloading, copying, installing or using the software you agree to this license.
|
|
|
|
// If you do not agree to this license, do not download, install,
|
|
|
|
// copy or use the software.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// License Agreement
|
|
|
|
// For Open Source Computer Vision Library
|
|
|
|
//
|
|
|
|
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
2011-04-17 21:14:45 +08:00
|
|
|
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
2010-05-12 01:44:00 +08:00
|
|
|
// Third party copyrights are property of their respective owners.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
// are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// * Redistribution's of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
//
|
|
|
|
// * Redistribution's in binary form must reproduce the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
|
|
// and/or other materials provided with the distribution.
|
|
|
|
//
|
|
|
|
// * The name of the copyright holders may not be used to endorse or promote products
|
|
|
|
// derived from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// This software is provided by the copyright holders and contributors "as is" and
|
|
|
|
// any express or implied warranties, including, but not limited to, the implied
|
|
|
|
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
|
|
|
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
|
|
|
// indirect, incidental, special, exemplary, or consequential damages
|
|
|
|
// (including, but not limited to, procurement of substitute goods or services;
|
|
|
|
// loss of use, data, or profits; or business interruption) however caused
|
|
|
|
// and on any theory of liability, whether in contract, strict liability,
|
|
|
|
// or tort (including negligence or otherwise) arising in any way out of
|
|
|
|
// the use of this software, even if advised of the possibility of such damage.
|
|
|
|
//
|
|
|
|
//M*/
|
|
|
|
|
|
|
|
#include "precomp.hpp"
|
|
|
|
|
|
|
|
namespace cv
|
|
|
|
{
|
|
|
|
|
|
|
|
template<typename T> static inline Scalar rawToScalar(const T& v)
|
|
|
|
{
|
|
|
|
Scalar s;
|
|
|
|
typedef typename DataType<T>::channel_type T1;
|
|
|
|
int i, n = DataType<T>::channels;
|
|
|
|
for( i = 0; i < n; i++ )
|
|
|
|
s.val[i] = ((T1*)&v)[i];
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************************\
|
|
|
|
* sum *
|
|
|
|
\****************************************************************************************/
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
template<typename T, typename ST>
|
2011-05-17 23:44:01 +08:00
|
|
|
static int sum_(const T* src0, const uchar* mask, ST* dst, int len, int cn )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
const T* src = src0;
|
|
|
|
if( !mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
int i;
|
|
|
|
int k = cn % 4;
|
|
|
|
if( k == 1 )
|
|
|
|
{
|
|
|
|
ST s0 = dst[0];
|
|
|
|
for( i = 0; i <= len - 4; i += 4, src += cn*4 )
|
|
|
|
s0 += src[0] + src[cn] + src[cn*2] + src[cn*3];
|
|
|
|
for( ; i < len; i++, src += cn )
|
|
|
|
s0 += src[0];
|
|
|
|
dst[0] = s0;
|
|
|
|
}
|
|
|
|
else if( k == 2 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST s0 = dst[0], s1 = dst[1];
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
s0 += src[0];
|
|
|
|
s1 += src[1];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
dst[0] = s0;
|
|
|
|
dst[1] = s1;
|
|
|
|
}
|
|
|
|
else if( k == 3 )
|
|
|
|
{
|
|
|
|
ST s0 = dst[0], s1 = dst[1], s2 = dst[2];
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
s0 += src[0];
|
|
|
|
s1 += src[1];
|
|
|
|
s2 += src[2];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
dst[0] = s0;
|
|
|
|
dst[1] = s1;
|
|
|
|
dst[2] = s2;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
for( ; k < cn; k += 4 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
src = src0 + k;
|
|
|
|
ST s0 = dst[k], s1 = dst[k+1], s2 = dst[k+2], s3 = dst[k+3];
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
|
|
|
{
|
|
|
|
s0 += src[0]; s1 += src[1];
|
|
|
|
s2 += src[2]; s3 += src[3];
|
|
|
|
}
|
|
|
|
dst[k] = s0;
|
|
|
|
dst[k+1] = s1;
|
|
|
|
dst[k+2] = s2;
|
|
|
|
dst[k+3] = s3;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
return len;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
int i, nzm = 0;
|
|
|
|
if( cn == 1 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST s = dst[0];
|
|
|
|
for( i = 0; i < len; i++ )
|
|
|
|
if( mask[i] )
|
|
|
|
{
|
|
|
|
s += src[i];
|
|
|
|
nzm++;
|
|
|
|
}
|
|
|
|
dst[0] = s;
|
|
|
|
}
|
|
|
|
else if( cn == 3 )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST s0 = dst[0], s1 = dst[1], s2 = dst[2];
|
|
|
|
for( i = 0; i < len; i++, src += 3 )
|
|
|
|
if( mask[i] )
|
|
|
|
{
|
|
|
|
s0 += src[0];
|
|
|
|
s1 += src[1];
|
|
|
|
s2 += src[2];
|
|
|
|
nzm++;
|
|
|
|
}
|
|
|
|
dst[0] = s0;
|
|
|
|
dst[1] = s1;
|
|
|
|
dst[2] = s2;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
|
|
|
if( mask[i] )
|
|
|
|
{
|
|
|
|
int k = 0;
|
|
|
|
for( ; k <= cn - 4; k += 4 )
|
|
|
|
{
|
|
|
|
ST s0, s1;
|
|
|
|
s0 = dst[k] + src[k];
|
|
|
|
s1 = dst[k+1] + src[k+1];
|
|
|
|
dst[k] = s0; dst[k+1] = s1;
|
|
|
|
s0 = dst[k+2] + src[k+2];
|
|
|
|
s1 = dst[k+3] + src[k+3];
|
|
|
|
dst[k+2] = s0; dst[k+3] = s1;
|
|
|
|
}
|
|
|
|
for( ; k < cn; k++ )
|
|
|
|
dst[k] += src[k];
|
|
|
|
nzm++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nzm;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
static int sum8u( const uchar* src, const uchar* mask, int* dst, int len, int cn )
|
|
|
|
{ return sum_(src, mask, dst, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sum8s( const schar* src, const uchar* mask, int* dst, int len, int cn )
|
|
|
|
{ return sum_(src, mask, dst, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sum16u( const ushort* src, const uchar* mask, int* dst, int len, int cn )
|
|
|
|
{ return sum_(src, mask, dst, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sum16s( const short* src, const uchar* mask, int* dst, int len, int cn )
|
|
|
|
{ return sum_(src, mask, dst, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sum32s( const int* src, const uchar* mask, double* dst, int len, int cn )
|
|
|
|
{ return sum_(src, mask, dst, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sum32f( const float* src, const uchar* mask, double* dst, int len, int cn )
|
|
|
|
{ return sum_(src, mask, dst, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sum64f( const double* src, const uchar* mask, double* dst, int len, int cn )
|
|
|
|
{ return sum_(src, mask, dst, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
typedef int (*SumFunc)(const uchar*, const uchar* mask, uchar*, int, int);
|
|
|
|
|
|
|
|
static SumFunc sumTab[] =
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
(SumFunc)sum8u, (SumFunc)sum8s, (SumFunc)sum16u, (SumFunc)sum16s,
|
|
|
|
(SumFunc)sum32s, (SumFunc)sum32f, (SumFunc)sum64f, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static int countNonZero_(const T* src, int len )
|
|
|
|
{
|
|
|
|
int i, nz = 0;
|
|
|
|
for( i = 0; i <= len - 4; i += 4 )
|
|
|
|
nz += (src[i] != 0) + (src[i+1] != 0) + (src[i+2] != 0) + (src[i+3] != 0);
|
|
|
|
for( ; i < len; i++ )
|
|
|
|
nz += src[i] != 0;
|
|
|
|
return nz;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int countNonZero8u( const uchar* src, int len )
|
|
|
|
{ return countNonZero_(src, len); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int countNonZero16u( const ushort* src, int len )
|
|
|
|
{ return countNonZero_(src, len); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int countNonZero32s( const int* src, int len )
|
|
|
|
{ return countNonZero_(src, len); }
|
|
|
|
|
|
|
|
static int countNonZero32f( const float* src, int len )
|
|
|
|
{ return countNonZero_(src, len); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int countNonZero64f( const double* src, int len )
|
|
|
|
{ return countNonZero_(src, len); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
typedef int (*CountNonZeroFunc)(const uchar*, int);
|
|
|
|
|
|
|
|
static CountNonZeroFunc countNonZeroTab[] =
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
(CountNonZeroFunc)countNonZero8u, (CountNonZeroFunc)countNonZero8u,
|
|
|
|
(CountNonZeroFunc)countNonZero16u, (CountNonZeroFunc)countNonZero16u,
|
|
|
|
(CountNonZeroFunc)countNonZero32s, (CountNonZeroFunc)countNonZero32f,
|
|
|
|
(CountNonZeroFunc)countNonZero64f, 0
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
template<typename T, typename ST, typename SQT>
|
|
|
|
static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
const T* src = src0;
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( !mask )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
int i;
|
|
|
|
int k = cn % 4;
|
|
|
|
|
|
|
|
if( k == 1 )
|
|
|
|
{
|
|
|
|
ST s0 = sum[0];
|
|
|
|
SQT sq0 = sqsum[0];
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
|
|
|
{
|
|
|
|
T v = src[0];
|
|
|
|
s0 += v; sq0 += (SQT)v*v;
|
|
|
|
}
|
|
|
|
sum[0] = s0;
|
|
|
|
sqsum[0] = sq0;
|
|
|
|
}
|
|
|
|
else if( k == 2 )
|
|
|
|
{
|
|
|
|
ST s0 = sum[0], s1 = sum[1];
|
|
|
|
SQT sq0 = sqsum[0], sq1 = sqsum[1];
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
|
|
|
{
|
|
|
|
T v0 = src[0], v1 = src[1];
|
|
|
|
s0 += v0; sq0 += (SQT)v0*v0;
|
|
|
|
s1 += v1; sq1 += (SQT)v1*v1;
|
|
|
|
}
|
|
|
|
sum[0] = s0; sum[1] = s1;
|
|
|
|
sqsum[0] = sq0; sqsum[1] = sq1;
|
|
|
|
}
|
|
|
|
else if( k == 3 )
|
|
|
|
{
|
|
|
|
ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
|
|
|
|
SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
|
|
|
{
|
|
|
|
T v0 = src[0], v1 = src[1], v2 = src[2];
|
|
|
|
s0 += v0; sq0 += (SQT)v0*v0;
|
|
|
|
s1 += v1; sq1 += (SQT)v1*v1;
|
|
|
|
s2 += v2; sq2 += (SQT)v2*v2;
|
|
|
|
}
|
|
|
|
sum[0] = s0; sum[1] = s1; sum[2] = s2;
|
|
|
|
sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( ; k < cn; k += 4 )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
src = src0 + k;
|
|
|
|
ST s0 = sum[k], s1 = sum[k+1], s2 = sum[k+2], s3 = sum[k+3];
|
|
|
|
SQT sq0 = sqsum[k], sq1 = sqsum[k+1], sq2 = sqsum[k+2], sq3 = sqsum[k+3];
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
|
|
|
{
|
|
|
|
T v0, v1;
|
|
|
|
v0 = src[0], v1 = src[1];
|
|
|
|
s0 += v0; sq0 += (SQT)v0*v0;
|
|
|
|
s1 += v1; sq1 += (SQT)v1*v1;
|
|
|
|
v0 = src[2], v1 = src[3];
|
|
|
|
s2 += v0; sq2 += (SQT)v0*v0;
|
|
|
|
s3 += v1; sq3 += (SQT)v1*v1;
|
|
|
|
}
|
|
|
|
sum[k] = s0; sum[k+1] = s1;
|
|
|
|
sum[k+2] = s2; sum[k+3] = s3;
|
|
|
|
sqsum[k] = sq0; sqsum[k+1] = sq1;
|
|
|
|
sqsum[k+2] = sq2; sqsum[k+3] = sq3;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
return len;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
int i, nzm = 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( cn == 1 )
|
|
|
|
{
|
|
|
|
ST s0 = sum[0];
|
|
|
|
SQT sq0 = sqsum[0];
|
|
|
|
for( i = 0; i < len; i++ )
|
|
|
|
if( mask[i] )
|
|
|
|
{
|
|
|
|
T v = src[i];
|
|
|
|
s0 += v; sq0 += (SQT)v*v;
|
|
|
|
nzm++;
|
|
|
|
}
|
|
|
|
sum[0] = s0;
|
|
|
|
sqsum[0] = sq0;
|
|
|
|
}
|
|
|
|
else if( cn == 3 )
|
|
|
|
{
|
|
|
|
ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
|
|
|
|
SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
|
|
|
|
for( i = 0; i < len; i++, src += 3 )
|
|
|
|
if( mask[i] )
|
|
|
|
{
|
|
|
|
T v0 = src[0], v1 = src[1], v2 = src[2];
|
|
|
|
s0 += v0; sq0 += (SQT)v0*v0;
|
|
|
|
s1 += v1; sq1 += (SQT)v1*v1;
|
|
|
|
s2 += v2; sq2 += (SQT)v2*v2;
|
|
|
|
nzm++;
|
|
|
|
}
|
|
|
|
sum[0] = s0; sum[1] = s1; sum[2] = s2;
|
|
|
|
sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( i = 0; i < len; i++, src += cn )
|
|
|
|
if( mask[i] )
|
|
|
|
{
|
|
|
|
for( int k = 0; k < cn; k++ )
|
|
|
|
{
|
|
|
|
T v = src[k];
|
|
|
|
ST s = sum[k] + v;
|
|
|
|
SQT sq = sqsum[k] + (SQT)v*v;
|
|
|
|
sum[k] = s; sqsum[k] = sq;
|
|
|
|
}
|
|
|
|
nzm++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nzm;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
|
|
|
|
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sqsum8s( const schar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
|
|
|
|
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sqsum16u( const ushort* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
|
|
|
|
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sqsum16s( const short* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
|
|
|
|
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sqsum32s( const int* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
|
|
|
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sqsum32f( const float* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
|
|
|
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static int sqsum64f( const double* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
|
|
|
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int);
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static SumSqrFunc sumSqrTab[] =
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
(SumSqrFunc)sqsum8u, (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s,
|
|
|
|
(SumSqrFunc)sqsum32s, (SumSqrFunc)sqsum32f, (SumSqrFunc)sqsum64f, 0
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
cv::Scalar cv::sum( InputArray _src )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
Mat src = _src.getMat();
|
|
|
|
int k, cn = src.channels(), depth = src.depth();
|
|
|
|
SumFunc func = sumTab[depth];
|
|
|
|
|
|
|
|
CV_Assert( cn <= 4 && func != 0 );
|
|
|
|
|
|
|
|
const Mat* arrays[] = {&src, 0};
|
|
|
|
uchar* ptrs[1];
|
|
|
|
NAryMatIterator it(arrays, ptrs);
|
|
|
|
Scalar s;
|
|
|
|
int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
|
|
|
|
int j, count = 0;
|
|
|
|
AutoBuffer<int> _buf;
|
|
|
|
int* buf = (int*)&s[0];
|
|
|
|
size_t esz = 0;
|
|
|
|
bool blockSum = depth < CV_32S;
|
|
|
|
|
|
|
|
if( blockSum )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15);
|
|
|
|
blockSize = std::min(blockSize, intSumBlockSize);
|
|
|
|
_buf.allocate(cn);
|
|
|
|
buf = _buf;
|
|
|
|
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
buf[k] = 0;
|
|
|
|
esz = src.elemSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
|
|
|
{
|
|
|
|
for( j = 0; j < total; j += blockSize )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
int bsz = std::min(total - j, blockSize);
|
|
|
|
func( ptrs[0], 0, (uchar*)buf, bsz, cn );
|
|
|
|
count += bsz;
|
|
|
|
if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
|
|
|
|
{
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
{
|
|
|
|
s[k] += buf[k];
|
|
|
|
buf[k] = 0;
|
|
|
|
}
|
|
|
|
count = 0;
|
|
|
|
}
|
|
|
|
ptrs[0] += bsz*esz;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
return s;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
int cv::countNonZero( InputArray _src )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
Mat src = _src.getMat();
|
|
|
|
CountNonZeroFunc func = countNonZeroTab[src.depth()];
|
|
|
|
|
|
|
|
CV_Assert( src.channels() == 1 && func != 0 );
|
|
|
|
|
|
|
|
const Mat* arrays[] = {&src, 0};
|
|
|
|
uchar* ptrs[1];
|
|
|
|
NAryMatIterator it(arrays, ptrs);
|
|
|
|
int total = (int)it.size, nz = 0;
|
|
|
|
|
|
|
|
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
|
|
|
nz += func( ptrs[0], total );
|
|
|
|
|
|
|
|
return nz;
|
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
cv::Scalar cv::mean( InputArray _src, InputArray _mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src = _src.getMat(), mask = _mask.getMat();
|
2011-06-14 20:03:34 +08:00
|
|
|
CV_Assert( mask.empty() || mask.type() == CV_8U );
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
int k, cn = src.channels(), depth = src.depth();
|
|
|
|
SumFunc func = sumTab[depth];
|
|
|
|
|
|
|
|
CV_Assert( cn <= 4 && func != 0 );
|
|
|
|
|
|
|
|
const Mat* arrays[] = {&src, &mask, 0};
|
|
|
|
uchar* ptrs[2];
|
|
|
|
NAryMatIterator it(arrays, ptrs);
|
|
|
|
Scalar s;
|
|
|
|
int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
|
|
|
|
int j, count = 0;
|
|
|
|
AutoBuffer<int> _buf;
|
|
|
|
int* buf = (int*)&s[0];
|
|
|
|
bool blockSum = depth <= CV_16S;
|
|
|
|
size_t esz = 0, nz0 = 0;
|
|
|
|
|
|
|
|
if( blockSum )
|
|
|
|
{
|
|
|
|
intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15);
|
|
|
|
blockSize = std::min(blockSize, intSumBlockSize);
|
|
|
|
_buf.allocate(cn);
|
|
|
|
buf = _buf;
|
|
|
|
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
buf[k] = 0;
|
|
|
|
esz = src.elemSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( j = 0; j < total; j += blockSize )
|
|
|
|
{
|
|
|
|
int bsz = std::min(total - j, blockSize);
|
|
|
|
int nz = func( ptrs[0], ptrs[1], (uchar*)buf, bsz, cn );
|
|
|
|
count += nz;
|
|
|
|
nz0 += nz;
|
|
|
|
if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
{
|
|
|
|
s[k] += buf[k];
|
|
|
|
buf[k] = 0;
|
|
|
|
}
|
|
|
|
count = 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
ptrs[0] += bsz*esz;
|
|
|
|
if( ptrs[1] )
|
|
|
|
ptrs[1] += bsz;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
return s*(nz0 ? 1./nz0 : 0);
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src = _src.getMat(), mask = _mask.getMat();
|
2011-06-14 20:03:34 +08:00
|
|
|
CV_Assert( mask.empty() || mask.type() == CV_8U );
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
int k, cn = src.channels(), depth = src.depth();
|
|
|
|
SumSqrFunc func = sumSqrTab[depth];
|
|
|
|
|
|
|
|
CV_Assert( func != 0 );
|
|
|
|
|
|
|
|
const Mat* arrays[] = {&src, &mask, 0};
|
|
|
|
uchar* ptrs[2];
|
|
|
|
NAryMatIterator it(arrays, ptrs);
|
2011-05-17 23:44:01 +08:00
|
|
|
int total = (int)it.size, blockSize = total, intSumBlockSize = 0;
|
2011-04-17 21:14:45 +08:00
|
|
|
int j, count = 0, nz0 = 0;
|
|
|
|
AutoBuffer<double> _buf(cn*4);
|
|
|
|
double *s = (double*)_buf, *sq = s + cn;
|
|
|
|
int *sbuf = (int*)s, *sqbuf = (int*)sq;
|
|
|
|
bool blockSum = depth <= CV_16S, blockSqSum = depth <= CV_8S;
|
|
|
|
size_t esz = 0;
|
|
|
|
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
s[k] = sq[k] = 0;
|
|
|
|
|
|
|
|
if( blockSum )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
intSumBlockSize = 1 << 15;
|
|
|
|
blockSize = std::min(blockSize, intSumBlockSize);
|
|
|
|
sbuf = (int*)(sq + cn);
|
|
|
|
if( blockSqSum )
|
|
|
|
sqbuf = sbuf + cn;
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
sbuf[k] = sqbuf[k] = 0;
|
|
|
|
esz = src.elemSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( j = 0; j < total; j += blockSize )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
int bsz = std::min(total - j, blockSize);
|
|
|
|
int nz = func( ptrs[0], ptrs[1], (uchar*)sbuf, (uchar*)sqbuf, bsz, cn );
|
|
|
|
count += nz;
|
|
|
|
nz0 += nz;
|
|
|
|
if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
|
|
|
|
{
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
{
|
|
|
|
s[k] += sbuf[k];
|
|
|
|
sbuf[k] = 0;
|
|
|
|
}
|
|
|
|
if( blockSqSum )
|
|
|
|
{
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
{
|
|
|
|
sq[k] += sqbuf[k];
|
|
|
|
sqbuf[k] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count = 0;
|
|
|
|
}
|
|
|
|
ptrs[0] += bsz*esz;
|
|
|
|
if( ptrs[1] )
|
|
|
|
ptrs[1] += bsz;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2011-02-10 04:55:11 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
double scale = nz0 ? 1./nz0 : 0.;
|
2011-07-19 20:27:07 +08:00
|
|
|
for( k = 0; k < cn; k++ )
|
2011-02-10 04:55:11 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
s[k] *= scale;
|
|
|
|
sq[k] = std::sqrt(std::max(sq[k]*scale - s[k]*s[k], 0.));
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( j = 0; j < 2; j++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
const double* sptr = j == 0 ? s : sq;
|
2011-06-06 22:51:27 +08:00
|
|
|
_OutputArray _dst = j == 0 ? _mean : _sdv;
|
2011-04-17 21:14:45 +08:00
|
|
|
if( !_dst.needed() )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( !_dst.fixedSize() )
|
|
|
|
_dst.create(cn, 1, CV_64F, -1, true);
|
|
|
|
Mat dst = _dst.getMat();
|
|
|
|
int dcn = (int)dst.total();
|
|
|
|
CV_Assert( dst.type() == CV_64F && dst.isContinuous() &&
|
|
|
|
(dst.cols == 1 || dst.rows == 1) && dcn >= cn );
|
|
|
|
double* dptr = dst.ptr<double>();
|
|
|
|
for( k = 0; k < cn; k++ )
|
|
|
|
dptr[k] = sptr[k];
|
|
|
|
for( ; k < dcn; k++ )
|
|
|
|
dptr[k] = 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************************\
|
|
|
|
* minMaxLoc *
|
|
|
|
\****************************************************************************************/
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
namespace cv
|
|
|
|
{
|
|
|
|
|
2011-02-10 04:55:11 +08:00
|
|
|
template<typename T, typename WT> static void
|
2011-04-17 21:14:45 +08:00
|
|
|
minMaxIdx_( const T* src, const uchar* mask, WT* _minVal, WT* _maxVal,
|
|
|
|
size_t* _minIdx, size_t* _maxIdx, int len, size_t startIdx )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
WT minVal = *_minVal, maxVal = *_maxVal;
|
2011-02-10 04:55:11 +08:00
|
|
|
size_t minIdx = *_minIdx, maxIdx = *_maxIdx;
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
if( !mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int i = 0; i < len; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
T val = src[i];
|
2011-02-10 04:55:11 +08:00
|
|
|
if( val < minVal )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-02-10 04:55:11 +08:00
|
|
|
minVal = val;
|
2011-04-17 21:14:45 +08:00
|
|
|
minIdx = startIdx + i;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-02-10 04:55:11 +08:00
|
|
|
if( val > maxVal )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-02-10 04:55:11 +08:00
|
|
|
maxVal = val;
|
2011-04-17 21:14:45 +08:00
|
|
|
maxIdx = startIdx + i;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
else
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int i = 0; i < len; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
T val = src[i];
|
|
|
|
if( mask[i] && val < minVal )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-02-10 04:55:11 +08:00
|
|
|
minVal = val;
|
2011-04-17 21:14:45 +08:00
|
|
|
minIdx = startIdx + i;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
if( mask[i] && val > maxVal )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-02-10 04:55:11 +08:00
|
|
|
maxVal = val;
|
2011-04-17 21:14:45 +08:00
|
|
|
maxIdx = startIdx + i;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-10 04:55:11 +08:00
|
|
|
*_minIdx = minIdx;
|
|
|
|
*_maxIdx = maxIdx;
|
|
|
|
*_minVal = minVal;
|
|
|
|
*_maxVal = maxVal;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static void minMaxIdx_8u(const uchar* src, const uchar* mask, int* minval, int* maxval,
|
|
|
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
|
|
|
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static void minMaxIdx_8s(const schar* src, const uchar* mask, int* minval, int* maxval,
|
|
|
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
|
|
|
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static void minMaxIdx_16u(const ushort* src, const uchar* mask, int* minval, int* maxval,
|
|
|
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
|
|
|
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static void minMaxIdx_16s(const short* src, const uchar* mask, int* minval, int* maxval,
|
|
|
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
|
|
|
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static void minMaxIdx_32s(const int* src, const uchar* mask, int* minval, int* maxval,
|
|
|
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
|
|
|
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static void minMaxIdx_32f(const float* src, const uchar* mask, float* minval, float* maxval,
|
|
|
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
|
|
|
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static void minMaxIdx_64f(const double* src, const uchar* mask, double* minval, double* maxval,
|
|
|
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
|
|
|
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
2011-02-10 04:55:11 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
typedef void (*MinMaxIdxFunc)(const uchar*, const uchar*, int*, int*, size_t*, size_t*, int, size_t);
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static MinMaxIdxFunc minmaxTab[] =
|
|
|
|
{
|
|
|
|
(MinMaxIdxFunc)minMaxIdx_8u, (MinMaxIdxFunc)minMaxIdx_8s, (MinMaxIdxFunc)minMaxIdx_16u,
|
|
|
|
(MinMaxIdxFunc)minMaxIdx_16s, (MinMaxIdxFunc)minMaxIdx_32s, (MinMaxIdxFunc)minMaxIdx_32f,
|
|
|
|
(MinMaxIdxFunc)minMaxIdx_64f, 0
|
|
|
|
};
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
static void ofs2idx(const Mat& a, size_t ofs, int* idx)
|
|
|
|
{
|
|
|
|
int i, d = a.dims;
|
2011-02-10 04:55:11 +08:00
|
|
|
if( ofs > 0 )
|
|
|
|
{
|
|
|
|
ofs--;
|
|
|
|
for( i = d-1; i >= 0; i-- )
|
|
|
|
{
|
|
|
|
int sz = a.size[i];
|
|
|
|
idx[i] = (int)(ofs % sz);
|
|
|
|
ofs /= sz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-02-10 04:55:11 +08:00
|
|
|
for( i = d-1; i >= 0; i-- )
|
|
|
|
idx[i] = -1;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::minMaxIdx(InputArray _src, double* minVal,
|
2011-04-17 21:14:45 +08:00
|
|
|
double* maxVal, int* minIdx, int* maxIdx,
|
2011-06-06 22:51:27 +08:00
|
|
|
InputArray _mask)
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src = _src.getMat(), mask = _mask.getMat();
|
2011-08-02 20:55:05 +08:00
|
|
|
int depth = src.depth(), cn = src.channels();
|
2011-04-17 21:14:45 +08:00
|
|
|
|
2011-08-02 20:55:05 +08:00
|
|
|
CV_Assert( (cn == 1 && (mask.empty() || mask.type() == CV_8U)) ||
|
|
|
|
(cn >= 1 && mask.empty() && !minIdx && !maxIdx) );
|
2011-04-17 21:14:45 +08:00
|
|
|
MinMaxIdxFunc func = minmaxTab[depth];
|
|
|
|
CV_Assert( func != 0 );
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
const Mat* arrays[] = {&src, &mask, 0};
|
|
|
|
uchar* ptrs[2];
|
|
|
|
NAryMatIterator it(arrays, ptrs);
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-02-10 04:55:11 +08:00
|
|
|
size_t minidx = 0, maxidx = 0;
|
2011-04-17 21:14:45 +08:00
|
|
|
int iminval = INT_MAX, imaxval = INT_MIN;
|
|
|
|
float fminval = FLT_MAX, fmaxval = -FLT_MAX;
|
|
|
|
double dminval = DBL_MAX, dmaxval = -DBL_MAX;
|
|
|
|
size_t startidx = 1;
|
|
|
|
int *minval = &iminval, *maxval = &imaxval;
|
2011-08-02 20:55:05 +08:00
|
|
|
int planeSize = (int)it.size*cn;
|
2011-02-10 04:55:11 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( depth == CV_32F )
|
|
|
|
minval = (int*)&fminval, maxval = (int*)&fmaxval;
|
|
|
|
else if( depth == CV_64F )
|
|
|
|
minval = (int*)&dminval, maxval = (int*)&dmaxval;
|
2011-02-10 04:55:11 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( size_t i = 0; i < it.nplanes; i++, ++it, startidx += planeSize )
|
|
|
|
func( ptrs[0], ptrs[1], minval, maxval, &minidx, &maxidx, planeSize, startidx );
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-02-10 04:55:11 +08:00
|
|
|
if( minidx == 0 )
|
2011-04-17 21:14:45 +08:00
|
|
|
dminval = dmaxval = 0;
|
|
|
|
else if( depth == CV_32F )
|
|
|
|
dminval = fminval, dmaxval = fmaxval;
|
|
|
|
else if( depth <= CV_32S )
|
|
|
|
dminval = iminval, dmaxval = imaxval;
|
2011-02-10 04:55:11 +08:00
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( minVal )
|
2011-04-17 21:14:45 +08:00
|
|
|
*minVal = dminval;
|
2010-10-12 20:31:40 +08:00
|
|
|
if( maxVal )
|
2011-04-17 21:14:45 +08:00
|
|
|
*maxVal = dmaxval;
|
|
|
|
|
2010-10-12 20:31:40 +08:00
|
|
|
if( minIdx )
|
2011-04-17 21:14:45 +08:00
|
|
|
ofs2idx(src, minidx, minIdx);
|
2010-10-12 20:31:40 +08:00
|
|
|
if( maxIdx )
|
2011-04-17 21:14:45 +08:00
|
|
|
ofs2idx(src, maxidx, maxIdx);
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
void cv::minMaxLoc( InputArray _img, double* minVal, double* maxVal,
|
|
|
|
Point* minLoc, Point* maxLoc, InputArray mask )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
Mat img = _img.getMat();
|
|
|
|
CV_Assert(img.dims <= 2);
|
|
|
|
|
|
|
|
minMaxIdx(_img, minVal, maxVal, (int*)minLoc, (int*)maxLoc, mask);
|
|
|
|
if( minLoc )
|
|
|
|
std::swap(minLoc->x, minLoc->y);
|
|
|
|
if( maxLoc )
|
|
|
|
std::swap(maxLoc->x, maxLoc->y);
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* norm *
|
|
|
|
\****************************************************************************************/
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
namespace cv
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
template<typename T, typename ST> int
|
|
|
|
normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST result = *_result;
|
|
|
|
if( !mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
len *= cn;
|
|
|
|
for( int i = 0; i < len; i++ )
|
2011-04-23 05:35:46 +08:00
|
|
|
result = std::max(result, ST(std::abs(src[i])));
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( int i = 0; i < len; i++, src += cn )
|
|
|
|
if( mask[i] )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int k = 0; k < cn; k++ )
|
2011-04-23 05:35:46 +08:00
|
|
|
result = std::max(result, ST(std::abs(src[k])));
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
*_result = result;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename ST> int
|
|
|
|
normL1_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
|
|
|
{
|
|
|
|
ST result = *_result;
|
|
|
|
if( !mask )
|
|
|
|
{
|
|
|
|
len *= cn;
|
|
|
|
for( int i = 0; i < len; i++ )
|
|
|
|
result += std::abs(src[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( int i = 0; i < len; i++, src += cn )
|
|
|
|
if( mask[i] )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int k = 0; k < cn; k++ )
|
|
|
|
result += std::abs(src[k]);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
*_result = result;
|
|
|
|
return 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
template<typename T, typename ST> int
|
|
|
|
normL2_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST result = *_result;
|
|
|
|
if( !mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
len *= cn;
|
|
|
|
for( int i = 0; i < len; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
T v = src[i];
|
|
|
|
result += (ST)v*v;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
else
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int i = 0; i < len; i++, src += cn )
|
|
|
|
if( mask[i] )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int k = 0; k < cn; k++ )
|
2011-02-10 04:55:11 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
T v = src[k];
|
|
|
|
result += (ST)v*v;
|
2011-02-10 04:55:11 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
*_result = result;
|
|
|
|
return 0;
|
|
|
|
}
|
2011-02-10 04:55:11 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
template<typename T, typename ST> int
|
|
|
|
normDiffInf_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn)
|
|
|
|
{
|
|
|
|
ST result = *_result;
|
|
|
|
if( !mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
len *= cn;
|
|
|
|
for( int i = 0; i < len; i++ )
|
2011-06-10 14:53:34 +08:00
|
|
|
result = std::max(result, (ST)std::abs(src1[i] - src2[i]));
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
|
|
|
|
if( mask[i] )
|
2011-02-10 04:55:11 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int k = 0; k < cn; k++ )
|
2011-06-10 14:53:34 +08:00
|
|
|
result = std::max(result, (ST)std::abs(src1[k] - src2[k]));
|
2011-02-10 04:55:11 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
*_result = result;
|
|
|
|
return 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
template<typename T, typename ST> int
|
|
|
|
normDiffL1_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST result = *_result;
|
|
|
|
if( !mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
len *= cn;
|
|
|
|
for( int i = 0; i < len; i++ )
|
|
|
|
result += std::abs(src1[i] - src2[i]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
|
|
|
|
if( mask[i] )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int k = 0; k < cn; k++ )
|
|
|
|
result += std::abs(src1[k] - src2[k]);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
*_result = result;
|
|
|
|
return 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
template<typename T, typename ST> int
|
|
|
|
normDiffL2_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST result = *_result;
|
|
|
|
if( !mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
len *= cn;
|
|
|
|
for( int i = 0; i < len; i++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST v = src1[i] - src2[i];
|
|
|
|
result += v*v;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
else
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
|
|
|
|
if( mask[i] )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( int k = 0; k < cn; k++ )
|
2011-02-10 04:55:11 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
ST v = src1[k] - src2[k];
|
|
|
|
result += v*v;
|
2011-02-10 04:55:11 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
*_result = result;
|
|
|
|
return 0;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
#define CV_DEF_NORM_FUNC(L, suffix, type, ntype) \
|
2011-05-17 23:44:01 +08:00
|
|
|
static int norm##L##_##suffix(const type* src, const uchar* mask, ntype* r, int len, int cn) \
|
2011-04-17 21:14:45 +08:00
|
|
|
{ return norm##L##_(src, mask, r, len, cn); } \
|
|
|
|
static int normDiff##L##_##suffix(const type* src1, const type* src2, \
|
2011-05-17 23:44:01 +08:00
|
|
|
const uchar* mask, ntype* r, int len, int cn) \
|
|
|
|
{ return normDiff##L##_(src1, src2, mask, r, (int)len, cn); }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
#define CV_DEF_NORM_ALL(suffix, type, inftype, l1type, l2type) \
|
|
|
|
CV_DEF_NORM_FUNC(Inf, suffix, type, inftype) \
|
|
|
|
CV_DEF_NORM_FUNC(L1, suffix, type, l1type) \
|
|
|
|
CV_DEF_NORM_FUNC(L2, suffix, type, l2type)
|
|
|
|
|
|
|
|
CV_DEF_NORM_ALL(8u, uchar, int, int, int)
|
|
|
|
CV_DEF_NORM_ALL(8s, schar, int, int, int)
|
|
|
|
CV_DEF_NORM_ALL(16u, ushort, int, int, double)
|
|
|
|
CV_DEF_NORM_ALL(16s, short, int, int, double)
|
|
|
|
CV_DEF_NORM_ALL(32s, int, int, double, double)
|
|
|
|
CV_DEF_NORM_ALL(32f, float, float, double, double)
|
|
|
|
CV_DEF_NORM_ALL(64f, double, double, double, double)
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
typedef int (*NormFunc)(const uchar*, const uchar*, uchar*, int, int);
|
|
|
|
typedef int (*NormDiffFunc)(const uchar*, const uchar*, const uchar*, uchar*, int, int);
|
|
|
|
|
|
|
|
static NormFunc normTab[3][8] =
|
|
|
|
{
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
(NormFunc)normInf_8u, (NormFunc)normInf_8s, (NormFunc)normInf_16u, (NormFunc)normInf_16s,
|
|
|
|
(NormFunc)normInf_32s, (NormFunc)normInf_32f, (NormFunc)normInf_64f, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
(NormFunc)normL1_8u, (NormFunc)normL1_8s, (NormFunc)normL1_16u, (NormFunc)normL1_16s,
|
|
|
|
(NormFunc)normL1_32s, (NormFunc)normL1_32f, (NormFunc)normL1_64f, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
(NormFunc)normL2_8u, (NormFunc)normL2_8s, (NormFunc)normL2_16u, (NormFunc)normL2_16s,
|
|
|
|
(NormFunc)normL2_32s, (NormFunc)normL2_32f, (NormFunc)normL2_64f, 0
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
static NormDiffFunc normDiffTab[3][8] =
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
(NormDiffFunc)normDiffInf_8u, (NormDiffFunc)normDiffInf_8s,
|
|
|
|
(NormDiffFunc)normDiffInf_16u, (NormDiffFunc)normDiffInf_16s,
|
|
|
|
(NormDiffFunc)normDiffInf_32s, (NormDiffFunc)normDiffInf_32f,
|
|
|
|
(NormDiffFunc)normDiffInf_64f, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
(NormDiffFunc)normDiffL1_8u, (NormDiffFunc)normDiffL1_8s,
|
|
|
|
(NormDiffFunc)normDiffL1_16u, (NormDiffFunc)normDiffL1_16s,
|
|
|
|
(NormDiffFunc)normDiffL1_32s, (NormDiffFunc)normDiffL1_32f,
|
|
|
|
(NormDiffFunc)normDiffL1_64f, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
(NormDiffFunc)normDiffL2_8u, (NormDiffFunc)normDiffL2_8s,
|
|
|
|
(NormDiffFunc)normDiffL2_16u, (NormDiffFunc)normDiffL2_16s,
|
|
|
|
(NormDiffFunc)normDiffL2_32s, (NormDiffFunc)normDiffL2_32f,
|
|
|
|
(NormDiffFunc)normDiffL2_64f, 0
|
|
|
|
}
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
}
|
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
double cv::norm( InputArray _src, int normType, InputArray _mask )
|
2011-04-17 21:14:45 +08:00
|
|
|
{
|
|
|
|
Mat src = _src.getMat(), mask = _mask.getMat();
|
|
|
|
int depth = src.depth(), cn = src.channels();
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
normType &= 7;
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( depth == CV_32F && src.isContinuous() && mask.empty() )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
size_t len = src.total()*cn;
|
|
|
|
if( len == (size_t)(int)len )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
const float* data = src.ptr<float>();
|
|
|
|
|
|
|
|
if( normType == NORM_L2 )
|
|
|
|
{
|
|
|
|
double result = 0;
|
|
|
|
normL2_32f(data, 0, &result, (int)len, 1);
|
|
|
|
return std::sqrt(result);
|
|
|
|
}
|
|
|
|
if( normType == NORM_L1 )
|
|
|
|
{
|
|
|
|
double result = 0;
|
|
|
|
normL1_32f(data, 0, &result, (int)len, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
float result = 0;
|
|
|
|
normInf_32f(data, 0, &result, (int)len, 1);
|
|
|
|
return result;
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( mask.empty() || mask.type() == CV_8U );
|
|
|
|
|
|
|
|
NormFunc func = normTab[normType >> 1][depth];
|
|
|
|
CV_Assert( func != 0 );
|
|
|
|
|
|
|
|
const Mat* arrays[] = {&src, &mask, 0};
|
|
|
|
uchar* ptrs[2];
|
2011-06-14 20:03:34 +08:00
|
|
|
union
|
|
|
|
{
|
|
|
|
double d;
|
|
|
|
int i;
|
|
|
|
float f;
|
|
|
|
}
|
|
|
|
result;
|
|
|
|
result.d = 0;
|
2011-04-17 21:14:45 +08:00
|
|
|
NAryMatIterator it(arrays, ptrs);
|
|
|
|
int j, total = (int)it.size, blockSize = total, intSumBlockSize = 0, count = 0;
|
|
|
|
bool blockSum = (normType == NORM_L1 && depth <= CV_16S) ||
|
|
|
|
(normType == NORM_L2 && depth <= CV_8S);
|
|
|
|
int isum = 0;
|
2011-06-14 20:03:34 +08:00
|
|
|
int *ibuf = &result.i;
|
2011-04-17 21:14:45 +08:00
|
|
|
size_t esz = 0;
|
|
|
|
|
|
|
|
if( blockSum )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
|
|
|
|
blockSize = std::min(blockSize, intSumBlockSize);
|
|
|
|
ibuf = &isum;
|
|
|
|
esz = src.elemSize();
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( j = 0; j < total; j += blockSize )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
int bsz = std::min(total - j, blockSize);
|
|
|
|
func( ptrs[0], ptrs[1], (uchar*)ibuf, bsz, cn );
|
|
|
|
count += bsz;
|
|
|
|
if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
|
|
|
|
{
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d += isum;
|
2011-04-17 21:14:45 +08:00
|
|
|
isum = 0;
|
|
|
|
count = 0;
|
|
|
|
}
|
|
|
|
ptrs[0] += bsz*esz;
|
|
|
|
if( ptrs[1] )
|
|
|
|
ptrs[1] += bsz;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
if( normType == NORM_INF )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
if( depth == CV_64F )
|
|
|
|
;
|
|
|
|
else if( depth == CV_32F )
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d = result.f;
|
2011-04-17 21:14:45 +08:00
|
|
|
else
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d = result.i;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
else if( normType == NORM_L2 )
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d = std::sqrt(result.d);
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-06-14 20:03:34 +08:00
|
|
|
return result.d;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
|
2011-06-06 22:51:27 +08:00
|
|
|
double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-06-02 20:45:00 +08:00
|
|
|
if( normType & CV_RELATIVE )
|
|
|
|
return norm(_src1, _src2, normType & ~CV_RELATIVE, _mask)/(norm(_src2, normType, _mask) + DBL_EPSILON);
|
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
|
|
|
|
int depth = src1.depth(), cn = src1.channels();
|
|
|
|
|
|
|
|
CV_Assert( src1.size == src2.size && src1.type() == src2.type() );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
normType &= 7;
|
2011-04-17 21:14:45 +08:00
|
|
|
CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
if( src1.depth() == CV_32F && src1.isContinuous() && src2.isContinuous() && mask.empty() )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
size_t len = src1.total()*src1.channels();
|
|
|
|
if( len == (size_t)(int)len )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
const float* data1 = src1.ptr<float>();
|
|
|
|
const float* data2 = src2.ptr<float>();
|
|
|
|
|
|
|
|
if( normType == NORM_L2 )
|
|
|
|
{
|
|
|
|
double result = 0;
|
|
|
|
normDiffL2_32f(data1, data2, 0, &result, (int)len, 1);
|
|
|
|
return std::sqrt(result);
|
|
|
|
}
|
|
|
|
if( normType == NORM_L1 )
|
|
|
|
{
|
|
|
|
double result = 0;
|
|
|
|
normDiffL1_32f(data1, data2, 0, &result, (int)len, 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
float result = 0;
|
|
|
|
normDiffInf_32f(data1, data2, 0, &result, (int)len, 1);
|
|
|
|
return result;
|
|
|
|
}
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
CV_Assert( mask.empty() || mask.type() == CV_8U );
|
|
|
|
|
|
|
|
NormDiffFunc func = normDiffTab[normType >> 1][depth];
|
|
|
|
CV_Assert( func != 0 );
|
|
|
|
|
|
|
|
const Mat* arrays[] = {&src1, &src2, &mask, 0};
|
|
|
|
uchar* ptrs[3];
|
2011-06-14 20:03:34 +08:00
|
|
|
union
|
|
|
|
{
|
|
|
|
double d;
|
|
|
|
float f;
|
|
|
|
int i;
|
|
|
|
unsigned u;
|
|
|
|
}
|
|
|
|
result;
|
|
|
|
result.d = 0;
|
2011-04-17 21:14:45 +08:00
|
|
|
NAryMatIterator it(arrays, ptrs);
|
|
|
|
int j, total = (int)it.size, blockSize = total, intSumBlockSize = 0, count = 0;
|
|
|
|
bool blockSum = (normType == NORM_L1 && depth <= CV_16S) ||
|
|
|
|
(normType == NORM_L2 && depth <= CV_8S);
|
2011-06-14 20:03:34 +08:00
|
|
|
unsigned isum = 0;
|
|
|
|
unsigned *ibuf = &result.u;
|
2011-04-17 21:14:45 +08:00
|
|
|
size_t esz = 0;
|
|
|
|
|
|
|
|
if( blockSum )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15);
|
|
|
|
blockSize = std::min(blockSize, intSumBlockSize);
|
|
|
|
ibuf = &isum;
|
|
|
|
esz = src1.elemSize();
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-04-17 21:14:45 +08:00
|
|
|
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
for( j = 0; j < total; j += blockSize )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
int bsz = std::min(total - j, blockSize);
|
|
|
|
func( ptrs[0], ptrs[1], ptrs[2], (uchar*)ibuf, bsz, cn );
|
|
|
|
count += bsz;
|
|
|
|
if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) )
|
|
|
|
{
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d += isum;
|
2011-04-17 21:14:45 +08:00
|
|
|
isum = 0;
|
|
|
|
count = 0;
|
|
|
|
}
|
|
|
|
ptrs[0] += bsz*esz;
|
|
|
|
ptrs[1] += bsz*esz;
|
|
|
|
if( ptrs[2] )
|
|
|
|
ptrs[2] += bsz;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
|
|
|
|
if( normType == NORM_INF )
|
2010-10-12 20:31:40 +08:00
|
|
|
{
|
2011-04-17 21:14:45 +08:00
|
|
|
if( depth == CV_64F )
|
|
|
|
;
|
|
|
|
else if( depth == CV_32F )
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d = result.f;
|
2011-04-17 21:14:45 +08:00
|
|
|
else
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d = result.u;
|
2010-10-12 20:31:40 +08:00
|
|
|
}
|
2011-04-17 21:14:45 +08:00
|
|
|
else if( normType == NORM_L2 )
|
2011-06-14 20:03:34 +08:00
|
|
|
result.d = std::sqrt(result.d);
|
2010-10-12 20:31:40 +08:00
|
|
|
|
2011-06-14 20:03:34 +08:00
|
|
|
return result.d;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL CvScalar cvSum( const CvArr* srcarr )
|
|
|
|
{
|
|
|
|
cv::Scalar sum = cv::sum(cv::cvarrToMat(srcarr, false, true, 1));
|
|
|
|
if( CV_IS_IMAGE(srcarr) )
|
|
|
|
{
|
|
|
|
int coi = cvGetImageCOI((IplImage*)srcarr);
|
|
|
|
if( coi )
|
|
|
|
{
|
|
|
|
CV_Assert( 0 < coi && coi <= 4 );
|
|
|
|
sum = cv::Scalar(sum[coi-1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
CV_IMPL int cvCountNonZero( const CvArr* imgarr )
|
|
|
|
{
|
|
|
|
cv::Mat img = cv::cvarrToMat(imgarr, false, true, 1);
|
|
|
|
if( img.channels() > 1 )
|
|
|
|
cv::extractImageCOI(imgarr, img);
|
|
|
|
return countNonZero(img);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL CvScalar
|
|
|
|
cvAvg( const void* imgarr, const void* maskarr )
|
|
|
|
{
|
|
|
|
cv::Mat img = cv::cvarrToMat(imgarr, false, true, 1);
|
|
|
|
cv::Scalar mean = !maskarr ? cv::mean(img) : cv::mean(img, cv::cvarrToMat(maskarr));
|
|
|
|
if( CV_IS_IMAGE(imgarr) )
|
|
|
|
{
|
|
|
|
int coi = cvGetImageCOI((IplImage*)imgarr);
|
|
|
|
if( coi )
|
|
|
|
{
|
|
|
|
CV_Assert( 0 < coi && coi <= 4 );
|
|
|
|
mean = cv::Scalar(mean[coi-1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return mean;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL void
|
|
|
|
cvAvgSdv( const CvArr* imgarr, CvScalar* _mean, CvScalar* _sdv, const void* maskarr )
|
|
|
|
{
|
|
|
|
cv::Scalar mean, sdv;
|
|
|
|
|
|
|
|
cv::Mat mask;
|
|
|
|
if( maskarr )
|
|
|
|
mask = cv::cvarrToMat(maskarr);
|
|
|
|
|
|
|
|
cv::meanStdDev(cv::cvarrToMat(imgarr, false, true, 1), mean, sdv, mask );
|
|
|
|
|
|
|
|
if( CV_IS_IMAGE(imgarr) )
|
|
|
|
{
|
|
|
|
int coi = cvGetImageCOI((IplImage*)imgarr);
|
|
|
|
if( coi )
|
|
|
|
{
|
|
|
|
CV_Assert( 0 < coi && coi <= 4 );
|
|
|
|
mean = cv::Scalar(mean[coi-1]);
|
|
|
|
sdv = cv::Scalar(sdv[coi-1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( _mean )
|
|
|
|
*(cv::Scalar*)_mean = mean;
|
|
|
|
if( _sdv )
|
|
|
|
*(cv::Scalar*)_sdv = sdv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL void
|
|
|
|
cvMinMaxLoc( const void* imgarr, double* _minVal, double* _maxVal,
|
|
|
|
CvPoint* _minLoc, CvPoint* _maxLoc, const void* maskarr )
|
|
|
|
{
|
|
|
|
cv::Mat mask, img = cv::cvarrToMat(imgarr, false, true, 1);
|
|
|
|
if( maskarr )
|
|
|
|
mask = cv::cvarrToMat(maskarr);
|
|
|
|
if( img.channels() > 1 )
|
|
|
|
cv::extractImageCOI(imgarr, img);
|
|
|
|
|
|
|
|
cv::minMaxLoc( img, _minVal, _maxVal,
|
|
|
|
(cv::Point*)_minLoc, (cv::Point*)_maxLoc, mask );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL double
|
|
|
|
cvNorm( const void* imgA, const void* imgB, int normType, const void* maskarr )
|
|
|
|
{
|
|
|
|
cv::Mat a, mask;
|
|
|
|
if( !imgA )
|
|
|
|
{
|
|
|
|
imgA = imgB;
|
|
|
|
imgB = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = cv::cvarrToMat(imgA, false, true, 1);
|
|
|
|
if( maskarr )
|
|
|
|
mask = cv::cvarrToMat(maskarr);
|
|
|
|
|
|
|
|
if( a.channels() > 1 && CV_IS_IMAGE(imgA) && cvGetImageCOI((const IplImage*)imgA) > 0 )
|
|
|
|
cv::extractImageCOI(imgA, a);
|
|
|
|
|
|
|
|
if( !imgB )
|
|
|
|
return !maskarr ? cv::norm(a, normType) : cv::norm(a, normType, mask);
|
|
|
|
|
|
|
|
cv::Mat b = cv::cvarrToMat(imgB, false, true, 1);
|
|
|
|
if( b.channels() > 1 && CV_IS_IMAGE(imgB) && cvGetImageCOI((const IplImage*)imgB) > 0 )
|
|
|
|
cv::extractImageCOI(imgB, b);
|
|
|
|
|
|
|
|
return !maskarr ? cv::norm(a, b, normType) : cv::norm(a, b, normType, mask);
|
|
|
|
}
|