Fix potential NaN in cv::norm.
authorVincent Rabaud <vrabaud@google.com>
Fri, 11 Jun 2021 20:03:33 +0000 (22:03 +0200)
committerVincent Rabaud <vrabaud@google.com>
Tue, 15 Jun 2021 12:58:11 +0000 (14:58 +0200)
There can be an int overflow.
cv::norm( InputArray _src, int normType, InputArray _mask ) is fine,
not cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask ).

modules/core/src/norm.cpp
modules/core/test/test_arithm.cpp

index 601082783e3cac1744d3200fddcde6d371e240ed..fad641554dac3fa092752193b70d1aac15bbe47f 100644 (file)
@@ -1171,7 +1171,7 @@ double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask
         // special case to handle "integer" overflow in accumulator
         const size_t esz = src1.elemSize();
         const int total = (int)it.size;
-        const int intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15);
+        const int intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
         const int blockSize = std::min(total, intSumBlockSize);
         int isum = 0;
         int count = 0;
index 2746feb2f245661ac82f942f880f494c08dbbe9b..74bf39fbc7a2281098736261eecabfc0f4a274f8 100644 (file)
@@ -2117,6 +2117,15 @@ TEST(Core_Norm, IPP_regression_NORM_L1_16UC3_small)
     EXPECT_EQ((double)20*cn, cv::norm(a, b, NORM_L1, mask));
 }
 
+TEST(Core_Norm, NORM_L2_8UC4)
+{
+    // Tests there is no integer overflow in norm computation for multiple channels.
+    const int kSide = 100;
+    cv::Mat4b a(kSide, kSide, cv::Scalar(255, 255, 255, 255));
+    cv::Mat4b b = cv::Mat4b::zeros(kSide, kSide);
+    const double kNorm = 2.*kSide*255.;
+    EXPECT_EQ(kNorm, cv::norm(a, b, NORM_L2));
+}
 
 TEST(Core_ConvertTo, regression_12121)
 {