diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index d47e2bb1ba..245e974ad8 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -178,6 +178,73 @@ static void threshGenericWithMask(const Mat& _src, Mat& _dst, const Mat& _mask, } +#if (CV_SIMD || CV_SIMD_SCALABLE || CV_SIMD_64F || CV_SIMD_SCALABLE_64F) +// Shared SIMD skeleton for thresh_16u/16s/32f/64f: 2x-unrolled body, 1x remainder, scalar tail. +template +static inline void threshSimdLoop(Size roi, const T* src, size_t src_step, T* dst, size_t dst_step, + VecOp vop, ScalarOp sop) +{ + const int vlanes = VTraits::vlanes(); + for (int i = 0; i < roi.height; i++, src += src_step, dst += dst_step) + { + int j = 0; + for (; j <= roi.width - 2*vlanes; j += 2*vlanes) + { + V v0 = vx_load(src + j); + V v1 = vx_load(src + j + vlanes); + v_store(dst + j, vop(v0)); + v_store(dst + j + vlanes, vop(v1)); + } + if (j <= roi.width - vlanes) + { + v_store(dst + j, vop(vx_load(src + j))); + j += vlanes; + } + for (; j < roi.width; j++) + dst[j] = sop(src[j]); + } +} + +// switch(type) shared across the 16u/16s/32f/64f depth functions; the per-type vector op and the +// matching scalar helper are passed as inlined lambdas, so codegen is identical to the +// hand-written per-depth loops. +template +static void threshSimdDispatch(Size roi, const T* src, size_t src_step, T* dst, size_t dst_step, + V vthresh, V vmaxval, T thresh, T maxval, int type) +{ + switch (type) + { + case THRESH_BINARY: + threshSimdLoop(roi, src, src_step, dst, dst_step, + [=](const V& v) { return v_and(v_lt(vthresh, v), vmaxval); }, + [=](const T& s) { return threshBinary(s, thresh, maxval); }); + break; + case THRESH_BINARY_INV: + threshSimdLoop(roi, src, src_step, dst, dst_step, + [=](const V& v) { return v_and(v_le(v, vthresh), vmaxval); }, + [=](const T& s) { return threshBinaryInv(s, thresh, maxval); }); + break; + case THRESH_TRUNC: + threshSimdLoop(roi, src, src_step, dst, dst_step, + [=](const V& v) { return v_min(v, vthresh); }, + [=](const T& s) { return threshTrunc(s, thresh); }); + break; + case THRESH_TOZERO: + threshSimdLoop(roi, src, src_step, dst, dst_step, + [=](const V& v) { return v_and(v_lt(vthresh, v), v); }, + [=](const T& s) { return threshToZero(s, thresh); }); + break; + case THRESH_TOZERO_INV: + threshSimdLoop(roi, src, src_step, dst, dst_step, + [=](const V& v) { return v_and(v_le(v, vthresh), v); }, + [=](const T& s) { return threshToZeroInv(s, thresh); }); + break; + default: + CV_Error( cv::Error::StsBadArg, "Unknown/unsupported threshold type" ); + } +} +#endif + static void thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) { @@ -358,152 +425,8 @@ thresh_16u(const Mat& _src, Mat& _dst, ushort thresh, ushort maxval, int type) const ushort* src = _src.ptr(); ushort* dst = _dst.ptr(); #if (CV_SIMD || CV_SIMD_SCALABLE) - int i, j; - v_uint16 thresh_u = vx_setall_u16(thresh); - v_uint16 maxval16 = vx_setall_u16(maxval); - - switch (type) - { - case THRESH_BINARY: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - for (j = 0; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes()) - { - v_uint16 v0, v1; - v0 = vx_load(src + j); - v1 = vx_load(src + j + VTraits::vlanes()); - v0 = v_lt(thresh_u, v0); - v1 = v_lt(thresh_u, v1); - v0 = v_and(v0, maxval16); - v1 = v_and(v1, maxval16); - v_store(dst + j, v0); - v_store(dst + j + VTraits::vlanes(), v1); - } - if (j <= roi.width - VTraits::vlanes()) - { - v_uint16 v0 = vx_load(src + j); - v0 = v_lt(thresh_u, v0); - v0 = v_and(v0, maxval16); - v_store(dst + j, v0); - j += VTraits::vlanes(); - } - - for (; j < roi.width; j++) - dst[j] = threshBinary(src[j], thresh, maxval); - } - break; - - case THRESH_BINARY_INV: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - j = 0; - for (; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes()) - { - v_uint16 v0, v1; - v0 = vx_load(src + j); - v1 = vx_load(src + j + VTraits::vlanes()); - v0 = v_le(v0, thresh_u); - v1 = v_le(v1, thresh_u); - v0 = v_and(v0, maxval16); - v1 = v_and(v1, maxval16); - v_store(dst + j, v0); - v_store(dst + j + VTraits::vlanes(), v1); - } - if (j <= roi.width - VTraits::vlanes()) - { - v_uint16 v0 = vx_load(src + j); - v0 = v_le(v0, thresh_u); - v0 = v_and(v0, maxval16); - v_store(dst + j, v0); - j += VTraits::vlanes(); - } - - for (; j < roi.width; j++) - dst[j] = threshBinaryInv(src[j], thresh, maxval); - } - break; - - case THRESH_TRUNC: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - j = 0; - for (; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes()) - { - v_uint16 v0, v1; - v0 = vx_load(src + j); - v1 = vx_load(src + j + VTraits::vlanes()); - v0 = v_min(v0, thresh_u); - v1 = v_min(v1, thresh_u); - v_store(dst + j, v0); - v_store(dst + j + VTraits::vlanes(), v1); - } - if (j <= roi.width - VTraits::vlanes()) - { - v_uint16 v0 = vx_load(src + j); - v0 = v_min(v0, thresh_u); - v_store(dst + j, v0); - j += VTraits::vlanes(); - } - - for (; j < roi.width; j++) - dst[j] = threshTrunc(src[j], thresh); - } - break; - - case THRESH_TOZERO: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - j = 0; - for (; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes()) - { - v_uint16 v0, v1; - v0 = vx_load(src + j); - v1 = vx_load(src + j + VTraits::vlanes()); - v0 = v_and(v_lt(thresh_u, v0), v0); - v1 = v_and(v_lt(thresh_u, v1), v1); - v_store(dst + j, v0); - v_store(dst + j + VTraits::vlanes(), v1); - } - if (j <= roi.width - VTraits::vlanes()) - { - v_uint16 v0 = vx_load(src + j); - v0 = v_and(v_lt(thresh_u, v0), v0); - v_store(dst + j, v0); - j += VTraits::vlanes(); - } - - for (; j < roi.width; j++) - dst[j] = threshToZero(src[j], thresh); - } - break; - - case THRESH_TOZERO_INV: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - j = 0; - for (; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes()) - { - v_uint16 v0, v1; - v0 = vx_load(src + j); - v1 = vx_load(src + j + VTraits::vlanes()); - v0 = v_and(v_le(v0, thresh_u), v0); - v1 = v_and(v_le(v1, thresh_u), v1); - v_store(dst + j, v0); - v_store(dst + j + VTraits::vlanes(), v1); - } - if (j <= roi.width - VTraits::vlanes()) - { - v_uint16 v0 = vx_load(src + j); - v0 = v_and(v_le(v0, thresh_u), v0); - v_store(dst + j, v0); - j += VTraits::vlanes(); - } - - for (; j < roi.width; j++) - dst[j] = threshToZeroInv(src[j], thresh); - } - break; - } + threshSimdDispatch(roi, src, src_step, dst, dst_step, + vx_setall_u16(thresh), vx_setall_u16(maxval), thresh, maxval, type); #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif @@ -527,155 +450,8 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) } #if (CV_SIMD || CV_SIMD_SCALABLE) - int i, j; - v_int16 thresh8 = vx_setall_s16( thresh ); - v_int16 maxval8 = vx_setall_s16( maxval ); - - switch( type ) - { - case THRESH_BINARY: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_int16 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_lt(thresh8, v0); - v1 = v_lt(thresh8, v1); - v0 = v_and(v0, maxval8); - v1 = v_and(v1, maxval8); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_int16 v0 = vx_load( src + j ); - v0 = v_lt(thresh8, v0); - v0 = v_and(v0, maxval8); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshBinary(src[j], thresh, maxval); - } - break; - - case THRESH_BINARY_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_int16 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_le(v0, thresh8); - v1 = v_le(v1, thresh8); - v0 = v_and(v0, maxval8); - v1 = v_and(v1, maxval8); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_int16 v0 = vx_load( src + j ); - v0 = v_le(v0, thresh8); - v0 = v_and(v0, maxval8); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshBinaryInv(src[j], thresh, maxval); - } - break; - - case THRESH_TRUNC: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_int16 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_min( v0, thresh8 ); - v1 = v_min( v1, thresh8 ); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_int16 v0 = vx_load( src + j ); - v0 = v_min( v0, thresh8 ); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshTrunc( src[j], thresh ); - } - break; - - case THRESH_TOZERO: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_int16 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_and(v_lt(thresh8, v0), v0); - v1 = v_and(v_lt(thresh8, v1), v1); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_int16 v0 = vx_load( src + j ); - v0 = v_and(v_lt(thresh8, v0), v0); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshToZero(src[j], thresh); - } - break; - - case THRESH_TOZERO_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_int16 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_and(v_le(v0, thresh8), v0); - v1 = v_and(v_le(v1, thresh8), v1); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_int16 v0 = vx_load( src + j ); - v0 = v_and(v_le(v0, thresh8), v0); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshToZeroInv(src[j], thresh); - } - break; - default: - CV_Error( cv::Error::StsBadArg, "" ); return; - } + threshSimdDispatch(roi, src, src_step, dst, dst_step, + vx_setall_s16(thresh), vx_setall_s16(maxval), thresh, maxval, type); #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif @@ -698,155 +474,8 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) } #if (CV_SIMD || CV_SIMD_SCALABLE) - int i, j; - v_float32 thresh4 = vx_setall_f32( thresh ); - v_float32 maxval4 = vx_setall_f32( maxval ); - - switch( type ) - { - case THRESH_BINARY: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float32 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_lt(thresh4, v0); - v1 = v_lt(thresh4, v1); - v0 = v_and(v0, maxval4); - v1 = v_and(v1, maxval4); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float32 v0 = vx_load( src + j ); - v0 = v_lt(thresh4, v0); - v0 = v_and(v0, maxval4); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshBinary(src[j], thresh, maxval); - } - break; - - case THRESH_BINARY_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float32 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_le(v0, thresh4); - v1 = v_le(v1, thresh4); - v0 = v_and(v0, maxval4); - v1 = v_and(v1, maxval4); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float32 v0 = vx_load( src + j ); - v0 = v_le(v0, thresh4); - v0 = v_and(v0, maxval4); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshBinaryInv(src[j], thresh, maxval); - } - break; - - case THRESH_TRUNC: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float32 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_min( v0, thresh4 ); - v1 = v_min( v1, thresh4 ); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float32 v0 = vx_load( src + j ); - v0 = v_min( v0, thresh4 ); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshTrunc(src[j], thresh); - } - break; - - case THRESH_TOZERO: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float32 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_and(v_lt(thresh4, v0), v0); - v1 = v_and(v_lt(thresh4, v1), v1); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float32 v0 = vx_load( src + j ); - v0 = v_and(v_lt(thresh4, v0), v0); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshToZero(src[j], thresh); - } - break; - - case THRESH_TOZERO_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float32 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_and(v_le(v0, thresh4), v0); - v1 = v_and(v_le(v1, thresh4), v1); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float32 v0 = vx_load( src + j ); - v0 = v_and(v_le(v0, thresh4), v0); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshToZeroInv(src[j], thresh); - } - break; - default: - CV_Error( cv::Error::StsBadArg, "" ); return; - } + threshSimdDispatch(roi, src, src_step, dst, dst_step, + vx_setall_f32(thresh), vx_setall_f32(maxval), thresh, maxval, type); #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif @@ -869,155 +498,8 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) } #if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) - int i, j; - v_float64 thresh2 = vx_setall_f64( thresh ); - v_float64 maxval2 = vx_setall_f64( maxval ); - - switch( type ) - { - case THRESH_BINARY: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float64 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_lt(thresh2, v0); - v1 = v_lt(thresh2, v1); - v0 = v_and(v0, maxval2); - v1 = v_and(v1, maxval2); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float64 v0 = vx_load( src + j ); - v0 = v_lt(thresh2, v0); - v0 = v_and(v0, maxval2); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshBinary(src[j], thresh, maxval); - } - break; - - case THRESH_BINARY_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float64 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_le(v0, thresh2); - v1 = v_le(v1, thresh2); - v0 = v_and(v0, maxval2); - v1 = v_and(v1, maxval2); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float64 v0 = vx_load( src + j ); - v0 = v_le(v0, thresh2); - v0 = v_and(v0, maxval2); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshBinaryInv(src[j], thresh, maxval); - } - break; - - case THRESH_TRUNC: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float64 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_min( v0, thresh2 ); - v1 = v_min( v1, thresh2 ); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float64 v0 = vx_load( src + j ); - v0 = v_min( v0, thresh2 ); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshTrunc(src[j], thresh); - } - break; - - case THRESH_TOZERO: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float64 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_and(v_lt(thresh2, v0), v0); - v1 = v_and(v_lt(thresh2, v1), v1); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float64 v0 = vx_load( src + j ); - v0 = v_and(v_lt(thresh2, v0), v0); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshToZero(src[j], thresh); - } - break; - - case THRESH_TOZERO_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j <= roi.width - 2*VTraits::vlanes(); j += 2*VTraits::vlanes() ) - { - v_float64 v0, v1; - v0 = vx_load( src + j ); - v1 = vx_load( src + j + VTraits::vlanes() ); - v0 = v_and(v_le(v0, thresh2), v0); - v1 = v_and(v_le(v1, thresh2), v1); - v_store( dst + j, v0 ); - v_store( dst + j + VTraits::vlanes(), v1 ); - } - if( j <= roi.width - VTraits::vlanes() ) - { - v_float64 v0 = vx_load( src + j ); - v0 = v_and(v_le(v0, thresh2), v0); - v_store( dst + j, v0 ); - j += VTraits::vlanes(); - } - - for( ; j < roi.width; j++ ) - dst[j] = threshToZeroInv(src[j], thresh); - } - break; - default: - CV_Error(cv::Error::StsBadArg, ""); return; - } + threshSimdDispatch(roi, src, src_step, dst, dst_step, + vx_setall_f64(thresh), vx_setall_f64(maxval), thresh, maxval, type); #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif