mirror of
https://github.com/opencv/opencv.git
synced 2026-09-13 13:55:39 -05:00
Merge pull request #29640 from yvonnelxxxx/fix/int-overflow-absdiff
fix: signed-integer-overflow in c_absdiff<int>
This commit is contained in:
@@ -1437,7 +1437,7 @@ The function cv::absdiff calculates:
|
||||
\f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1} - \texttt{src2}(I) |)\f]
|
||||
where I is a multi-dimensional index of array elements. In case of
|
||||
multi-channel arrays, each channel is processed independently.
|
||||
@note Saturation is not applied when the arrays have the depth CV_32S.
|
||||
@note Saturation might not be applied when the arrays have the depth CV_32S.
|
||||
You may even get a negative value in the case of overflow.
|
||||
@note (Python) Be careful to difference behaviour between src1/src2 are single number and they are tuple/array.
|
||||
`absdiff(src,X)` means `absdiff(src,(X,X,X,X))`.
|
||||
|
||||
@@ -168,6 +168,9 @@ inline schar c_absdiff(schar a, schar b)
|
||||
template<>
|
||||
inline short c_absdiff(short a, short b)
|
||||
{ return saturate_cast<short>(std::abs(a - b)); }
|
||||
template<> inline int c_absdiff<int>(int a, int b){
|
||||
return (int)((unsigned)std::max(a, b) - (unsigned)std::min(a, b));
|
||||
}
|
||||
// specializations to prevent "-0" results
|
||||
template<>
|
||||
inline float c_absdiff<float>(float a, float b)
|
||||
|
||||
@@ -2848,6 +2848,39 @@ TEST(Core_ConvertTo, regression_12121)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_AbsDiff, regression_29639_integer_overflow)
|
||||
{
|
||||
const struct { int a, b; } cases[] = {
|
||||
{ INT_MIN, 0 },
|
||||
{ 0, INT_MIN },
|
||||
{ INT_MIN, INT_MAX },
|
||||
{ INT_MAX, INT_MIN },
|
||||
{ INT_MIN, -1 },
|
||||
{ INT_MAX, 0 },
|
||||
{ 7, -5 },
|
||||
};
|
||||
for (const auto& c : cases)
|
||||
{
|
||||
cv::Mat a(3, 11, CV_32SC1, cv::Scalar(c.a));
|
||||
cv::Mat b(3, 11, CV_32SC1, cv::Scalar(c.b));
|
||||
cv::Mat d;
|
||||
cv::absdiff(a, b, d);
|
||||
|
||||
int wraparound = (int)((unsigned)std::max(c.a, c.b) - (unsigned)std::min(c.a, c.b));
|
||||
int64 diff = (int64)c.a - (int64)c.b;
|
||||
int saturated = cv::saturate_cast<int>(diff < 0 ? -diff : diff);
|
||||
|
||||
int first = d.at<int>(0, 0);
|
||||
int last = d.at<int>(d.rows - 1, d.cols - 1);
|
||||
EXPECT_TRUE(first == wraparound || first == saturated)
|
||||
<< "absdiff(" << c.a << ", " << c.b << ") first element (vector path) = "
|
||||
<< first << ", expected wraparound " << wraparound << " or saturate " << saturated;
|
||||
EXPECT_TRUE(last == wraparound || last == saturated)
|
||||
<< "absdiff(" << c.a << ", " << c.b << ") last element (scalar remainder) = "
|
||||
<< last << ", expected wraparound " << wraparound << " or saturate " << saturated;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_MeanStdDev, regression_multichannel)
|
||||
{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user