|
|
@ -48,777 +48,47 @@ |
|
|
|
#include "opencv2/core/hal/intrin.hpp" |
|
|
|
#include "opencv2/core/hal/intrin.hpp" |
|
|
|
#include <opencv2/core/utils/configuration.private.hpp> |
|
|
|
#include <opencv2/core/utils/configuration.private.hpp> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "morph.simd.hpp" |
|
|
|
|
|
|
|
#include "morph.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************************\
|
|
|
|
/****************************************************************************************\
|
|
|
|
Basic Morphological Operations: Erosion & Dilation |
|
|
|
Basic Morphological Operations: Erosion & Dilation |
|
|
|
\****************************************************************************************/ |
|
|
|
\****************************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
using namespace std; |
|
|
|
namespace cv { |
|
|
|
|
|
|
|
|
|
|
|
namespace cv |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T> struct MinOp |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef T type1; |
|
|
|
|
|
|
|
typedef T type2; |
|
|
|
|
|
|
|
typedef T rtype; |
|
|
|
|
|
|
|
T operator ()(const T a, const T b) const { return std::min(a, b); } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T> struct MaxOp |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef T type1; |
|
|
|
|
|
|
|
typedef T type2; |
|
|
|
|
|
|
|
typedef T rtype; |
|
|
|
|
|
|
|
T operator ()(const T a, const T b) const { return std::max(a, b); } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef CV_MIN_8U |
|
|
|
|
|
|
|
#undef CV_MAX_8U |
|
|
|
|
|
|
|
#define CV_MIN_8U(a,b) ((a) - CV_FAST_CAST_8U((a) - (b))) |
|
|
|
|
|
|
|
#define CV_MAX_8U(a,b) ((a) + CV_FAST_CAST_8U((b) - (a))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<> inline uchar MinOp<uchar>::operator ()(const uchar a, const uchar b) const { return CV_MIN_8U(a, b); } |
|
|
|
|
|
|
|
template<> inline uchar MaxOp<uchar>::operator ()(const uchar a, const uchar b) const { return CV_MAX_8U(a, b); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct MorphRowNoVec |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MorphRowNoVec(int, int) {} |
|
|
|
|
|
|
|
int operator()(const uchar*, uchar*, int, int) const { return 0; } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct MorphColumnNoVec |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MorphColumnNoVec(int, int) {} |
|
|
|
|
|
|
|
int operator()(const uchar**, uchar*, int, int, int) const { return 0; } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct MorphNoVec |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int operator()(uchar**, int, uchar*, int) const { return 0; } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if CV_SIMD |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class VecUpdate> struct MorphRowVec |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef typename VecUpdate::vtype vtype; |
|
|
|
|
|
|
|
typedef typename vtype::lane_type stype; |
|
|
|
|
|
|
|
MorphRowVec(int _ksize, int _anchor) : ksize(_ksize), anchor(_anchor) {} |
|
|
|
|
|
|
|
int operator()(const uchar* src, uchar* dst, int width, int cn) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i, k, _ksize = ksize*cn; |
|
|
|
|
|
|
|
width *= cn; |
|
|
|
|
|
|
|
VecUpdate updateOp; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load((const stype*)src + i); |
|
|
|
|
|
|
|
vtype s1 = vx_load((const stype*)src + i + vtype::nlanes); |
|
|
|
|
|
|
|
vtype s2 = vx_load((const stype*)src + i + 2*vtype::nlanes); |
|
|
|
|
|
|
|
vtype s3 = vx_load((const stype*)src + i + 3*vtype::nlanes); |
|
|
|
|
|
|
|
for (k = cn; k < _ksize; k += cn) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load((const stype*)src + i + k)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load((const stype*)src + i + k + vtype::nlanes)); |
|
|
|
|
|
|
|
s2 = updateOp(s2, vx_load((const stype*)src + i + k + 2*vtype::nlanes)); |
|
|
|
|
|
|
|
s3 = updateOp(s3, vx_load((const stype*)src + i + k + 3*vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
v_store((stype*)dst + i, s0); |
|
|
|
|
|
|
|
v_store((stype*)dst + i + vtype::nlanes, s1); |
|
|
|
|
|
|
|
v_store((stype*)dst + i + 2*vtype::nlanes, s2); |
|
|
|
|
|
|
|
v_store((stype*)dst + i + 3*vtype::nlanes, s3); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - 2*vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load((const stype*)src + i); |
|
|
|
|
|
|
|
vtype s1 = vx_load((const stype*)src + i + vtype::nlanes); |
|
|
|
|
|
|
|
for( k = cn; k < _ksize; k += cn ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load((const stype*)src + i + k)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load((const stype*)src + i + k + vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
v_store((stype*)dst + i, s0); |
|
|
|
|
|
|
|
v_store((stype*)dst + i + vtype::nlanes, s1); |
|
|
|
|
|
|
|
i += 2*vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s = vx_load((const stype*)src + i); |
|
|
|
|
|
|
|
for( k = cn; k < _ksize; k += cn ) |
|
|
|
|
|
|
|
s = updateOp(s, vx_load((const stype*)src + i + k)); |
|
|
|
|
|
|
|
v_store((stype*)dst + i, s); |
|
|
|
|
|
|
|
i += vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes/2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s = vx_load_low((const stype*)src + i); |
|
|
|
|
|
|
|
for( k = cn; k < _ksize; k += cn ) |
|
|
|
|
|
|
|
s = updateOp(s, vx_load_low((const stype*)src + i + k)); |
|
|
|
|
|
|
|
v_store_low((stype*)dst + i, s); |
|
|
|
|
|
|
|
i += vtype::nlanes/2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return i - i % cn; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ksize, anchor; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class VecUpdate> struct MorphColumnVec |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef typename VecUpdate::vtype vtype; |
|
|
|
|
|
|
|
typedef typename vtype::lane_type stype; |
|
|
|
|
|
|
|
MorphColumnVec(int _ksize, int _anchor) : ksize(_ksize), anchor(_anchor) {} |
|
|
|
|
|
|
|
int operator()(const uchar** _src, uchar* _dst, int dststep, int count, int width) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i = 0, k, _ksize = ksize; |
|
|
|
|
|
|
|
VecUpdate updateOp; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < count + ksize - 1; i++ ) |
|
|
|
|
|
|
|
CV_Assert( ((size_t)_src[i] & (CV_SIMD_WIDTH-1)) == 0 ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const stype** src = (const stype**)_src; |
|
|
|
|
|
|
|
stype* dst = (stype*)_dst; |
|
|
|
|
|
|
|
dststep /= sizeof(dst[0]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( ; _ksize > 1 && count > 1; count -= 2, dst += dststep*2, src += 2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const stype* sptr = src[1] + i; |
|
|
|
|
|
|
|
vtype s0 = vx_load_aligned(sptr); |
|
|
|
|
|
|
|
vtype s1 = vx_load_aligned(sptr + vtype::nlanes); |
|
|
|
|
|
|
|
vtype s2 = vx_load_aligned(sptr + 2*vtype::nlanes); |
|
|
|
|
|
|
|
vtype s3 = vx_load_aligned(sptr + 3*vtype::nlanes); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 2; k < _ksize; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_aligned(sptr)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)); |
|
|
|
|
|
|
|
s2 = updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes)); |
|
|
|
|
|
|
|
s3 = updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sptr = src[0] + i; |
|
|
|
|
|
|
|
v_store(dst + i, updateOp(s0, vx_load_aligned(sptr))); |
|
|
|
|
|
|
|
v_store(dst + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes))); |
|
|
|
|
|
|
|
v_store(dst + i + 2*vtype::nlanes, updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes))); |
|
|
|
|
|
|
|
v_store(dst + i + 3*vtype::nlanes, updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(sptr))); |
|
|
|
|
|
|
|
v_store(dst + dststep + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes))); |
|
|
|
|
|
|
|
v_store(dst + dststep + i + 2*vtype::nlanes, updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes))); |
|
|
|
|
|
|
|
v_store(dst + dststep + i + 3*vtype::nlanes, updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - 2*vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const stype* sptr = src[1] + i; |
|
|
|
|
|
|
|
vtype s0 = vx_load_aligned(sptr); |
|
|
|
|
|
|
|
vtype s1 = vx_load_aligned(sptr + vtype::nlanes); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 2; k < _ksize; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_aligned(sptr)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sptr = src[0] + i; |
|
|
|
|
|
|
|
v_store(dst + i, updateOp(s0, vx_load_aligned(sptr))); |
|
|
|
|
|
|
|
v_store(dst + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(sptr))); |
|
|
|
|
|
|
|
v_store(dst + dststep + i + vtype::nlanes, updateOp(s1, vx_load_aligned(sptr + vtype::nlanes))); |
|
|
|
|
|
|
|
i += 2*vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load_aligned(src[1] + i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 2; k < _ksize; k++ ) |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_aligned(src[k] + i)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
v_store(dst + i, updateOp(s0, vx_load_aligned(src[0] + i))); |
|
|
|
|
|
|
|
v_store(dst + dststep + i, updateOp(s0, vx_load_aligned(src[k] + i))); |
|
|
|
|
|
|
|
i += vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes/2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load_low(src[1] + i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 2; k < _ksize; k++ ) |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_low(src[k] + i)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
v_store_low(dst + i, updateOp(s0, vx_load_low(src[0] + i))); |
|
|
|
|
|
|
|
v_store_low(dst + dststep + i, updateOp(s0, vx_load_low(src[k] + i))); |
|
|
|
|
|
|
|
i += vtype::nlanes/2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( ; count > 0; count--, dst += dststep, src++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const stype* sptr = src[0] + i; |
|
|
|
|
|
|
|
vtype s0 = vx_load_aligned(sptr); |
|
|
|
|
|
|
|
vtype s1 = vx_load_aligned(sptr + vtype::nlanes); |
|
|
|
|
|
|
|
vtype s2 = vx_load_aligned(sptr + 2*vtype::nlanes); |
|
|
|
|
|
|
|
vtype s3 = vx_load_aligned(sptr + 3*vtype::nlanes); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 1; k < _ksize; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_aligned(sptr)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)); |
|
|
|
|
|
|
|
s2 = updateOp(s2, vx_load_aligned(sptr + 2*vtype::nlanes)); |
|
|
|
|
|
|
|
s3 = updateOp(s3, vx_load_aligned(sptr + 3*vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
v_store(dst + i, s0); |
|
|
|
|
|
|
|
v_store(dst + i + vtype::nlanes, s1); |
|
|
|
|
|
|
|
v_store(dst + i + 2*vtype::nlanes, s2); |
|
|
|
|
|
|
|
v_store(dst + i + 3*vtype::nlanes, s3); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - 2*vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const stype* sptr = src[0] + i; |
|
|
|
|
|
|
|
vtype s0 = vx_load_aligned(sptr); |
|
|
|
|
|
|
|
vtype s1 = vx_load_aligned(sptr + vtype::nlanes); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 1; k < _ksize; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_aligned(sptr)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load_aligned(sptr + vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
v_store(dst + i, s0); |
|
|
|
|
|
|
|
v_store(dst + i + vtype::nlanes, s1); |
|
|
|
|
|
|
|
i += 2*vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load_aligned(src[0] + i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 1; k < _ksize; k++ ) |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_aligned(src[k] + i)); |
|
|
|
|
|
|
|
v_store(dst + i, s0); |
|
|
|
|
|
|
|
i += vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes/2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load_low(src[0] + i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 1; k < _ksize; k++ ) |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_low(src[k] + i)); |
|
|
|
|
|
|
|
v_store_low(dst + i, s0); |
|
|
|
|
|
|
|
i += vtype::nlanes/2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return i; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ksize, anchor; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class VecUpdate> struct MorphVec |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef typename VecUpdate::vtype vtype; |
|
|
|
|
|
|
|
typedef typename vtype::lane_type stype; |
|
|
|
|
|
|
|
int operator()(uchar** _src, int nz, uchar* _dst, int width) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const stype** src = (const stype**)_src; |
|
|
|
|
|
|
|
stype* dst = (stype*)_dst; |
|
|
|
|
|
|
|
int i, k; |
|
|
|
|
|
|
|
VecUpdate updateOp; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( i = 0; i <= width - 4*vtype::nlanes; i += 4*vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const stype* sptr = src[0] + i; |
|
|
|
|
|
|
|
vtype s0 = vx_load(sptr); |
|
|
|
|
|
|
|
vtype s1 = vx_load(sptr + vtype::nlanes); |
|
|
|
|
|
|
|
vtype s2 = vx_load(sptr + 2*vtype::nlanes); |
|
|
|
|
|
|
|
vtype s3 = vx_load(sptr + 3*vtype::nlanes); |
|
|
|
|
|
|
|
for( k = 1; k < nz; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load(sptr)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load(sptr + vtype::nlanes)); |
|
|
|
|
|
|
|
s2 = updateOp(s2, vx_load(sptr + 2*vtype::nlanes)); |
|
|
|
|
|
|
|
s3 = updateOp(s3, vx_load(sptr + 3*vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
v_store(dst + i, s0); |
|
|
|
|
|
|
|
v_store(dst + i + vtype::nlanes, s1); |
|
|
|
|
|
|
|
v_store(dst + i + 2*vtype::nlanes, s2); |
|
|
|
|
|
|
|
v_store(dst + i + 3*vtype::nlanes, s3); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - 2*vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const stype* sptr = src[0] + i; |
|
|
|
|
|
|
|
vtype s0 = vx_load(sptr); |
|
|
|
|
|
|
|
vtype s1 = vx_load(sptr + vtype::nlanes); |
|
|
|
|
|
|
|
for( k = 1; k < nz; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load(sptr)); |
|
|
|
|
|
|
|
s1 = updateOp(s1, vx_load(sptr + vtype::nlanes)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
v_store(dst + i, s0); |
|
|
|
|
|
|
|
v_store(dst + i + vtype::nlanes, s1); |
|
|
|
|
|
|
|
i += 2*vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load(src[0] + i); |
|
|
|
|
|
|
|
for( k = 1; k < nz; k++ ) |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load(src[k] + i)); |
|
|
|
|
|
|
|
v_store(dst + i, s0); |
|
|
|
|
|
|
|
i += vtype::nlanes; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( i <= width - vtype::nlanes/2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vtype s0 = vx_load_low(src[0] + i); |
|
|
|
|
|
|
|
for( k = 1; k < nz; k++ ) |
|
|
|
|
|
|
|
s0 = updateOp(s0, vx_load_low(src[k] + i)); |
|
|
|
|
|
|
|
v_store_low(dst + i, s0); |
|
|
|
|
|
|
|
i += vtype::nlanes/2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return i; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T> struct VMin |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef T vtype; |
|
|
|
|
|
|
|
vtype operator()(const vtype& a, const vtype& b) const { return v_min(a,b); } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
template <typename T> struct VMax |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef T vtype; |
|
|
|
|
|
|
|
vtype operator()(const vtype& a, const vtype& b) const { return v_max(a,b); } |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphRowVec<VMin<v_uint8> > ErodeRowVec8u; |
|
|
|
|
|
|
|
typedef MorphRowVec<VMax<v_uint8> > DilateRowVec8u; |
|
|
|
|
|
|
|
typedef MorphRowVec<VMin<v_uint16> > ErodeRowVec16u; |
|
|
|
|
|
|
|
typedef MorphRowVec<VMax<v_uint16> > DilateRowVec16u; |
|
|
|
|
|
|
|
typedef MorphRowVec<VMin<v_int16> > ErodeRowVec16s; |
|
|
|
|
|
|
|
typedef MorphRowVec<VMax<v_int16> > DilateRowVec16s; |
|
|
|
|
|
|
|
typedef MorphRowVec<VMin<v_float32> > ErodeRowVec32f; |
|
|
|
|
|
|
|
typedef MorphRowVec<VMax<v_float32> > DilateRowVec32f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphColumnVec<VMin<v_uint8> > ErodeColumnVec8u; |
|
|
|
|
|
|
|
typedef MorphColumnVec<VMax<v_uint8> > DilateColumnVec8u; |
|
|
|
|
|
|
|
typedef MorphColumnVec<VMin<v_uint16> > ErodeColumnVec16u; |
|
|
|
|
|
|
|
typedef MorphColumnVec<VMax<v_uint16> > DilateColumnVec16u; |
|
|
|
|
|
|
|
typedef MorphColumnVec<VMin<v_int16> > ErodeColumnVec16s; |
|
|
|
|
|
|
|
typedef MorphColumnVec<VMax<v_int16> > DilateColumnVec16s; |
|
|
|
|
|
|
|
typedef MorphColumnVec<VMin<v_float32> > ErodeColumnVec32f; |
|
|
|
|
|
|
|
typedef MorphColumnVec<VMax<v_float32> > DilateColumnVec32f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphVec<VMin<v_uint8> > ErodeVec8u; |
|
|
|
|
|
|
|
typedef MorphVec<VMax<v_uint8> > DilateVec8u; |
|
|
|
|
|
|
|
typedef MorphVec<VMin<v_uint16> > ErodeVec16u; |
|
|
|
|
|
|
|
typedef MorphVec<VMax<v_uint16> > DilateVec16u; |
|
|
|
|
|
|
|
typedef MorphVec<VMin<v_int16> > ErodeVec16s; |
|
|
|
|
|
|
|
typedef MorphVec<VMax<v_int16> > DilateVec16s; |
|
|
|
|
|
|
|
typedef MorphVec<VMin<v_float32> > ErodeVec32f; |
|
|
|
|
|
|
|
typedef MorphVec<VMax<v_float32> > DilateVec32f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphRowNoVec ErodeRowVec8u; |
|
|
|
|
|
|
|
typedef MorphRowNoVec DilateRowVec8u; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphColumnNoVec ErodeColumnVec8u; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec DilateColumnVec8u; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphRowNoVec ErodeRowVec16u; |
|
|
|
|
|
|
|
typedef MorphRowNoVec DilateRowVec16u; |
|
|
|
|
|
|
|
typedef MorphRowNoVec ErodeRowVec16s; |
|
|
|
|
|
|
|
typedef MorphRowNoVec DilateRowVec16s; |
|
|
|
|
|
|
|
typedef MorphRowNoVec ErodeRowVec32f; |
|
|
|
|
|
|
|
typedef MorphRowNoVec DilateRowVec32f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphColumnNoVec ErodeColumnVec16u; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec DilateColumnVec16u; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec ErodeColumnVec16s; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec DilateColumnVec16s; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec ErodeColumnVec32f; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec DilateColumnVec32f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphNoVec ErodeVec8u; |
|
|
|
|
|
|
|
typedef MorphNoVec DilateVec8u; |
|
|
|
|
|
|
|
typedef MorphNoVec ErodeVec16u; |
|
|
|
|
|
|
|
typedef MorphNoVec DilateVec16u; |
|
|
|
|
|
|
|
typedef MorphNoVec ErodeVec16s; |
|
|
|
|
|
|
|
typedef MorphNoVec DilateVec16s; |
|
|
|
|
|
|
|
typedef MorphNoVec ErodeVec32f; |
|
|
|
|
|
|
|
typedef MorphNoVec DilateVec32f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef MorphRowNoVec ErodeRowVec64f; |
|
|
|
|
|
|
|
typedef MorphRowNoVec DilateRowVec64f; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec ErodeColumnVec64f; |
|
|
|
|
|
|
|
typedef MorphColumnNoVec DilateColumnVec64f; |
|
|
|
|
|
|
|
typedef MorphNoVec ErodeVec64f; |
|
|
|
|
|
|
|
typedef MorphNoVec DilateVec64f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class Op, class VecOp> struct MorphRowFilter : public BaseRowFilter |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef typename Op::rtype T; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MorphRowFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ksize = _ksize; |
|
|
|
|
|
|
|
anchor = _anchor; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void operator()(const uchar* src, uchar* dst, int width, int cn) CV_OVERRIDE |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i, j, k, _ksize = ksize*cn; |
|
|
|
|
|
|
|
const T* S = (const T*)src; |
|
|
|
|
|
|
|
Op op; |
|
|
|
|
|
|
|
T* D = (T*)dst; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( _ksize == cn ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0; i < width*cn; i++ ) |
|
|
|
|
|
|
|
D[i] = S[i]; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int i0 = vecOp(src, dst, width, cn); |
|
|
|
|
|
|
|
width *= cn; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 0; k < cn; k++, S++, D++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = i0; i <= width - cn*2; i += cn*2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const T* s = S + i; |
|
|
|
|
|
|
|
T m = s[cn]; |
|
|
|
|
|
|
|
for( j = cn*2; j < _ksize; j += cn ) |
|
|
|
|
|
|
|
m = op(m, s[j]); |
|
|
|
|
|
|
|
D[i] = op(m, s[0]); |
|
|
|
|
|
|
|
D[i+cn] = op(m, s[j]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( ; i < width; i += cn ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const T* s = S + i; |
|
|
|
|
|
|
|
T m = s[0]; |
|
|
|
|
|
|
|
for( j = cn; j < _ksize; j += cn ) |
|
|
|
|
|
|
|
m = op(m, s[j]); |
|
|
|
|
|
|
|
D[i] = m; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VecOp vecOp; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class Op, class VecOp> struct MorphColumnFilter : public BaseColumnFilter |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef typename Op::rtype T; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MorphColumnFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ksize = _ksize; |
|
|
|
|
|
|
|
anchor = _anchor; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void operator()(const uchar** _src, uchar* dst, int dststep, int count, int width) CV_OVERRIDE |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i, k, _ksize = ksize; |
|
|
|
|
|
|
|
const T** src = (const T**)_src; |
|
|
|
|
|
|
|
T* D = (T*)dst; |
|
|
|
|
|
|
|
Op op; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int i0 = vecOp(_src, dst, dststep, count, width); |
|
|
|
|
|
|
|
dststep /= sizeof(D[0]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( ; _ksize > 1 && count > 1; count -= 2, D += dststep*2, src += 2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
i = i0; |
|
|
|
|
|
|
|
#if CV_ENABLE_UNROLLED |
|
|
|
|
|
|
|
for( ; i <= width - 4; i += 4 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const T* sptr = src[1] + i; |
|
|
|
|
|
|
|
T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 2; k < _ksize; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]); |
|
|
|
|
|
|
|
s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sptr = src[0] + i; |
|
|
|
|
|
|
|
D[i] = op(s0, sptr[0]); |
|
|
|
|
|
|
|
D[i+1] = op(s1, sptr[1]); |
|
|
|
|
|
|
|
D[i+2] = op(s2, sptr[2]); |
|
|
|
|
|
|
|
D[i+3] = op(s3, sptr[3]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
D[i+dststep] = op(s0, sptr[0]); |
|
|
|
|
|
|
|
D[i+dststep+1] = op(s1, sptr[1]); |
|
|
|
|
|
|
|
D[i+dststep+2] = op(s2, sptr[2]); |
|
|
|
|
|
|
|
D[i+dststep+3] = op(s3, sptr[3]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
for( ; i < width; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
T s0 = src[1][i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 2; k < _ksize; k++ ) |
|
|
|
|
|
|
|
s0 = op(s0, src[k][i]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
D[i] = op(s0, src[0][i]); |
|
|
|
|
|
|
|
D[i+dststep] = op(s0, src[k][i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( ; count > 0; count--, D += dststep, src++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
i = i0; |
|
|
|
|
|
|
|
#if CV_ENABLE_UNROLLED |
|
|
|
|
|
|
|
for( ; i <= width - 4; i += 4 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const T* sptr = src[0] + i; |
|
|
|
|
|
|
|
T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 1; k < _ksize; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = src[k] + i; |
|
|
|
|
|
|
|
s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]); |
|
|
|
|
|
|
|
s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
D[i] = s0; D[i+1] = s1; |
|
|
|
|
|
|
|
D[i+2] = s2; D[i+3] = s3; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
for( ; i < width; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
T s0 = src[0][i]; |
|
|
|
|
|
|
|
for( k = 1; k < _ksize; k++ ) |
|
|
|
|
|
|
|
s0 = op(s0, src[k][i]); |
|
|
|
|
|
|
|
D[i] = s0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VecOp vecOp; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class Op, class VecOp> struct MorphFilter : BaseFilter |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
typedef typename Op::rtype T; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MorphFilter( const Mat& _kernel, Point _anchor ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
anchor = _anchor; |
|
|
|
|
|
|
|
ksize = _kernel.size(); |
|
|
|
|
|
|
|
CV_Assert( _kernel.type() == CV_8U ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<uchar> coeffs; // we do not really the values of non-zero
|
|
|
|
|
|
|
|
// kernel elements, just their locations
|
|
|
|
|
|
|
|
preprocess2DKernel( _kernel, coords, coeffs ); |
|
|
|
|
|
|
|
ptrs.resize( coords.size() ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void operator()(const uchar** src, uchar* dst, int dststep, int count, int width, int cn) CV_OVERRIDE |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const Point* pt = &coords[0]; |
|
|
|
|
|
|
|
const T** kp = (const T**)&ptrs[0]; |
|
|
|
|
|
|
|
int i, k, nz = (int)coords.size(); |
|
|
|
|
|
|
|
Op op; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
width *= cn; |
|
|
|
|
|
|
|
for( ; count > 0; count--, dst += dststep, src++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
T* D = (T*)dst; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 0; k < nz; k++ ) |
|
|
|
|
|
|
|
kp[k] = (const T*)src[pt[k].y] + pt[k].x*cn; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = vecOp(&ptrs[0], nz, dst, width); |
|
|
|
|
|
|
|
#if CV_ENABLE_UNROLLED |
|
|
|
|
|
|
|
for( ; i <= width - 4; i += 4 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const T* sptr = kp[0] + i; |
|
|
|
|
|
|
|
T s0 = sptr[0], s1 = sptr[1], s2 = sptr[2], s3 = sptr[3]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for( k = 1; k < nz; k++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sptr = kp[k] + i; |
|
|
|
|
|
|
|
s0 = op(s0, sptr[0]); s1 = op(s1, sptr[1]); |
|
|
|
|
|
|
|
s2 = op(s2, sptr[2]); s3 = op(s3, sptr[3]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
D[i] = s0; D[i+1] = s1; |
|
|
|
|
|
|
|
D[i+2] = s2; D[i+3] = s3; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
for( ; i < width; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
T s0 = kp[0][i]; |
|
|
|
|
|
|
|
for( k = 1; k < nz; k++ ) |
|
|
|
|
|
|
|
s0 = op(s0, kp[k][i]); |
|
|
|
|
|
|
|
D[i] = s0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<Point> coords; |
|
|
|
|
|
|
|
std::vector<uchar*> ptrs; |
|
|
|
|
|
|
|
VecOp vecOp; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////// External Interface /////////////////////////////////////
|
|
|
|
/////////////////////////////////// External Interface /////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
cv::Ptr<cv::BaseRowFilter> cv::getMorphologyRowFilter(int op, int type, int ksize, int anchor) |
|
|
|
Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int ksize, int anchor) |
|
|
|
{ |
|
|
|
|
|
|
|
int depth = CV_MAT_DEPTH(type); |
|
|
|
|
|
|
|
if( anchor < 0 ) |
|
|
|
|
|
|
|
anchor = ksize/2; |
|
|
|
|
|
|
|
CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE ); |
|
|
|
|
|
|
|
if( op == MORPH_ERODE ) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if( depth == CV_8U ) |
|
|
|
CV_INSTRUMENT_REGION(); |
|
|
|
return makePtr<MorphRowFilter<MinOp<uchar>, |
|
|
|
|
|
|
|
ErodeRowVec8u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16U ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MinOp<ushort>, |
|
|
|
|
|
|
|
ErodeRowVec16u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16S ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MinOp<short>, |
|
|
|
|
|
|
|
ErodeRowVec16s> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_32F ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MinOp<float>, |
|
|
|
|
|
|
|
ErodeRowVec32f> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_64F ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MinOp<double>, |
|
|
|
|
|
|
|
ErodeRowVec64f> >(ksize, anchor); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( depth == CV_8U ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MaxOp<uchar>, |
|
|
|
|
|
|
|
DilateRowVec8u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16U ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MaxOp<ushort>, |
|
|
|
|
|
|
|
DilateRowVec16u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16S ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MaxOp<short>, |
|
|
|
|
|
|
|
DilateRowVec16s> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_32F ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MaxOp<float>, |
|
|
|
|
|
|
|
DilateRowVec32f> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_64F ) |
|
|
|
|
|
|
|
return makePtr<MorphRowFilter<MaxOp<double>, |
|
|
|
|
|
|
|
DilateRowVec64f> >(ksize, anchor); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type)); |
|
|
|
CV_CPU_DISPATCH(getMorphologyRowFilter, (op, type, ksize, anchor), |
|
|
|
|
|
|
|
CV_CPU_DISPATCH_MODES_ALL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cv::Ptr<cv::BaseColumnFilter> cv::getMorphologyColumnFilter(int op, int type, int ksize, int anchor) |
|
|
|
Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int depth = CV_MAT_DEPTH(type); |
|
|
|
CV_INSTRUMENT_REGION(); |
|
|
|
if( anchor < 0 ) |
|
|
|
|
|
|
|
anchor = ksize/2; |
|
|
|
|
|
|
|
CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE ); |
|
|
|
|
|
|
|
if( op == MORPH_ERODE ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( depth == CV_8U ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MinOp<uchar>, |
|
|
|
|
|
|
|
ErodeColumnVec8u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16U ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MinOp<ushort>, |
|
|
|
|
|
|
|
ErodeColumnVec16u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16S ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MinOp<short>, |
|
|
|
|
|
|
|
ErodeColumnVec16s> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_32F ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MinOp<float>, |
|
|
|
|
|
|
|
ErodeColumnVec32f> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_64F ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MinOp<double>, |
|
|
|
|
|
|
|
ErodeColumnVec64f> >(ksize, anchor); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( depth == CV_8U ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MaxOp<uchar>, |
|
|
|
|
|
|
|
DilateColumnVec8u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16U ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MaxOp<ushort>, |
|
|
|
|
|
|
|
DilateColumnVec16u> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16S ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MaxOp<short>, |
|
|
|
|
|
|
|
DilateColumnVec16s> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_32F ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MaxOp<float>, |
|
|
|
|
|
|
|
DilateColumnVec32f> >(ksize, anchor); |
|
|
|
|
|
|
|
if( depth == CV_64F ) |
|
|
|
|
|
|
|
return makePtr<MorphColumnFilter<MaxOp<double>, |
|
|
|
|
|
|
|
DilateColumnVec64f> >(ksize, anchor); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type)); |
|
|
|
CV_CPU_DISPATCH(getMorphologyColumnFilter, (op, type, ksize, anchor), |
|
|
|
|
|
|
|
CV_CPU_DISPATCH_MODES_ALL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Ptr<cv::BaseFilter> cv::getMorphologyFilter(int op, int type, InputArray _kernel, Point anchor) |
|
|
|
Ptr<BaseFilter> getMorphologyFilter(int op, int type, InputArray _kernel, Point anchor) |
|
|
|
{ |
|
|
|
|
|
|
|
Mat kernel = _kernel.getMat(); |
|
|
|
|
|
|
|
int depth = CV_MAT_DEPTH(type); |
|
|
|
|
|
|
|
anchor = normalizeAnchor(anchor, kernel.size()); |
|
|
|
|
|
|
|
CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE ); |
|
|
|
|
|
|
|
if( op == MORPH_ERODE ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( depth == CV_8U ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MinOp<uchar>, ErodeVec8u> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16U ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MinOp<ushort>, ErodeVec16u> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16S ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MinOp<short>, ErodeVec16s> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_32F ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MinOp<float>, ErodeVec32f> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_64F ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MinOp<double>, ErodeVec64f> >(kernel, anchor); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if( depth == CV_8U ) |
|
|
|
CV_INSTRUMENT_REGION(); |
|
|
|
return makePtr<MorphFilter<MaxOp<uchar>, DilateVec8u> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16U ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MaxOp<ushort>, DilateVec16u> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_16S ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MaxOp<short>, DilateVec16s> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_32F ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MaxOp<float>, DilateVec32f> >(kernel, anchor); |
|
|
|
|
|
|
|
if( depth == CV_64F ) |
|
|
|
|
|
|
|
return makePtr<MorphFilter<MaxOp<double>, DilateVec64f> >(kernel, anchor); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CV_Error_( CV_StsNotImplemented, ("Unsupported data type (=%d)", type)); |
|
|
|
Mat kernel = _kernel.getMat(); |
|
|
|
|
|
|
|
CV_CPU_DISPATCH(getMorphologyFilter, (op, type, kernel, anchor), |
|
|
|
|
|
|
|
CV_CPU_DISPATCH_MODES_ALL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Ptr<cv::FilterEngine> cv::createMorphologyFilter( int op, int type, InputArray _kernel, |
|
|
|
Ptr<FilterEngine> createMorphologyFilter( |
|
|
|
|
|
|
|
int op, int type, InputArray _kernel, |
|
|
|
Point anchor, int _rowBorderType, int _columnBorderType, |
|
|
|
Point anchor, int _rowBorderType, int _columnBorderType, |
|
|
|
const Scalar& _borderValue) |
|
|
|
const Scalar& _borderValue) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -862,7 +132,7 @@ cv::Ptr<cv::FilterEngine> cv::createMorphologyFilter( int op, int type, InputArr |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat cv::getStructuringElement(int shape, Size ksize, Point anchor) |
|
|
|
Mat getStructuringElement(int shape, Size ksize, Point anchor) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i, j; |
|
|
|
int i, j; |
|
|
|
int r = 0, c = 0; |
|
|
|
int r = 0, c = 0; |
|
|
@ -915,9 +185,6 @@ cv::Mat cv::getStructuringElement(int shape, Size ksize, Point anchor) |
|
|
|
return elem; |
|
|
|
return elem; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
namespace cv |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ===== 1. replacement implementation
|
|
|
|
// ===== 1. replacement implementation
|
|
|
|
|
|
|
|
|
|
|
|
static bool halMorph(int op, int src_type, int dst_type, |
|
|
|
static bool halMorph(int op, int src_type, int dst_type, |
|
|
@ -1732,9 +999,7 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, |
|
|
|
(src.isSubmatrix() && !isolated)); |
|
|
|
(src.isSubmatrix() && !isolated)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
void erode( InputArray src, OutputArray dst, InputArray kernel, |
|
|
|
|
|
|
|
|
|
|
|
void cv::erode( InputArray src, OutputArray dst, InputArray kernel, |
|
|
|
|
|
|
|
Point anchor, int iterations, |
|
|
|
Point anchor, int iterations, |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1744,7 +1009,7 @@ void cv::erode( InputArray src, OutputArray dst, InputArray kernel, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cv::dilate( InputArray src, OutputArray dst, InputArray kernel, |
|
|
|
void dilate( InputArray src, OutputArray dst, InputArray kernel, |
|
|
|
Point anchor, int iterations, |
|
|
|
Point anchor, int iterations, |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1755,8 +1020,6 @@ void cv::dilate( InputArray src, OutputArray dst, InputArray kernel, |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
|
|
|
|
|
|
|
|
namespace cv { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, |
|
|
|
static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, |
|
|
|
InputArray kernel, Point anchor, int iterations, |
|
|
|
InputArray kernel, Point anchor, int iterations, |
|
|
|
int borderType, const Scalar& borderValue) |
|
|
|
int borderType, const Scalar& borderValue) |
|
|
@ -1813,13 +1076,11 @@ static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#define IPP_DISABLE_MORPH_ADV 1 |
|
|
|
#define IPP_DISABLE_MORPH_ADV 1 |
|
|
|
#ifdef HAVE_IPP |
|
|
|
#ifdef HAVE_IPP |
|
|
|
#if !IPP_DISABLE_MORPH_ADV |
|
|
|
#if !IPP_DISABLE_MORPH_ADV |
|
|
|
namespace cv { |
|
|
|
|
|
|
|
static bool ipp_morphologyEx(int op, InputArray _src, OutputArray _dst, |
|
|
|
static bool ipp_morphologyEx(int op, InputArray _src, OutputArray _dst, |
|
|
|
InputArray _kernel, |
|
|
|
InputArray _kernel, |
|
|
|
Point anchor, int iterations, |
|
|
|
Point anchor, int iterations, |
|
|
@ -1884,11 +1145,10 @@ static bool ipp_morphologyEx(int op, InputArray _src, OutputArray _dst, |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, |
|
|
|
void morphologyEx( InputArray _src, OutputArray _dst, int op, |
|
|
|
InputArray _kernel, Point anchor, int iterations, |
|
|
|
InputArray _kernel, Point anchor, int iterations, |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1985,6 +1245,8 @@ void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace cv
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL IplConvKernel * |
|
|
|
CV_IMPL IplConvKernel * |
|
|
|
cvCreateStructuringElementEx( int cols, int rows, |
|
|
|
cvCreateStructuringElementEx( int cols, int rows, |
|
|
|
int anchorX, int anchorY, |
|
|
|
int anchorX, int anchorY, |
|
|
|