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 | 172 ++++++++++-------- 3 files changed, 105 insertions(+), 136 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) +#ifdef HAVE_OPENCV_GPULEGACY + +namespace +{ + class ImagePyramidImpl : public ImagePyramid + { + public: + ImagePyramidImpl(InputArray img, int nLayers, Stream& stream); + + void getLayer(OutputArray outImg, Size outRoi, Stream& stream = Stream::Null()) const; + + private: + GpuMat layer0_; + std::vector pyramid_; + int nLayers_; + }; + + ImagePyramidImpl::ImagePyramidImpl(InputArray _img, int numLayers, Stream& stream) + { + GpuMat img = _img.getGpuMat(); + + CV_Assert( img.depth() <= CV_32F && img.channels() <= 4 ); + + img.copyTo(layer0_, stream); + + Size szLastLayer = img.size(); + nLayers_ = 1; + + if (numLayers <= 0) + numLayers = 255; // it will cut-off when any of the dimensions goes 1 + + pyramid_.resize(numLayers); + + for (int i = 0; i < numLayers - 1; ++i) + { + Size szCurLayer(szLastLayer.width / 2, szLastLayer.height / 2); + + if (szCurLayer.width == 0 || szCurLayer.height == 0) + break; + + ensureSizeIsEnough(szCurLayer, img.type(), pyramid_[i]); + nLayers_++; + + const GpuMat& prevLayer = i == 0 ? layer0_ : pyramid_[i - 1]; + + 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 + { + 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 == layer0_.cols && outRoi.height == layer0_.rows) + { + layer0_.copyTo(outImg, stream); + return; + } + + 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; + } + + cudev::pyramid::interpolateFrom1(lastLayer, outImg, outImg.depth(), outImg.channels(), StreamAccessor::getStream(stream)); + } +} + +#endif + +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 - CV_Assert(img.depth() <= CV_32F && img.channels() <= 4); - - layer0_ = img; - Size szLastLayer = img.size(); - nLayers_ = 1; - - if (numLayers <= 0) - numLayers = 255; //it will cut-off when any of the dimensions goes 1 - - pyramid_.resize(numLayers); - - for (int i = 0; i < numLayers - 1; ++i) - { - Size szCurLayer(szLastLayer.width / 2, szLastLayer.height / 2); - - if (szCurLayer.width == 0 || szCurLayer.height == 0) - break; - - ensureSizeIsEnough(szCurLayer, img.type(), pyramid_[i]); - nLayers_++; - - const GpuMat& prevLayer = i == 0 ? layer0_ : pyramid_[i - 1]; - - cudev::pyramid::downsampleX2(prevLayer, pyramid_[i], img.depth(), img.channels(), StreamAccessor::getStream(stream)); - - szLastLayer = szCurLayer; - } -#endif -} - -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); - - ensureSizeIsEnough(outRoi, layer0_.type(), outImg); - - if (outRoi.width == layer0_.cols && outRoi.height == layer0_.rows) - { - layer0_.copyTo(outImg, stream); - } - - 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; - } - - cudev::pyramid::interpolateFrom1(lastLayer, outImg, outImg.depth(), outImg.channels(), StreamAccessor::getStream(stream)); + return new ImagePyramidImpl(img, nLayers, stream); #endif }