From b866890b2768d1a9f56a7218d45b08bdebe70370 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Thu, 25 Apr 2013 13:49:45 +0400 Subject: [PATCH] switched to Input/Output Array in abs, sqr, sqrt, exp, log, pow --- modules/gpuarithm/include/opencv2/gpuarithm.hpp | 46 +++--- modules/gpuarithm/src/element_operations.cpp | 164 ++++++++++++--------- modules/gpuarithm/test/test_element_operations.cpp | 118 +++++++-------- 3 files changed, 170 insertions(+), 158 deletions(-) diff --git a/modules/gpuarithm/include/opencv2/gpuarithm.hpp b/modules/gpuarithm/include/opencv2/gpuarithm.hpp index 67fdc81..67dab25 100644 --- a/modules/gpuarithm/include/opencv2/gpuarithm.hpp +++ b/modules/gpuarithm/include/opencv2/gpuarithm.hpp @@ -72,41 +72,35 @@ static inline void divide(double src1, InputArray src2, OutputArray dst, int dty //! 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()); - -//! adds scaled array to another one (dst = alpha*src1 + src2) -static inline void scaleAdd(const GpuMat& src1, double alpha, const GpuMat& src2, GpuMat& dst, Stream& stream = Stream::Null()) -{ - addWeighted(src1, alpha, src2, 1.0, 0.0, dst, -1, stream); -} - //! 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()); +CV_EXPORTS void abs(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); //! computes square of each pixel in an image -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void sqr(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); +CV_EXPORTS void sqr(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); //! computes square root of each pixel in an image -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void sqrt(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); +CV_EXPORTS void sqrt(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); -//! computes exponent of each matrix element (b = e**a) -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void exp(const GpuMat& a, GpuMat& b, Stream& stream = Stream::Null()); +//! computes exponent of each matrix element +CV_EXPORTS void exp(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); -//! computes natural logarithm of absolute value of each matrix element: b = log(abs(a)) -//! supports CV_8U, CV_16U, CV_16S and CV_32F depth -CV_EXPORTS void log(const GpuMat& a, GpuMat& b, Stream& stream = Stream::Null()); +//! computes natural logarithm of absolute value of each matrix element +CV_EXPORTS void log(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); //! computes power of each matrix element: -// (dst(i,j) = pow( src(i,j) , power), if src.type() is integer -// (dst(i,j) = pow(fabs(src(i,j)), power), otherwise -//! supports all, except depth == CV_64F -CV_EXPORTS void pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream = Stream::Null()); +//! (dst(i,j) = pow( src(i,j) , power), if src.type() is integer +//! (dst(i,j) = pow(fabs(src(i,j)), power), otherwise +CV_EXPORTS void pow(InputArray src, double power, 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()); + +//! adds scaled array to another one (dst = alpha*src1 + src2) +static inline void scaleAdd(const GpuMat& src1, double alpha, const GpuMat& src2, GpuMat& dst, Stream& stream = Stream::Null()) +{ + addWeighted(src1, alpha, src2, 1.0, 0.0, dst, -1, stream); +} //! compares elements of two arrays (c = a b) CV_EXPORTS void compare(const GpuMat& a, const GpuMat& b, GpuMat& c, int cmpop, Stream& stream = Stream::Null()); diff --git a/modules/gpuarithm/src/element_operations.cpp b/modules/gpuarithm/src/element_operations.cpp index 181f516..b93f300 100644 --- a/modules/gpuarithm/src/element_operations.cpp +++ b/modules/gpuarithm/src/element_operations.cpp @@ -57,17 +57,17 @@ void cv::gpu::divide(InputArray, InputArray, OutputArray, double, int, Stream&) void cv::gpu::absdiff(InputArray, InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::abs(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::abs(InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::sqr(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::sqr(InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::sqrt(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::sqrt(InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::exp(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::exp(InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::log(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::log(InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::pow(const GpuMat&, double, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::pow(InputArray, double, OutputArray, Stream&) { throw_no_cuda(); } void cv::gpu::compare(const GpuMat&, const GpuMat&, GpuMat&, int, Stream&) { throw_no_cuda(); } void cv::gpu::compare(const GpuMat&, Scalar, GpuMat&, int, Stream&) { throw_no_cuda(); } @@ -1484,7 +1484,7 @@ namespace arithm void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } -void cv::gpu::abs(const GpuMat& src, GpuMat& dst, Stream& stream) +void cv::gpu::abs(InputArray _src, OutputArray _dst, Stream& stream) { using namespace arithm; @@ -1500,6 +1500,8 @@ void cv::gpu::abs(const GpuMat& src, GpuMat& dst, Stream& stream) absMat }; + GpuMat src = _src.getGpuMat(); + const int depth = src.depth(); CV_Assert( depth <= CV_64F ); @@ -1511,7 +1513,8 @@ void cv::gpu::abs(const GpuMat& src, GpuMat& dst, Stream& stream) CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); } - dst.create(src.size(), src.type()); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } @@ -1525,7 +1528,7 @@ namespace arithm void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } -void cv::gpu::sqr(const GpuMat& src, GpuMat& dst, Stream& stream) +void cv::gpu::sqr(InputArray _src, OutputArray _dst, Stream& stream) { using namespace arithm; @@ -1541,6 +1544,8 @@ void cv::gpu::sqr(const GpuMat& src, GpuMat& dst, Stream& stream) sqrMat }; + GpuMat src = _src.getGpuMat(); + const int depth = src.depth(); CV_Assert( depth <= CV_64F ); @@ -1552,7 +1557,8 @@ void cv::gpu::sqr(const GpuMat& src, GpuMat& dst, Stream& stream) CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); } - dst.create(src.size(), src.type()); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } @@ -1566,7 +1572,7 @@ namespace arithm void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } -void cv::gpu::sqrt(const GpuMat& src, GpuMat& dst, Stream& stream) +void cv::gpu::sqrt(InputArray _src, OutputArray _dst, Stream& stream) { using namespace arithm; @@ -1582,6 +1588,8 @@ void cv::gpu::sqrt(const GpuMat& src, GpuMat& dst, Stream& stream) sqrtMat }; + GpuMat src = _src.getGpuMat(); + const int depth = src.depth(); CV_Assert( depth <= CV_64F ); @@ -1593,7 +1601,52 @@ void cv::gpu::sqrt(const GpuMat& src, GpuMat& dst, Stream& stream) CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); } - dst.create(src.size(), src.type()); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); + + funcs[depth](src, dst, StreamAccessor::getStream(stream)); +} + +//////////////////////////////////////////////////////////////////////// +// exp + +namespace arithm +{ + template + void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); +} + +void cv::gpu::exp(InputArray _src, OutputArray _dst, Stream& stream) +{ + using namespace arithm; + + typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); + static const func_t funcs[] = + { + expMat, + expMat, + expMat, + expMat, + expMat, + expMat, + expMat + }; + + GpuMat src = _src.getGpuMat(); + + const int depth = src.depth(); + + CV_Assert( depth <= CV_64F ); + CV_Assert( src.channels() == 1 ); + + if (depth == CV_64F) + { + if (!deviceSupports(NATIVE_DOUBLE)) + CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); + } + + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } @@ -1607,7 +1660,7 @@ namespace arithm void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } -void cv::gpu::log(const GpuMat& src, GpuMat& dst, Stream& stream) +void cv::gpu::log(InputArray _src, OutputArray _dst, Stream& stream) { using namespace arithm; @@ -1623,6 +1676,8 @@ void cv::gpu::log(const GpuMat& src, GpuMat& dst, Stream& stream) logMat }; + GpuMat src = _src.getGpuMat(); + const int depth = src.depth(); CV_Assert( depth <= CV_64F ); @@ -1634,40 +1689,40 @@ void cv::gpu::log(const GpuMat& src, GpuMat& dst, Stream& stream) CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); } - dst.create(src.size(), src.type()); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// -// exp +// pow namespace arithm { - template - void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); + template void pow(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); } -void cv::gpu::exp(const GpuMat& src, GpuMat& dst, Stream& stream) +void cv::gpu::pow(InputArray _src, double power, OutputArray _dst, Stream& stream) { - using namespace arithm; - - typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); + typedef void (*func_t)(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { - expMat, - expMat, - expMat, - expMat, - expMat, - expMat, - expMat + arithm::pow, + arithm::pow, + arithm::pow, + arithm::pow, + arithm::pow, + arithm::pow, + arithm::pow }; + GpuMat src = _src.getGpuMat(); + const int depth = src.depth(); + const int cn = src.channels(); - CV_Assert( depth <= CV_64F ); - CV_Assert( src.channels() == 1 ); + CV_Assert(depth <= CV_64F); if (depth == CV_64F) { @@ -1675,9 +1730,13 @@ void cv::gpu::exp(const GpuMat& src, GpuMat& dst, Stream& stream) CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); } - dst.create(src.size(), src.type()); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); - funcs[depth](src, dst, StreamAccessor::getStream(stream)); + PtrStepSzb src_(src.rows, src.cols * cn, src.data, src.step); + PtrStepSzb dst_(src.rows, src.cols * cn, dst.data, dst.step); + + funcs[depth](src_, power, dst_, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// @@ -2563,47 +2622,6 @@ void cv::gpu::max(const GpuMat& src, double val, GpuMat& dst, Stream& stream) } //////////////////////////////////////////////////////////////////////// -// pow - -namespace arithm -{ - template void pow(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); -} - -void cv::gpu::pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream) -{ - typedef void (*func_t)(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); - static const func_t funcs[] = - { - arithm::pow, - arithm::pow, - arithm::pow, - arithm::pow, - arithm::pow, - arithm::pow, - arithm::pow - }; - - const int depth = src.depth(); - const int cn = src.channels(); - - CV_Assert(depth <= CV_64F); - - if (depth == CV_64F) - { - if (!deviceSupports(NATIVE_DOUBLE)) - CV_Error(cv::Error::StsUnsupportedFormat, "The device doesn't support double"); - } - - dst.create(src.size(), src.type()); - - PtrStepSzb src_(src.rows, src.cols * cn, src.data, src.step); - PtrStepSzb dst_(src.rows, src.cols * cn, dst.data, dst.step); - - funcs[depth](src_, power, dst_, StreamAccessor::getStream(stream)); -} - -//////////////////////////////////////////////////////////////////////// // addWeighted namespace arithm diff --git a/modules/gpuarithm/test/test_element_operations.cpp b/modules/gpuarithm/test/test_element_operations.cpp index 0515a23..d009893 100644 --- a/modules/gpuarithm/test/test_element_operations.cpp +++ b/modules/gpuarithm/test/test_element_operations.cpp @@ -1771,6 +1771,65 @@ INSTANTIATE_TEST_CASE_P(GPU_Arithm, Exp, testing::Combine( WHOLE_SUBMAT)); //////////////////////////////////////////////////////////////////////////////// +// Pow + +PARAM_TEST_CASE(Pow, cv::gpu::DeviceInfo, cv::Size, MatDepth, UseRoi) +{ + cv::gpu::DeviceInfo devInfo; + cv::Size size; + int depth; + bool useRoi; + + virtual void SetUp() + { + devInfo = GET_PARAM(0); + size = GET_PARAM(1); + depth = GET_PARAM(2); + useRoi = GET_PARAM(3); + + cv::gpu::setDevice(devInfo.deviceID()); + } +}; + +GPU_TEST_P(Pow, Accuracy) +{ + cv::Mat src = randomMat(size, depth, 0.0, 10.0); + double power = randomDouble(2.0, 4.0); + + if (src.depth() < CV_32F) + power = static_cast(power); + + if (depth == CV_64F && !supportFeature(devInfo, cv::gpu::NATIVE_DOUBLE)) + { + try + { + cv::gpu::GpuMat dst; + cv::gpu::pow(loadMat(src), power, dst); + } + catch (const cv::Exception& e) + { + ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code); + } + } + else + { + cv::gpu::GpuMat dst = createMat(size, depth, useRoi); + cv::gpu::pow(loadMat(src, useRoi), power, dst); + + cv::Mat dst_gold; + cv::pow(src, power, dst_gold); + + EXPECT_MAT_NEAR(dst_gold, dst, depth < CV_32F ? 0.0 : 1e-1); + } +} + +INSTANTIATE_TEST_CASE_P(GPU_Arithm, Pow, testing::Combine( + ALL_DEVICES, + DIFFERENT_SIZES, + ALL_DEPTH, + WHOLE_SUBMAT)); + +//////////////////////////////////////////////////////////////////////////////// // Compare_Array CV_ENUM(CmpCode, cv::CMP_EQ, cv::CMP_GT, cv::CMP_GE, cv::CMP_LT, cv::CMP_LE, cv::CMP_NE) @@ -2402,65 +2461,6 @@ INSTANTIATE_TEST_CASE_P(GPU_Arithm, Max, testing::Combine( ALL_DEPTH, WHOLE_SUBMAT)); -//////////////////////////////////////////////////////////////////////////////// -// Pow - -PARAM_TEST_CASE(Pow, cv::gpu::DeviceInfo, cv::Size, MatDepth, UseRoi) -{ - cv::gpu::DeviceInfo devInfo; - cv::Size size; - int depth; - bool useRoi; - - virtual void SetUp() - { - devInfo = GET_PARAM(0); - size = GET_PARAM(1); - depth = GET_PARAM(2); - useRoi = GET_PARAM(3); - - cv::gpu::setDevice(devInfo.deviceID()); - } -}; - -GPU_TEST_P(Pow, Accuracy) -{ - cv::Mat src = randomMat(size, depth, 0.0, 10.0); - double power = randomDouble(2.0, 4.0); - - if (src.depth() < CV_32F) - power = static_cast(power); - - if (depth == CV_64F && !supportFeature(devInfo, cv::gpu::NATIVE_DOUBLE)) - { - try - { - cv::gpu::GpuMat dst; - cv::gpu::pow(loadMat(src), power, dst); - } - catch (const cv::Exception& e) - { - ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code); - } - } - else - { - cv::gpu::GpuMat dst = createMat(size, depth, useRoi); - cv::gpu::pow(loadMat(src, useRoi), power, dst); - - cv::Mat dst_gold; - cv::pow(src, power, dst_gold); - - EXPECT_MAT_NEAR(dst_gold, dst, depth < CV_32F ? 0.0 : 1e-1); - } -} - -INSTANTIATE_TEST_CASE_P(GPU_Arithm, Pow, testing::Combine( - ALL_DEVICES, - DIFFERENT_SIZES, - ALL_DEPTH, - WHOLE_SUBMAT)); - ////////////////////////////////////////////////////////////////////////////// // AddWeighted -- 2.7.4