From fc2ee2047e4a4cd392a7523b999fb8f769d9ecf4 Mon Sep 17 00:00:00 2001 From: Havard Haug Date: Fri, 1 Aug 2025 00:40:04 +0200 Subject: [PATCH 1/3] Add assert to ensure non-overlapping memory regions are used for the warpaffine function --- modules/cudawarping/src/warp.cpp | 13 ++++++++ modules/cudawarping/test/test_warp_affine.cpp | 30 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/modules/cudawarping/src/warp.cpp b/modules/cudawarping/src/warp.cpp index 8690f54085d..15c583a7923 100644 --- a/modules/cudawarping/src/warp.cpp +++ b/modules/cudawarping/src/warp.cpp @@ -208,6 +208,19 @@ void cv::cuda::warpAffine(InputArray _src, OutputArray _dst, InputArray _M, Size _dst.create(dsize, src.type()); GpuMat dst = _dst.getGpuMat(); + const uchar* src_start = src.data; + const uchar* dst_start = dst.data; + + size_t src_size = src.step * src.rows; + size_t dst_size = dst.step * dst.rows; + + const uchar* src_end = src_start + src_size; + const uchar* dst_end = dst_start + dst_size; + + bool overlap = src_end > dst_start && dst_end > src_start; + + CV_Assert(!overlap && "In-place operation not supported for cv::cuda::warpAffine"); + Size wholeSize; Point ofs; src.locateROI(wholeSize, ofs); diff --git a/modules/cudawarping/test/test_warp_affine.cpp b/modules/cudawarping/test/test_warp_affine.cpp index d26a5fdeb7c..ebbba914ced 100644 --- a/modules/cudawarping/test/test_warp_affine.cpp +++ b/modules/cudawarping/test/test_warp_affine.cpp @@ -222,6 +222,36 @@ CUDA_TEST_P(WarpAffine, Accuracy) EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-1 : 1.0); } +CUDA_TEST_P(WarpAffine, OverlapDetection) +{ + cv::Mat src = randomMat(size, type); + ASSERT_FALSE(src.empty()); + cv::cuda::GpuMat gpuSrc; + gpuSrc.upload(src); + + cv::Mat M = cv::Mat::eye(2, 3, CV_64FC1); + int flags = interpolation; + if (inverse) + flags |= cv::WARP_INVERSE_MAP; + + { + cv::cuda::GpuMat gpuDst(gpuSrc, cv::Rect(0, 0, size.width, size.height)); + + EXPECT_THROW( + cv::cuda::warpAffine(gpuSrc, gpuDst, M, size, flags, borderType, cv::Scalar::all(0)), + cv::Exception); + } + + { + cv::cuda::GpuMat gpuDst(size, gpuSrc.type()); + ASSERT_NE(gpuSrc.data, gpuDst.data); // Confirm they are distinct + + EXPECT_NO_THROW({ + cv::cuda::warpAffine(gpuSrc, gpuDst, M, size, flags, borderType, cv::Scalar::all(0)); + }); + } +} + INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpAffine, testing::Combine( ALL_DEVICES, DIFFERENT_SIZES, From 46d015eeb7c7fab08a3057bfc43767e8bbe7d673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Haug?= Date: Sat, 2 Aug 2025 21:04:04 +0000 Subject: [PATCH 2/3] Document that cudas warpaffine function requires src != dst --- modules/cudawarping/include/opencv2/cudawarping.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/cudawarping/include/opencv2/cudawarping.hpp b/modules/cudawarping/include/opencv2/cudawarping.hpp index b9ca957358e..6c920fa8c24 100644 --- a/modules/cudawarping/include/opencv2/cudawarping.hpp +++ b/modules/cudawarping/include/opencv2/cudawarping.hpp @@ -118,6 +118,7 @@ CV_EXPORTS_W void resize(InputArray src, OutputArray dst, Size dsize, double fx= @param src Source image. CV_8U , CV_16U , CV_32S , or CV_32F depth and 1, 3, or 4 channels are supported. @param dst Destination image with the same type as src . The size is dsize . + **In-place operation (src == dst) is not supported and will result in an error.** @param M *2x3* Mat or UMat transformation matrix. @param dsize Size of the destination image. @param flags Combination of interpolation methods (see resize) and the optional flag @@ -127,6 +128,7 @@ INTER_NEAREST , INTER_LINEAR , and INTER_CUBIC interpolation methods are support @param borderValue @param stream Stream for the asynchronous version. +@note In-place operation is not supported. If src and dst refer to the same data, the behavior is undefined. @sa warpAffine */ CV_EXPORTS void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, From 9a4f16d1dd4fca6dc017cea44a13453c62ab1e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Haug?= Date: Mon, 4 Aug 2025 10:29:59 +0000 Subject: [PATCH 3/3] Assert that src and dst data are not equal for warpaffine --- modules/cudawarping/src/warp.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/modules/cudawarping/src/warp.cpp b/modules/cudawarping/src/warp.cpp index 15c583a7923..839b786ce45 100644 --- a/modules/cudawarping/src/warp.cpp +++ b/modules/cudawarping/src/warp.cpp @@ -208,18 +208,7 @@ void cv::cuda::warpAffine(InputArray _src, OutputArray _dst, InputArray _M, Size _dst.create(dsize, src.type()); GpuMat dst = _dst.getGpuMat(); - const uchar* src_start = src.data; - const uchar* dst_start = dst.data; - - size_t src_size = src.step * src.rows; - size_t dst_size = dst.step * dst.rows; - - const uchar* src_end = src_start + src_size; - const uchar* dst_end = dst_start + dst_size; - - bool overlap = src_end > dst_start && dst_end > src_start; - - CV_Assert(!overlap && "In-place operation not supported for cv::cuda::warpAffine"); + CV_Assert( src.data != dst.data && "In-place operation not supported for cv::cuda::warpAffine" ); Size wholeSize; Point ofs;