From 6d6ff268872bc3e650af6e264a66fcce5fbc62cd Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Fri, 26 Apr 2013 17:18:56 +0400 Subject: [PATCH] refactored gpu::ImagePyramid (converted it to abstract interface) --- .../gpuwarping/include/opencv2/gpuwarping.hpp | 26 +--- modules/gpuwarping/perf/perf_warping.cpp | 43 +----- modules/gpuwarping/src/pyramids.cpp | 140 +++++++++++------- 3 files changed, 89 insertions(+), 120 deletions(-) diff --git a/modules/gpuwarping/include/opencv2/gpuwarping.hpp b/modules/gpuwarping/include/opencv2/gpuwarping.hpp index 5b140682e3..ed17464ec4 100644 --- a/modules/gpuwarping/include/opencv2/gpuwarping.hpp +++ b/modules/gpuwarping/include/opencv2/gpuwarping.hpp @@ -100,32 +100,14 @@ CV_EXPORTS void pyrDown(InputArray src, OutputArray dst, Stream& stream = Stream //! upsamples the source image and then smoothes it CV_EXPORTS void pyrUp(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); -class CV_EXPORTS ImagePyramid +class CV_EXPORTS ImagePyramid : public Algorithm { public: - inline ImagePyramid() : nLayers_(0) {} - inline ImagePyramid(const GpuMat& img, int nLayers, Stream& stream = Stream::Null()) - { - build(img, nLayers, stream); - } - - void build(const GpuMat& img, int nLayers, Stream& stream = Stream::Null()); - - void getLayer(GpuMat& outImg, Size outRoi, Stream& stream = Stream::Null()) const; - - inline void release() - { - layer0_.release(); - pyramid_.clear(); - nLayers_ = 0; - } - -private: - GpuMat layer0_; - std::vector pyramid_; - int nLayers_; + virtual void getLayer(OutputArray outImg, Size outRoi, Stream& stream = Stream::Null()) const = 0; }; +CV_EXPORTS Ptr createImagePyramid(InputArray img, int nLayers = -1, Stream& stream = Stream::Null()); + }} // namespace cv { namespace gpu { #endif /* __OPENCV_GPUWARPING_HPP__ */ diff --git a/modules/gpuwarping/perf/perf_warping.cpp b/modules/gpuwarping/perf/perf_warping.cpp index fd555cbe56..266475bb0c 100644 --- a/modules/gpuwarping/perf/perf_warping.cpp +++ b/modules/gpuwarping/perf/perf_warping.cpp @@ -515,45 +515,6 @@ PERF_TEST_P(Sz_Depth_Cn, PyrUp, } } -////////////////////////////////////////////////////////////////////// -// ImagePyramidBuild - -PERF_TEST_P(Sz_Depth_Cn, ImagePyramidBuild, - Combine(GPU_TYPICAL_MAT_SIZES, - Values(CV_8U, CV_16U, CV_32F), - GPU_CHANNELS_1_3_4)) -{ - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - const int nLayers = 5; - const cv::Size dstSize(size.width / 2 + 10, size.height / 2 + 10); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - - cv::gpu::ImagePyramid d_pyr; - - TEST_CYCLE() d_pyr.build(d_src, nLayers); - - cv::gpu::GpuMat dst; - d_pyr.getLayer(dst, dstSize); - - GPU_SANITY_CHECK(dst); - } - else - { - FAIL_NO_CPU(); - } -} - ////////////////////////////////////////////////////////////////////// // ImagePyramidGetLayer @@ -579,9 +540,9 @@ PERF_TEST_P(Sz_Depth_Cn, ImagePyramidGetLayer, const cv::gpu::GpuMat d_src(src); cv::gpu::GpuMat dst; - cv::gpu::ImagePyramid d_pyr(d_src, nLayers); + cv::Ptr d_pyr = cv::gpu::createImagePyramid(d_src, nLayers); - TEST_CYCLE() d_pyr.getLayer(dst, dstSize); + TEST_CYCLE() d_pyr->getLayer(dst, dstSize); GPU_SANITY_CHECK(dst); } diff --git a/modules/gpuwarping/src/pyramids.cpp b/modules/gpuwarping/src/pyramids.cpp index 39812352d8..577ed85677 100644 --- a/modules/gpuwarping/src/pyramids.cpp +++ b/modules/gpuwarping/src/pyramids.cpp @@ -42,13 +42,15 @@ #include "precomp.hpp" +using namespace cv; +using namespace cv::gpu; + #if !defined HAVE_CUDA || defined(CUDA_DISABLER) void cv::gpu::pyrDown(InputArray, OutputArray, Stream&) { throw_no_cuda(); } void cv::gpu::pyrUp(InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::ImagePyramid::build(const GpuMat&, int, Stream&) { throw_no_cuda(); } -void cv::gpu::ImagePyramid::getLayer(GpuMat&, Size, Stream&) const { throw_no_cuda(); } +Ptr cv::gpu::createImagePyramid(InputArray, int, Stream&) { throw_no_cuda(); return Ptr(); } #else // HAVE_CUDA @@ -134,84 +136,108 @@ void cv::gpu::pyrUp(InputArray _src, OutputArray _dst, Stream& stream) ////////////////////////////////////////////////////////////////////////////// // ImagePyramid -void cv::gpu::ImagePyramid::build(const GpuMat& img, int numLayers, Stream& stream) -{ -#ifndef HAVE_OPENCV_GPULEGACY - (void) img; - (void) numLayers; - (void) stream; - throw_no_cuda(); -#else - CV_Assert(img.depth() <= CV_32F && img.channels() <= 4); +#ifdef HAVE_OPENCV_GPULEGACY - layer0_ = img; - Size szLastLayer = img.size(); - nLayers_ = 1; +namespace +{ + class ImagePyramidImpl : public ImagePyramid + { + public: + ImagePyramidImpl(InputArray img, int nLayers, Stream& stream); - if (numLayers <= 0) - numLayers = 255; //it will cut-off when any of the dimensions goes 1 + void getLayer(OutputArray outImg, Size outRoi, Stream& stream = Stream::Null()) const; - pyramid_.resize(numLayers); + private: + GpuMat layer0_; + std::vector pyramid_; + int nLayers_; + }; - for (int i = 0; i < numLayers - 1; ++i) + ImagePyramidImpl::ImagePyramidImpl(InputArray _img, int numLayers, Stream& stream) { - Size szCurLayer(szLastLayer.width / 2, szLastLayer.height / 2); + GpuMat img = _img.getGpuMat(); - if (szCurLayer.width == 0 || szCurLayer.height == 0) - break; + CV_Assert( img.depth() <= CV_32F && img.channels() <= 4 ); - ensureSizeIsEnough(szCurLayer, img.type(), pyramid_[i]); - nLayers_++; + img.copyTo(layer0_, stream); - const GpuMat& prevLayer = i == 0 ? layer0_ : pyramid_[i - 1]; + Size szLastLayer = img.size(); + nLayers_ = 1; - cudev::pyramid::downsampleX2(prevLayer, pyramid_[i], img.depth(), img.channels(), StreamAccessor::getStream(stream)); + if (numLayers <= 0) + numLayers = 255; // it will cut-off when any of the dimensions goes 1 - szLastLayer = szCurLayer; - } -#endif -} + pyramid_.resize(numLayers); -void cv::gpu::ImagePyramid::getLayer(GpuMat& outImg, Size outRoi, Stream& stream) const -{ -#ifndef HAVE_OPENCV_GPULEGACY - (void) outImg; - (void) outRoi; - (void) stream; - throw_no_cuda(); -#else - CV_Assert(outRoi.width <= layer0_.cols && outRoi.height <= layer0_.rows && outRoi.width > 0 && outRoi.height > 0); + for (int i = 0; i < numLayers - 1; ++i) + { + Size szCurLayer(szLastLayer.width / 2, szLastLayer.height / 2); - ensureSizeIsEnough(outRoi, layer0_.type(), outImg); + if (szCurLayer.width == 0 || szCurLayer.height == 0) + break; - if (outRoi.width == layer0_.cols && outRoi.height == layer0_.rows) - { - layer0_.copyTo(outImg, stream); - } + ensureSizeIsEnough(szCurLayer, img.type(), pyramid_[i]); + nLayers_++; - float lastScale = 1.0f; - float curScale; - GpuMat lastLayer = layer0_; - GpuMat curLayer; + const GpuMat& prevLayer = i == 0 ? layer0_ : pyramid_[i - 1]; - for (int i = 0; i < nLayers_ - 1; ++i) + cudev::pyramid::downsampleX2(prevLayer, pyramid_[i], img.depth(), img.channels(), StreamAccessor::getStream(stream)); + + szLastLayer = szCurLayer; + } + } + + void ImagePyramidImpl::getLayer(OutputArray _outImg, Size outRoi, Stream& stream) const { - curScale = lastScale * 0.5f; - curLayer = pyramid_[i]; + CV_Assert( outRoi.width <= layer0_.cols && outRoi.height <= layer0_.rows && outRoi.width > 0 && outRoi.height > 0 ); + + ensureSizeIsEnough(outRoi, layer0_.type(), _outImg); + GpuMat outImg = _outImg.getGpuMat(); - if (outRoi.width == curLayer.cols && outRoi.height == curLayer.rows) + if (outRoi.width == layer0_.cols && outRoi.height == layer0_.rows) { - curLayer.copyTo(outImg, stream); + layer0_.copyTo(outImg, stream); + return; } - if (outRoi.width >= curLayer.cols && outRoi.height >= curLayer.rows) - break; + float lastScale = 1.0f; + float curScale; + GpuMat lastLayer = layer0_; + GpuMat curLayer; + + for (int i = 0; i < nLayers_ - 1; ++i) + { + curScale = lastScale * 0.5f; + curLayer = pyramid_[i]; + + if (outRoi.width == curLayer.cols && outRoi.height == curLayer.rows) + { + curLayer.copyTo(outImg, stream); + } + + if (outRoi.width >= curLayer.cols && outRoi.height >= curLayer.rows) + break; + + lastScale = curScale; + lastLayer = curLayer; + } - lastScale = curScale; - lastLayer = curLayer; + cudev::pyramid::interpolateFrom1(lastLayer, outImg, outImg.depth(), outImg.channels(), StreamAccessor::getStream(stream)); } +} + +#endif - cudev::pyramid::interpolateFrom1(lastLayer, outImg, outImg.depth(), outImg.channels(), StreamAccessor::getStream(stream)); +Ptr cv::gpu::createImagePyramid(InputArray img, int nLayers, Stream& stream) +{ +#ifndef HAVE_OPENCV_GPULEGACY + (void) img; + (void) numLayers; + (void) stream; + throw_no_cuda(); + return Ptr(); +#else + return new ImagePyramidImpl(img, nLayers, stream); #endif }