diff --git a/modules/cudaarithm/src/cuda/absdiff_mat.cu b/modules/cudaarithm/src/cuda/absdiff_mat.cu index da475563e25..1df17751daf 100644 --- a/modules/cudaarithm/src/cuda/absdiff_mat.cu +++ b/modules/cudaarithm/src/cuda/absdiff_mat.cu @@ -49,6 +49,7 @@ #else #include "opencv2/cudev.hpp" +#include using namespace cv::cudev; @@ -77,6 +78,16 @@ namespace } }; + template <> struct AbsDiffOp1 : binary_function + { + __device__ __forceinline__ int operator ()(int a, int b) const + { + const long long diff = static_cast(a) - static_cast(b); + const long long absDiff = diff < 0 ? -diff : diff; + return static_cast(absDiff > INT_MAX ? INT_MAX : absDiff); + } + }; + template struct TransformPolicy : DefaultTransformPolicy { }; diff --git a/modules/cudaarithm/test/test_element_operations.cpp b/modules/cudaarithm/test/test_element_operations.cpp index 46e156d993e..537eb9dde2d 100644 --- a/modules/cudaarithm/test/test_element_operations.cpp +++ b/modules/cudaarithm/test/test_element_operations.cpp @@ -1404,6 +1404,23 @@ CUDA_TEST_P(AbsDiff, Array) } } +CUDA_TEST_P(AbsDiff, IntMin) +{ + if (depth != CV_32S) + return; + + cv::Mat src1 = (cv::Mat_(1, 2) << std::numeric_limits::min(), 0); + cv::Mat src2 = (cv::Mat_(1, 2) << 0, std::numeric_limits::min()); + + cv::Mat expected = (cv::Mat_(1, 2) << std::numeric_limits::max(), + std::numeric_limits::max()); + + cv::cuda::GpuMat dst; + cv::cuda::absdiff(loadMat(src1), loadMat(src2), dst); + + EXPECT_MAT_NEAR(expected, dst, 0.0); +} + CUDA_TEST_P(AbsDiff, Scalar) { cv::Mat src = randomMat(size, depth);