Merge pull request #21258 from eplankin:fix_threshold_to_zero_ipp_bug
authoreplankin <elena.plankina@intel.com>
Fri, 17 Dec 2021 13:31:37 +0000 (16:31 +0300)
committerGitHub <noreply@github.com>
Fri, 17 Dec 2021 13:31:37 +0000 (13:31 +0000)
Fixed threshold(THRESH_TOZERO) at imgproc(IPP)

* Fixed #16085: imgproc(IPP): wrong result from threshold(THRESH_TOZERO)

* 1. Added test cases with float where all bits of mantissa equal 1, min and max float as inputs
2. Used nextafterf instead of cast to hex

* Used float value in test instead of hex and casts

* Changed input value in test

modules/imgproc/src/thresh.cpp
modules/imgproc/test/test_thresh.cpp

index 2e6690e..c3799d8 100644 (file)
@@ -774,16 +774,14 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
             }
             setIppErrorStatus();
             break;
-#if 0  // details: https://github.com/opencv/opencv/pull/16085
         case THRESH_TOZERO:
-            if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh + FLT_EPSILON, 0))
+            if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, nextafterf(thresh, std::numeric_limits<float>::infinity()), 0))
             {
                 CV_IMPL_ADD(CV_IMPL_IPP);
                 return;
             }
             setIppErrorStatus();
             break;
-#endif
         case THRESH_TOZERO_INV:
             if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0))
             {
index a8e9616..f51afa1 100644 (file)
@@ -443,4 +443,34 @@ TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_16085)
     EXPECT_EQ(0, cv::norm(result, NORM_INF));
 }
 
+TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_21258)
+{
+    Size sz(16, 16);
+    float val = nextafterf(16.0f, 0.0f);  // 0x417fffff, all bits in mantissa are 1
+    Mat input(sz, CV_32F, Scalar::all(val));
+    Mat result;
+    cv::threshold(input, result, val, 0.0, THRESH_TOZERO);
+    EXPECT_EQ(0, cv::norm(result, NORM_INF));
+}
+
+TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_21258_Min)
+{
+    Size sz(16, 16);
+    float min_val = -std::numeric_limits<float>::max();
+    Mat input(sz, CV_32F, Scalar::all(min_val));
+    Mat result;
+    cv::threshold(input, result, min_val, 0.0, THRESH_TOZERO);
+    EXPECT_EQ(0, cv::norm(result, NORM_INF));
+}
+
+TEST(Imgproc_Threshold, regression_THRESH_TOZERO_IPP_21258_Max)
+{
+    Size sz(16, 16);
+    float max_val = std::numeric_limits<float>::max();
+    Mat input(sz, CV_32F, Scalar::all(max_val));
+    Mat result;
+    cv::threshold(input, result, max_val, 0.0, THRESH_TOZERO);
+    EXPECT_EQ(0, cv::norm(result, NORM_INF));
+}
+
 }} // namespace