diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index db2f67da7d..57c15a30d4 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -2805,7 +2805,8 @@ The function can process the image in-place. @param src Source 8-bit single-channel image. @param dst Destination image of the same size and the same type as src. @param maxValue Non-zero value assigned to the pixels for which the condition is satisfied -@param adaptiveMethod Adaptive thresholding algorithm to use, see cv::AdaptiveThresholdTypes +@param adaptiveMethod Adaptive thresholding algorithm to use, see cv::AdaptiveThresholdTypes. +The BORDER_REPLICATE | BORDER_ISOLATED is used to process boundaries. @param thresholdType Thresholding type that must be either THRESH_BINARY or THRESH_BINARY_INV, see cv::ThresholdTypes. @param blockSize Size of a pixel neighborhood that is used to calculate a threshold value for the diff --git a/modules/imgproc/include/opencv2/imgproc/hal/interface.h b/modules/imgproc/include/opencv2/imgproc/hal/interface.h index 23eb0baa40..f8dbcfe791 100644 --- a/modules/imgproc/include/opencv2/imgproc/hal/interface.h +++ b/modules/imgproc/include/opencv2/imgproc/hal/interface.h @@ -21,6 +21,26 @@ #define CV_HAL_MORPH_DILATE 1 //! @} +//! @name Threshold types +//! @sa cv::ThresholdTypes +//! @{ +#define CV_HAL_THRESH_BINARY 0 +#define CV_HAL_THRESH_BINARY_INV 1 +#define CV_HAL_THRESH_TRUNC 2 +#define CV_HAL_THRESH_TOZERO 3 +#define CV_HAL_THRESH_TOZERO_INV 4 +#define CV_HAL_THRESH_MASK 7 +#define CV_HAL_THRESH_OTSU 8 +#define CV_HAL_THRESH_TRIANGLE 16 +//! @} + +//! @name Adaptive threshold algorithm +//! @sa cv::AdaptiveThresholdTypes +//! @{ +#define CV_HAL_ADAPTIVE_THRESH_MEAN_C 0 +#define CV_HAL_ADAPTIVE_THRESH_GAUSSIAN_C 1 +//! @} + //! @} #endif diff --git a/modules/imgproc/perf/perf_threshold.cpp b/modules/imgproc/perf/perf_threshold.cpp index 846f1a0290..bbe151dac9 100644 --- a/modules/imgproc/perf/perf_threshold.cpp +++ b/modules/imgproc/perf/perf_threshold.cpp @@ -60,15 +60,16 @@ PERF_TEST_P(Size_Only, threshold_otsu, testing::Values(TYPICAL_MAT_SIZES)) CV_ENUM(AdaptThreshType, THRESH_BINARY, THRESH_BINARY_INV) CV_ENUM(AdaptThreshMethod, ADAPTIVE_THRESH_MEAN_C, ADAPTIVE_THRESH_GAUSSIAN_C) -typedef std::tr1::tuple Size_AdaptThreshType_AdaptThreshMethod_BlockSize_t; -typedef perf::TestBaseWithParam Size_AdaptThreshType_AdaptThreshMethod_BlockSize; +typedef std::tr1::tuple Size_AdaptThreshType_AdaptThreshMethod_BlockSize_Delta_t; +typedef perf::TestBaseWithParam Size_AdaptThreshType_AdaptThreshMethod_BlockSize_Delta; -PERF_TEST_P(Size_AdaptThreshType_AdaptThreshMethod_BlockSize, adaptiveThreshold, +PERF_TEST_P(Size_AdaptThreshType_AdaptThreshMethod_BlockSize_Delta, adaptiveThreshold, testing::Combine( testing::Values(TYPICAL_MAT_SIZES), AdaptThreshType::all(), AdaptThreshMethod::all(), - testing::Values(3, 5) + testing::Values(3, 5), + testing::Values(0.0, 10.0) ) ) { @@ -76,12 +77,14 @@ PERF_TEST_P(Size_AdaptThreshType_AdaptThreshMethod_BlockSize, adaptiveThreshold, AdaptThreshType adaptThreshType = get<1>(GetParam()); AdaptThreshMethod adaptThreshMethod = get<2>(GetParam()); int blockSize = get<3>(GetParam()); + double C = get<4>(GetParam()); double maxValue = theRNG().uniform(1, 254); - double C = 10.0; int type = CV_8UC1; - Mat src(sz, type); + + Mat src_full(cv::Size(sz.width + 2, sz.height + 2), type); + Mat src = src_full(cv::Rect(1, 1, sz.width, sz.height)); Mat dst(sz, type); declare.in(src, WARMUP_RNG).out(dst); diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index f43fc70ee0..be05644067 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -630,6 +630,40 @@ inline int hal_ni_medianBlur(const uchar* src_data, size_t src_step, uchar* dst_ #define cv_hal_medianBlur hal_ni_medianBlur //! @endcond +/** + @brief Calculates adaptive threshold + @param src_data,src_step Source image + @param dst_data,dst_step Destination image + @param width,height Source image dimensions + @param maxValue Value assigned to the pixels for which the condition is satisfied + @param adaptiveMethod Adaptive thresholding algorithm + @param thresholdType Thresholding type + @param blockSize Size of a pixel neighborhood that is used to calculate a threshold value + @param C Constant subtracted from the mean or weighted mean +*/ +inline int hal_ni_adaptiveThreshold(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_adaptiveThreshold hal_ni_adaptiveThreshold +//! @endcond + +/** + @brief Calculates fixed-level threshold to each array element + @param src_data,src_step Source image + @param dst_data,dst_step Destination image + @param width,height Source image dimensions + @param depth Depths of source and destination image + @param cn Number of channels + @param thresh Threshold value + @param maxValue Value assigned to the pixels for which the condition is satisfied + @param thresholdType Thresholding type +*/ +inline int hal_ni_threshold(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int depth, int cn, double thresh, double maxValue, int thresholdType) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_threshold hal_ni_threshold +//! @endcond + //! @} #if defined __GNUC__ diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index f7ad1955a8..8cf17aebb1 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -1214,6 +1214,10 @@ public: Mat srcStripe = src.rowRange(row0, row1); Mat dstStripe = dst.rowRange(row0, row1); + CALL_HAL(threshold, cv_hal_threshold, srcStripe.data, srcStripe.step, dstStripe.data, dstStripe.step, + srcStripe.cols, srcStripe.rows, srcStripe.depth(), srcStripe.channels(), + thresh, maxval, thresholdType); + if (srcStripe.depth() == CV_8U) { thresh_8u( srcStripe, dstStripe, (uchar)thresh, (uchar)maxval, thresholdType ); @@ -1530,6 +1534,9 @@ void cv::adaptiveThreshold( InputArray _src, OutputArray _dst, double maxValue, return; } + CALL_HAL(adaptiveThreshold, cv_hal_adaptiveThreshold, src.data, src.step, dst.data, dst.step, src.cols, src.rows, + maxValue, method, type, blockSize, delta); + Mat mean; if( src.data != dst.data ) @@ -1537,13 +1544,13 @@ void cv::adaptiveThreshold( InputArray _src, OutputArray _dst, double maxValue, if (method == ADAPTIVE_THRESH_MEAN_C) boxFilter( src, mean, src.type(), Size(blockSize, blockSize), - Point(-1,-1), true, BORDER_REPLICATE ); + Point(-1,-1), true, BORDER_REPLICATE|BORDER_ISOLATED ); else if (method == ADAPTIVE_THRESH_GAUSSIAN_C) { Mat srcfloat,meanfloat; src.convertTo(srcfloat,CV_32F); meanfloat=srcfloat; - GaussianBlur(srcfloat, meanfloat, Size(blockSize, blockSize), 0, 0, BORDER_REPLICATE); + GaussianBlur(srcfloat, meanfloat, Size(blockSize, blockSize), 0, 0, BORDER_REPLICATE|BORDER_ISOLATED); meanfloat.convertTo(mean, src.type()); } else