From 5ec8c51b981b10bce64a70d859f25510aec82e41 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov <vlad.vinogradov@itseez.com> Date: Thu, 25 Apr 2013 13:37:44 +0400 Subject: [PATCH] switched to Input/Output Array in gpu::absdiff --- .../gpuarithm/include/opencv2/gpuarithm.hpp | 8 +- modules/gpuarithm/src/element_operations.cpp | 86 +++++++------------ .../test/test_element_operations.cpp | 29 +++++++ 3 files changed, 64 insertions(+), 59 deletions(-) diff --git a/modules/gpuarithm/include/opencv2/gpuarithm.hpp b/modules/gpuarithm/include/opencv2/gpuarithm.hpp index 2fc6b48de..67fdc819e 100644 --- a/modules/gpuarithm/include/opencv2/gpuarithm.hpp +++ b/modules/gpuarithm/include/opencv2/gpuarithm.hpp @@ -69,6 +69,9 @@ static inline void divide(double src1, InputArray src2, OutputArray dst, int dty divide(src1, src2, dst, 1.0, dtype, stream); } +//! computes element-wise absolute difference of two arrays (dst = abs(src1 - src2)) +CV_EXPORTS void absdiff(InputArray src1, InputArray src2, OutputArray dst, Stream& stream = Stream::Null()); + //! computes the weighted sum of two arrays (dst = alpha*src1 + beta*src2 + gamma) CV_EXPORTS void addWeighted(const GpuMat& src1, double alpha, const GpuMat& src2, double beta, double gamma, GpuMat& dst, int dtype = -1, Stream& stream = Stream::Null()); @@ -79,11 +82,6 @@ static inline void scaleAdd(const GpuMat& src1, double alpha, const GpuMat& src2 addWeighted(src1, alpha, src2, 1.0, 0.0, dst, -1, stream); } -//! computes element-wise absolute difference of two arrays (c = abs(a - b)) -CV_EXPORTS void absdiff(const GpuMat& a, const GpuMat& b, GpuMat& c, Stream& stream = Stream::Null()); -//! computes element-wise absolute difference of array and scalar (c = abs(a - s)) -CV_EXPORTS void absdiff(const GpuMat& a, const Scalar& s, GpuMat& c, Stream& stream = Stream::Null()); - //! computes absolute value of each matrix element //! supports CV_16S and CV_32F depth CV_EXPORTS void abs(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); diff --git a/modules/gpuarithm/src/element_operations.cpp b/modules/gpuarithm/src/element_operations.cpp index 24f67b7db..181f5161d 100644 --- a/modules/gpuarithm/src/element_operations.cpp +++ b/modules/gpuarithm/src/element_operations.cpp @@ -55,8 +55,7 @@ void cv::gpu::multiply(InputArray, InputArray, OutputArray, double, int, Stream& void cv::gpu::divide(InputArray, InputArray, OutputArray, double, int, Stream&) { throw_no_cuda(); } -void cv::gpu::absdiff(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } -void cv::gpu::absdiff(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::absdiff(InputArray, InputArray, OutputArray, Stream&) { throw_no_cuda(); } void cv::gpu::abs(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } @@ -1380,37 +1379,24 @@ namespace arithm void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); } -void cv::gpu::absdiff(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& s) +static void absDiffMat(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat&, double, Stream& _stream) { - using namespace arithm; - typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { - absDiffMat<unsigned char>, - absDiffMat<signed char>, - absDiffMat<unsigned short>, - absDiffMat<short>, - absDiffMat<int>, - absDiffMat<float>, - absDiffMat<double> + arithm::absDiffMat<unsigned char>, + arithm::absDiffMat<signed char>, + arithm::absDiffMat<unsigned short>, + arithm::absDiffMat<short>, + arithm::absDiffMat<int>, + arithm::absDiffMat<float>, + arithm::absDiffMat<double> }; const int depth = src1.depth(); const int cn = src1.channels(); - CV_Assert( depth <= CV_64F ); - CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); - - if (depth == CV_64F) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); - } - - dst.create(src1.size(), src1.type()); - - cudaStream_t stream = StreamAccessor::getStream(s); + cudaStream_t stream = StreamAccessor::getStream(_stream); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); @@ -1430,10 +1416,10 @@ void cv::gpu::absdiff(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Strea { const int vcols = src1_.cols >> 2; - absDiffMat_v4(PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src1_.data, src1_.step), - PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src2_.data, src2_.step), - PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) dst_.data, dst_.step), - stream); + arithm::absDiffMat_v4(PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src1_.data, src1_.step), + PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src2_.data, src2_.step), + PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) dst_.data, dst_.step), + stream); return; } @@ -1441,10 +1427,10 @@ void cv::gpu::absdiff(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Strea { const int vcols = src1_.cols >> 1; - absDiffMat_v2(PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src1_.data, src1_.step), - PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src2_.data, src2_.step), - PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) dst_.data, dst_.step), - stream); + arithm::absDiffMat_v2(PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src1_.data, src1_.step), + PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) src2_.data, src2_.step), + PtrStepSz<unsigned int>(src1_.rows, vcols, (unsigned int*) dst_.data, dst_.step), + stream); return; } @@ -1465,36 +1451,28 @@ namespace arithm void absDiffScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); } -void cv::gpu::absdiff(const GpuMat& src1, const Scalar& src2, GpuMat& dst, Stream& stream) +static void absDiffScalar(const GpuMat& src, Scalar val, bool, GpuMat& dst, const GpuMat&, double, Stream& stream) { - using namespace arithm; - typedef void (*func_t)(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { - absDiffScalar<unsigned char, float>, - absDiffScalar<signed char, float>, - absDiffScalar<unsigned short, float>, - absDiffScalar<short, float>, - absDiffScalar<int, float>, - absDiffScalar<float, float>, - absDiffScalar<double, double> + arithm::absDiffScalar<unsigned char, float>, + arithm::absDiffScalar<signed char, float>, + arithm::absDiffScalar<unsigned short, float>, + arithm::absDiffScalar<short, float>, + arithm::absDiffScalar<int, float>, + arithm::absDiffScalar<float, float>, + arithm::absDiffScalar<double, double> }; - const int depth = src1.depth(); + const int depth = src.depth(); - CV_Assert( depth <= CV_64F ); - CV_Assert( src1.channels() == 1 ); + funcs[depth](src, val[0], dst, StreamAccessor::getStream(stream)); +} - if (depth == CV_64F) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); - } - - dst.create(src1.size(), src1.type()); - - funcs[depth](src1, src2.val[0], dst, StreamAccessor::getStream(stream)); +void cv::gpu::absdiff(InputArray src1, InputArray src2, OutputArray dst, Stream& stream) +{ + arithm_op(src1, src2, dst, noArray(), 1.0, -1, stream, absDiffMat, absDiffScalar); } ////////////////////////////////////////////////////////////////////////////// diff --git a/modules/gpuarithm/test/test_element_operations.cpp b/modules/gpuarithm/test/test_element_operations.cpp index 345c96015..0515a23ad 100644 --- a/modules/gpuarithm/test/test_element_operations.cpp +++ b/modules/gpuarithm/test/test_element_operations.cpp @@ -1433,6 +1433,35 @@ GPU_TEST_P(AbsDiff, Scalar) } } +GPU_TEST_P(AbsDiff, Scalar_First) +{ + cv::Mat src = randomMat(size, depth); + cv::Scalar val = randomScalar(0.0, 255.0); + + if (depth == CV_64F && !supportFeature(devInfo, cv::gpu::NATIVE_DOUBLE)) + { + try + { + cv::gpu::GpuMat dst; + cv::gpu::absdiff(val, loadMat(src), dst); + } + catch (const cv::Exception& e) + { + ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code); + } + } + else + { + cv::gpu::GpuMat dst = createMat(size, depth, useRoi); + cv::gpu::absdiff(val, loadMat(src, useRoi), dst); + + cv::Mat dst_gold; + cv::absdiff(val, src, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, depth <= CV_32F ? 1.0 : 1e-5); + } +} + INSTANTIATE_TEST_CASE_P(GPU_Arithm, AbsDiff, testing::Combine( ALL_DEVICES, DIFFERENT_SIZES,