From 430909e2a3bc1c5a2000519328211567ddfde269 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:26:56 +0300 Subject: [PATCH] Revert "Merge pull request #29492 from Akansha-977:threshold_IPP_5.x" This reverts commit c64d89e75c15fda579a5fe9bbb2db820c74d5664. --- modules/imgproc/src/thresh.cpp | 668 +++++++++++++++++++++++++++++---- 1 file changed, 593 insertions(+), 75 deletions(-) diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 245e974ad8..d47e2bb1ba 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -178,73 +178,6 @@ 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 ) { @@ -425,8 +358,152 @@ 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) - threshSimdDispatch(roi, src, src_step, dst, dst_step, - vx_setall_u16(thresh), vx_setall_u16(maxval), thresh, maxval, type); + 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; + } #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif @@ -450,8 +527,155 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) } #if (CV_SIMD || CV_SIMD_SCALABLE) - threshSimdDispatch(roi, src, src_step, dst, dst_step, - vx_setall_s16(thresh), vx_setall_s16(maxval), thresh, maxval, type); + 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; + } #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif @@ -474,8 +698,155 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) } #if (CV_SIMD || CV_SIMD_SCALABLE) - threshSimdDispatch(roi, src, src_step, dst, dst_step, - vx_setall_f32(thresh), vx_setall_f32(maxval), thresh, maxval, type); + 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; + } #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif @@ -498,8 +869,155 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) } #if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F) - threshSimdDispatch(roi, src, src_step, dst, dst_step, - vx_setall_f64(thresh), vx_setall_f64(maxval), thresh, maxval, type); + 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; + } #else threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); #endif