From ca245e995a4e59e24ae359f0edd1418117838762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arvid=20Piehl=20Lauritsen=20B=C3=B6ttiger?= Date: Mon, 18 Sep 2017 15:33:14 +0300 Subject: [PATCH] Added support for thresholding CV_16U images. --- modules/imgproc/src/thresh.cpp | 230 +++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 729d77da93..b6b0c2ca1f 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -269,6 +269,204 @@ 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; + } + + // HAVE_TEGRA_OPTIMIZATION not supported + + // HAVE_IPP not supported + + int j = 0; + const ushort* src = _src.ptr(); + ushort* dst = _dst.ptr(); + + // CV_SIMD128 not supported +#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 +#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; + } + } +} + static void thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) @@ -1178,6 +1376,10 @@ public: else if( srcStripe.depth() == CV_16S ) { thresh_16s( srcStripe, dstStripe, (short)thresh, (short)maxval, thresholdType ); + } + else if( srcStripe.depth() == CV_16U ) + { + thresh_16u( srcStripe, dstStripe, (ushort)thresh, (ushort)maxval, thresholdType ); } else if( srcStripe.depth() == CV_32F ) { @@ -1422,6 +1624,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_32F ) ; else if( src.depth() == CV_64F )