From fa109b94d9ff02a6b9fb37c73e790791273523f4 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 18 Sep 2017 15:42:44 +0300 Subject: [PATCH] Update 16UC thresholding --- modules/imgproc/src/thresh.cpp | 661 ++++++++++++++--------------------- modules/imgproc/test/test_thresh.cpp | 64 +++- 2 files changed, 314 insertions(+), 411 deletions(-) diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index b6b0c2c..f7ad195 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -49,6 +49,78 @@ namespace cv { +template +static inline T threshBinary(const T& src, const T& thresh, const T& maxval) +{ + return src > thresh ? maxval : 0; +} + +template +static inline T threshBinaryInv(const T& src, const T& thresh, const T& maxval) +{ + return src <= thresh ? maxval : 0; +} + +template +static inline T threshTrunc(const T& src, const T& thresh) +{ + return std::min(src, thresh); +} + +template +static inline T threshToZero(const T& src, const T& thresh) +{ + return src > thresh ? src : 0; +} + +template +static inline T threshToZeroInv(const T& src, const T& thresh) +{ + return src <= thresh ? src : 0; +} + +template +static void threshGeneric(Size roi, const T* src, size_t src_step, T* dst, + size_t dst_step, T thresh, T maxval, int type) +{ + int i = 0, j; + switch (type) + { + case THRESH_BINARY: + for (; i < roi.height; i++, src += src_step, dst += dst_step) + for (j = 0; j < roi.width; j++) + dst[j] = threshBinary(src[j], thresh, maxval); + return; + + case THRESH_BINARY_INV: + for (; i < roi.height; i++, src += src_step, dst += dst_step) + for (j = 0; j < roi.width; j++) + dst[j] = threshBinaryInv(src[j], thresh, maxval); + return; + + case THRESH_TRUNC: + for (; i < roi.height; i++, src += src_step, dst += dst_step) + for (j = 0; j < roi.width; j++) + dst[j] = threshTrunc(src[j], thresh); + return; + + case THRESH_TOZERO: + for (; i < roi.height; i++, src += src_step, dst += dst_step) + for (j = 0; j < roi.width; j++) + dst[j] = threshToZero(src[j], thresh); + return; + + case THRESH_TOZERO_INV: + for (; i < roi.height; i++, src += src_step, dst += dst_step) + for (j = 0; j < roi.width; j++) + dst[j] = threshToZeroInv(src[j], thresh); + return; + + default: + CV_Error( CV_StsBadArg, "" ); return; + } +} + static void thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) { @@ -272,206 +344,148 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) static void thresh_16u(const Mat& _src, Mat& _dst, ushort thresh, ushort maxval, int type) { - Size roi = _src.size(); - roi.width *= _src.channels(); - size_t src_step = _src.step; - size_t dst_step = _dst.step; - - if (_src.isContinuous() && _dst.isContinuous()) - { - roi.width *= roi.height; - roi.height = 1; - src_step = dst_step = roi.width; - } + Size roi = _src.size(); + roi.width *= _src.channels(); + size_t src_step = _src.step / _src.elemSize1(); + size_t dst_step = _dst.step / _dst.elemSize1(); - // HAVE_TEGRA_OPTIMIZATION not supported + if (_src.isContinuous() && _dst.isContinuous()) + { + roi.width *= roi.height; + roi.height = 1; + src_step = dst_step = roi.width; + } - // HAVE_IPP not supported + // HAVE_TEGRA_OPTIMIZATION not supported - int j = 0; - const ushort* src = _src.ptr(); - ushort* dst = _dst.ptr(); + // HAVE_IPP not supported - // CV_SIMD128 not supported + const ushort* src = _src.ptr(); + ushort* dst = _dst.ptr(); #if CV_SIMD128 - bool useSIMD = checkHardwareSupport(CV_CPU_SSE2) || checkHardwareSupport(CV_CPU_NEON); - if (useSIMD) - { - int i; - v_uint16x8 thresh_u = v_setall_u16(thresh); - v_uint16x8 maxval16 = v_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 - 16; j += 16) - { - v_uint16x8 v0, v1; - v0 = v_load(src + j); - v1 = v_load(src + j + 8); - v0 = thresh_u < v0; - v1 = thresh_u < v1; - v0 = v0 & maxval16; - v1 = v1 & maxval16; - v_store(dst + j, v0); - v_store(dst + j + 8, v1); - } - } - break; - - case THRESH_BINARY_INV: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - j = 0; - for (; j <= roi.width - 16; j += 16) - { - v_uint16x8 v0, v1; - v0 = v_load(src + j); - v1 = v_load(src + j + 8); - v0 = v0 <= thresh_u; - v1 = v1 <= thresh_u; - v0 = v0 & maxval16; - v1 = v1 & maxval16; - v_store(dst + j, v0); - v_store(dst + j + 8, v1); - } - - for (; j < roi.width; j++) - dst[j] = src[j] <= thresh ? maxval : 0; - } - break; - - case THRESH_TRUNC: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - j = 0; - for (; j <= roi.width - 16; j += 16) - { - v_uint16x8 v0, v1; - v0 = v_load(src + j); - v1 = v_load(src + j + 8); - v0 = v_min(v0, thresh_u); - v1 = v_min(v1, thresh_u); - v_store(dst + j, v0); - v_store(dst + j + 8, v1); - } - - for (; j < roi.width; j++) - dst[j] = std::min(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 - 16; j += 16) - { - v_uint16x8 v0, v1; - v0 = v_load(src + j); - v1 = v_load(src + j + 8); - v0 = (thresh_u < v0) & v0; - v1 = (thresh_u < v1) & v1; - v_store(dst + j, v0); - v_store(dst + j + 8, v1); - } - - for (; j < roi.width; j++) - { - short v = src[j]; - dst[j] = v > thresh ? v : 0; - } - } - break; - - case THRESH_TOZERO_INV: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - j = 0; - for (; j <= roi.width - 16; j += 16) - { - v_uint16x8 v0, v1; - v0 = v_load(src + j); - v1 = v_load(src + j + 8); - v0 = (v0 <= thresh_u) & v0; - v1 = (v1 <= thresh_u) & v1; - v_store(dst + j, v0); - v_store(dst + j + 8, v1); - } - - for (; j < roi.width; j++) - { - short v = src[j]; - dst[j] = v <= thresh ? v : 0; - } - } - break; - } - } - else + bool useSIMD = checkHardwareSupport(CV_CPU_SSE2) || checkHardwareSupport(CV_CPU_NEON); + if (useSIMD) + { + int i, j; + v_uint16x8 thresh_u = v_setall_u16(thresh); + v_uint16x8 maxval16 = v_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 - 16; j += 16) + { + v_uint16x8 v0, v1; + v0 = v_load(src + j); + v1 = v_load(src + j + 8); + v0 = thresh_u < v0; + v1 = thresh_u < v1; + v0 = v0 & maxval16; + v1 = v1 & maxval16; + v_store(dst + j, v0); + v_store(dst + j + 8, v1); + } + + 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 - 16; j += 16) + { + v_uint16x8 v0, v1; + v0 = v_load(src + j); + v1 = v_load(src + j + 8); + v0 = v0 <= thresh_u; + v1 = v1 <= thresh_u; + v0 = v0 & maxval16; + v1 = v1 & maxval16; + v_store(dst + j, v0); + v_store(dst + j + 8, v1); + } + + 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 - 16; j += 16) + { + v_uint16x8 v0, v1; + v0 = v_load(src + j); + v1 = v_load(src + j + 8); + v0 = v_min(v0, thresh_u); + v1 = v_min(v1, thresh_u); + v_store(dst + j, v0); + v_store(dst + j + 8, v1); + } + + 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 - 16; j += 16) + { + v_uint16x8 v0, v1; + v0 = v_load(src + j); + v1 = v_load(src + j + 8); + v0 = (thresh_u < v0) & v0; + v1 = (thresh_u < v1) & v1; + v_store(dst + j, v0); + v_store(dst + j + 8, v1); + } + + 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 - 16; j += 16) + { + v_uint16x8 v0, v1; + v0 = v_load(src + j); + v1 = v_load(src + j + 8); + v0 = (v0 <= thresh_u) & v0; + v1 = (v1 <= thresh_u) & v1; + v_store(dst + j, v0); + v_store(dst + j + 8, v1); + } + + for (; j < roi.width; j++) + dst[j] = threshToZeroInv(src[j], thresh); + } + break; + } + } + else #endif - { - int i; - switch (type) - { - case THRESH_BINARY: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - for (j = 0; j < roi.width; j++) - dst[j] = src[j] > thresh ? maxval : 0; - } - break; - - case THRESH_BINARY_INV: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - for (j = 0; j < roi.width; j++) - dst[j] = src[j] <= thresh ? maxval : 0; - } - break; - - case THRESH_TRUNC: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - for (j = 0; j < roi.width; j++) - dst[j] = std::min(src[j], thresh); - } - break; - - case THRESH_TOZERO: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - for (j = 0; j < roi.width; j++) - { - short v = src[j]; - dst[j] = v > thresh ? v : 0; - } - } - break; - - case THRESH_TOZERO_INV: - for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) - { - for (j = 0; j < roi.width; j++) - { - short v = src[j]; - dst[j] = v <= thresh ? v : 0; - } - } - break; - default: - CV_Error( CV_StsBadArg, "" ); return; - } - } + { + threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); + } } - static void thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) { - int i, j; Size roi = _src.size(); roi.width *= _src.channels(); const short* src = _src.ptr(); @@ -546,6 +560,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON ); if( useSIMD ) { + int i, j; v_int16x8 thresh8 = v_setall_s16( thresh ); v_int16x8 maxval8 = v_setall_s16( maxval ); @@ -569,7 +584,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) } for( ; j < roi.width; j++ ) - dst[j] = src[j] > thresh ? maxval : 0; + dst[j] = threshBinary(src[j], thresh, maxval); } break; @@ -591,7 +606,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) } for( ; j < roi.width; j++ ) - dst[j] = src[j] <= thresh ? maxval : 0; + dst[j] = threshBinaryInv(src[j], thresh, maxval); } break; @@ -611,7 +626,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) } for( ; j < roi.width; j++ ) - dst[j] = std::min( src[j], thresh ); + dst[j] = threshTrunc( src[j], thresh ); } break; @@ -631,10 +646,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) } for( ; j < roi.width; j++ ) - { - short v = src[j]; - dst[j] = v > thresh ? v : 0; - } + dst[j] = threshToZero(src[j], thresh); } break; @@ -654,10 +666,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) } for( ; j < roi.width; j++ ) - { - short v = src[j]; - dst[j] = v <= thresh ? v : 0; - } + dst[j] = threshToZeroInv(src[j], thresh); } break; default: @@ -667,56 +676,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) else #endif { - switch( type ) - { - case THRESH_BINARY: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - dst[j] = src[j] > thresh ? maxval : 0; - } - break; - - case THRESH_BINARY_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - dst[j] = src[j] <= thresh ? maxval : 0; - } - break; - - case THRESH_TRUNC: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - dst[j] = std::min( src[j], thresh ); - } - break; - - case THRESH_TOZERO: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - { - short v = src[j]; - dst[j] = v > thresh ? v : 0; - } - } - break; - - case THRESH_TOZERO_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - { - short v = src[j]; - dst[j] = v <= thresh ? v : 0; - } - } - break; - default: - CV_Error( CV_StsBadArg, "" ); return; - } + threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); } } @@ -724,7 +684,6 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) static void thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) { - int i, j; Size roi = _src.size(); roi.width *= _src.channels(); const float* src = _src.ptr(); @@ -781,6 +740,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON ); if( useSIMD ) { + int i, j; v_float32x4 thresh4 = v_setall_f32( thresh ); v_float32x4 maxval4 = v_setall_f32( maxval ); @@ -804,7 +764,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) } for( ; j < roi.width; j++ ) - dst[j] = src[j] > thresh ? maxval : 0; + dst[j] = threshBinary(src[j], thresh, maxval); } break; @@ -826,7 +786,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) } for( ; j < roi.width; j++ ) - dst[j] = src[j] <= thresh ? maxval : 0; + dst[j] = threshBinaryInv(src[j], thresh, maxval); } break; @@ -846,7 +806,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) } for( ; j < roi.width; j++ ) - dst[j] = std::min( src[j], thresh ); + dst[j] = threshTrunc(src[j], thresh); } break; @@ -866,10 +826,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) } for( ; j < roi.width; j++ ) - { - float v = src[j]; - dst[j] = v > thresh ? v : 0; - } + dst[j] = threshToZero(src[j], thresh); } break; @@ -889,10 +846,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) } for( ; j < roi.width; j++ ) - { - float v = src[j]; - dst[j] = v <= thresh ? v : 0; - } + dst[j] = threshToZeroInv(src[j], thresh); } break; default: @@ -902,63 +856,13 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) else #endif { - switch( type ) - { - case THRESH_BINARY: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - dst[j] = src[j] > thresh ? maxval : 0; - } - break; - - case THRESH_BINARY_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - dst[j] = src[j] <= thresh ? maxval : 0; - } - break; - - case THRESH_TRUNC: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - dst[j] = std::min( src[j], thresh ); - } - break; - - case THRESH_TOZERO: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - { - float v = src[j]; - dst[j] = v > thresh ? v : 0; - } - } - break; - - case THRESH_TOZERO_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - for( j = 0; j < roi.width; j++ ) - { - float v = src[j]; - dst[j] = v <= thresh ? v : 0; - } - } - break; - default: - CV_Error( CV_StsBadArg, "" ); return; - } + threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); } } static void thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) { - int i, j; Size roi = _src.size(); roi.width *= _src.channels(); const double* src = _src.ptr(); @@ -976,6 +880,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON ); if( useSIMD ) { + int i, j; v_float64x2 thresh2 = v_setall_f64( thresh ); v_float64x2 maxval2 = v_setall_f64( maxval ); @@ -999,7 +904,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) } for( ; j < roi.width; j++ ) - dst[j] = src[j] > thresh ? maxval : 0; + dst[j] = threshBinary(src[j], thresh, maxval); } break; @@ -1021,7 +926,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) } for( ; j < roi.width; j++ ) - dst[j] = src[j] <= thresh ? maxval : 0; + dst[j] = threshBinaryInv(src[j], thresh, maxval); } break; @@ -1041,7 +946,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) } for( ; j < roi.width; j++ ) - dst[j] = std::min( src[j], thresh ); + dst[j] = threshTrunc(src[j], thresh); } break; @@ -1061,10 +966,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) } for( ; j < roi.width; j++ ) - { - double v = src[j]; - dst[j] = v > thresh ? v : 0; - } + dst[j] = threshToZero(src[j], thresh); } break; @@ -1084,10 +986,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) } for( ; j < roi.width; j++ ) - { - double v = src[j]; - dst[j] = v <= thresh ? v : 0; - } + dst[j] = threshToZeroInv(src[j], thresh); } break; default: @@ -1097,61 +996,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) else #endif { - switch( type ) - { - case THRESH_BINARY: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j < roi.width; j++ ) - dst[j] = src[j] > thresh ? maxval : 0; - } - break; - - case THRESH_BINARY_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j < roi.width; j++ ) - dst[j] = src[j] <= thresh ? maxval : 0; - } - break; - - case THRESH_TRUNC: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j < roi.width; j++ ) - dst[j] = std::min( 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; j++ ) - { - double v = src[j]; - dst[j] = v > thresh ? v : 0; - } - } - break; - - case THRESH_TOZERO_INV: - for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step ) - { - j = 0; - for( ; j < roi.width; j++ ) - { - double v = src[j]; - dst[j] = v <= thresh ? v : 0; - } - } - break; - default: - CV_Error(CV_StsBadArg, ""); return; - } + threshGeneric(roi, src, src_step, dst, dst_step, thresh, maxval, type); } } @@ -1377,7 +1222,7 @@ public: { thresh_16s( srcStripe, dstStripe, (short)thresh, (short)maxval, thresholdType ); } - else if( srcStripe.depth() == CV_16U ) + else if( srcStripe.depth() == CV_16U ) { thresh_16u( srcStripe, dstStripe, (ushort)thresh, (ushort)maxval, thresholdType ); } @@ -1624,34 +1469,34 @@ double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double m thresh = ithresh; maxval = imaxval; } - else if (src.depth() == CV_16U ) - { - int ithresh = cvFloor(thresh); - thresh = ithresh; - int imaxval = cvRound(maxval); - if (type == THRESH_TRUNC) - imaxval = ithresh; - imaxval = saturate_cast(imaxval); - - int ushrt_min = 0; - if (ithresh < ushrt_min || ithresh >= USHRT_MAX) - { - if (type == THRESH_BINARY || type == THRESH_BINARY_INV || - ((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < ushrt_min) || - (type == THRESH_TOZERO && ithresh >= USHRT_MAX)) - { - int v = type == THRESH_BINARY ? (ithresh >= USHRT_MAX ? 0 : imaxval) : - type == THRESH_BINARY_INV ? (ithresh >= USHRT_MAX ? imaxval : 0) : - /*type == THRESH_TRUNC ? imaxval :*/ 0; - dst.setTo(v); - } - else - src.copyTo(dst); - return thresh; - } - thresh = ithresh; - maxval = imaxval; - } + else if (src.depth() == CV_16U ) + { + int ithresh = cvFloor(thresh); + thresh = ithresh; + int imaxval = cvRound(maxval); + if (type == THRESH_TRUNC) + imaxval = ithresh; + imaxval = saturate_cast(imaxval); + + int ushrt_min = 0; + if (ithresh < ushrt_min || ithresh >= USHRT_MAX) + { + if (type == THRESH_BINARY || type == THRESH_BINARY_INV || + ((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < ushrt_min) || + (type == THRESH_TOZERO && ithresh >= USHRT_MAX)) + { + int v = type == THRESH_BINARY ? (ithresh >= USHRT_MAX ? 0 : imaxval) : + type == THRESH_BINARY_INV ? (ithresh >= USHRT_MAX ? imaxval : 0) : + /*type == THRESH_TRUNC ? imaxval :*/ 0; + dst.setTo(v); + } + else + src.copyTo(dst); + return thresh; + } + thresh = ithresh; + maxval = imaxval; + } else if( src.depth() == CV_32F ) ; else if( src.depth() == CV_64F ) diff --git a/modules/imgproc/test/test_thresh.cpp b/modules/imgproc/test/test_thresh.cpp index 469ccf5..6f0d16e 100644 --- a/modules/imgproc/test/test_thresh.cpp +++ b/modules/imgproc/test/test_thresh.cpp @@ -75,9 +75,9 @@ void CV_ThreshTest::get_test_array_types_and_sizes( int test_case_idx, vector >& sizes, vector >& types ) { RNG& rng = ts->get_rng(); - int depth = cvtest::randInt(rng) % 4, cn = cvtest::randInt(rng) % 4 + 1; + int depth = cvtest::randInt(rng) % 5, cn = cvtest::randInt(rng) % 4 + 1; cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); - depth = depth == 0 ? CV_8U : depth == 1 ? CV_16S : depth == 2 ? CV_32F : CV_64F; + depth = depth == 0 ? CV_8U : depth == 1 ? CV_16S : depth == 2 ? CV_16U : depth == 3 ? CV_32F : CV_64F; types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn); thresh_type = cvtest::randInt(rng) % 5; @@ -98,6 +98,15 @@ void CV_ThreshTest::get_test_array_types_and_sizes( int test_case_idx, if( cvtest::randInt(rng)%4 == 0 ) max_val = (double)SHRT_MAX; } + else if( depth == CV_16U ) + { + double min_val = -100.f; + max_val = USHRT_MAX+100.f; + thresh_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val); + max_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val); + if( cvtest::randInt(rng)%4 == 0 ) + max_val = (double)USHRT_MAX; + } else { thresh_val = (cvtest::randReal(rng)*1000. - 500.); @@ -138,13 +147,18 @@ static void test_threshold( const Mat& _src, Mat& _dst, ithresh2 = saturate_cast(ithresh); imaxval = saturate_cast(maxval); } + else if( depth == CV_16U ) + { + ithresh2 = saturate_cast(ithresh); + imaxval = saturate_cast(maxval); + } else { ithresh2 = cvRound(ithresh); imaxval = cvRound(maxval); } - assert( depth == CV_8U || depth == CV_16S || depth == CV_32F || depth == CV_64F ); + assert( depth == CV_8U || depth == CV_16S || depth == CV_16U || depth == CV_32F || depth == CV_64F ); switch( thresh_type ) { @@ -165,6 +179,13 @@ static void test_threshold( const Mat& _src, Mat& _dst, for( j = 0; j < width_n; j++ ) dst[j] = (short)(src[j] > ithresh ? imaxval : 0); } + else if( depth == CV_16U ) + { + const ushort* src = _src.ptr(i); + ushort* dst = _dst.ptr(i); + for( j = 0; j < width_n; j++ ) + dst[j] = (ushort)(src[j] > ithresh ? imaxval : 0); + } else if( depth == CV_32F ) { const float* src = _src.ptr(i); @@ -198,6 +219,13 @@ static void test_threshold( const Mat& _src, Mat& _dst, for( j = 0; j < width_n; j++ ) dst[j] = (short)(src[j] > ithresh ? 0 : imaxval); } + else if( depth == CV_16U ) + { + const ushort* src = _src.ptr(i); + ushort* dst = _dst.ptr(i); + for( j = 0; j < width_n; j++ ) + dst[j] = (ushort)(src[j] > ithresh ? 0 : imaxval); + } else if( depth == CV_32F ) { const float* src = _src.ptr(i); @@ -237,6 +265,16 @@ static void test_threshold( const Mat& _src, Mat& _dst, dst[j] = (short)(s > ithresh ? ithresh2 : s); } } + else if( depth == CV_16U ) + { + const ushort* src = _src.ptr(i); + ushort* dst = _dst.ptr(i); + for( j = 0; j < width_n; j++ ) + { + int s = src[j]; + dst[j] = (ushort)(s > ithresh ? ithresh2 : s); + } + } else if( depth == CV_32F ) { const float* src = _src.ptr(i); @@ -282,6 +320,16 @@ static void test_threshold( const Mat& _src, Mat& _dst, dst[j] = (short)(s > ithresh ? s : 0); } } + else if( depth == CV_16U ) + { + const ushort* src = _src.ptr(i); + ushort* dst = _dst.ptr(i); + for( j = 0; j < width_n; j++ ) + { + int s = src[j]; + dst[j] = (ushort)(s > ithresh ? s : 0); + } + } else if( depth == CV_32F ) { const float* src = _src.ptr(i); @@ -327,6 +375,16 @@ static void test_threshold( const Mat& _src, Mat& _dst, dst[j] = (short)(s > ithresh ? 0 : s); } } + else if( depth == CV_16U ) + { + const ushort* src = _src.ptr(i); + ushort* dst = _dst.ptr(i); + for( j = 0; j < width_n; j++ ) + { + int s = src[j]; + dst[j] = (ushort)(s > ithresh ? 0 : s); + } + } else if (depth == CV_32F) { const float* src = _src.ptr(i); -- 2.7.4