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, diff --git a/modules/cudawarping/src/warp.cpp b/modules/cudawarping/src/warp.cpp index 8690f54085d..839b786ce45 100644 --- a/modules/cudawarping/src/warp.cpp +++ b/modules/cudawarping/src/warp.cpp @@ -208,6 +208,8 @@ void cv::cuda::warpAffine(InputArray _src, OutputArray _dst, InputArray _M, Size _dst.create(dsize, src.type()); GpuMat dst = _dst.getGpuMat(); + CV_Assert( src.data != dst.data && "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,