From ad4d6bed9dccdb6fecc5daff0463efe26343c5e9 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 30 Apr 2013 13:59:10 +0400 Subject: [PATCH] refactored gpu::GeneralizedHough --- modules/gpuimgproc/include/opencv2/gpuimgproc.hpp | 28 +-- modules/gpuimgproc/perf/perf_hough.cpp | 2 +- modules/gpuimgproc/src/hough.cpp | 251 ++++++++++++---------- modules/gpuimgproc/test/test_hough.cpp | 4 +- samples/gpu/generalized_hough.cpp | 6 +- 5 files changed, 150 insertions(+), 141 deletions(-) diff --git a/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp b/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp index a4ed11e..d368ae0 100644 --- a/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp +++ b/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp @@ -344,34 +344,20 @@ inline void HoughCircles(InputArray src, OutputArray circles, int /*method*/, fl //! finds arbitrary template in the grayscale image using Generalized Hough Transform //! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122. //! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038. -class CV_EXPORTS GeneralizedHough_GPU : public cv::Algorithm +class CV_EXPORTS GeneralizedHough : public Algorithm { public: - static Ptr create(int method); - - GeneralizedHough_GPU(); - virtual ~GeneralizedHough_GPU(); + static Ptr create(int method); //! set template to search - void setTemplate(const GpuMat& templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1)); - void setTemplate(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter = Point(-1, -1)); + virtual void setTemplate(InputArray templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1)) = 0; + virtual void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1)) = 0; //! find template on image - void detect(const GpuMat& image, GpuMat& positions, int cannyThreshold = 100); - void detect(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions); - - void download(const GpuMat& d_positions, OutputArray h_positions, OutputArray h_votes = noArray()); - - void release(); + virtual void detect(InputArray image, OutputArray positions, int cannyThreshold = 100) = 0; + virtual void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions) = 0; -protected: - virtual void setTemplateImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter) = 0; - virtual void detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions) = 0; - virtual void releaseImpl() = 0; - -private: - GpuMat edges_; - Ptr canny_; + virtual void downloadResults(InputArray d_positions, OutputArray h_positions, OutputArray h_votes = noArray()) = 0; }; ////////////////////////// Corners Detection /////////////////////////// diff --git a/modules/gpuimgproc/perf/perf_hough.cpp b/modules/gpuimgproc/perf/perf_hough.cpp index b0f41e5..f72a820 100644 --- a/modules/gpuimgproc/perf/perf_hough.cpp +++ b/modules/gpuimgproc/perf/perf_hough.cpp @@ -286,7 +286,7 @@ PERF_TEST_P(Method_Sz, GeneralizedHough, const cv::gpu::GpuMat d_dy(dy); cv::gpu::GpuMat posAndVotes; - cv::Ptr d_hough = cv::gpu::GeneralizedHough_GPU::create(method); + cv::Ptr d_hough = cv::gpu::GeneralizedHough::create(method); if (method & GHT_ROTATION) { d_hough->set("maxAngle", 90.0); diff --git a/modules/gpuimgproc/src/hough.cpp b/modules/gpuimgproc/src/hough.cpp index 67d6e38..90b0261 100644 --- a/modules/gpuimgproc/src/hough.cpp +++ b/modules/gpuimgproc/src/hough.cpp @@ -51,16 +51,9 @@ Ptr cv::gpu::createHoughLinesDetector(float, float, int Ptr cv::gpu::createHoughSegmentDetector(float, float, int, int, int) { throw_no_cuda(); return Ptr(); } -Ptr cv::gpu::createHoughCirclesDetector(float, float, int, int, int, int, int) { throw_no_cuda(); return Ptr(); } +Ptr cv::gpu::createHoughCirclesDetector(float, float, int, int, int, int, int) { throw_no_cuda(); return Ptr(); } -Ptr cv::gpu::GeneralizedHough_GPU::create(int) { throw_no_cuda(); return Ptr(); } -cv::gpu::GeneralizedHough_GPU::~GeneralizedHough_GPU() {} -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat&, int, Point) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat&, const GpuMat&, const GpuMat&, Point) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat&, GpuMat&, int) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat&, const GpuMat&, const GpuMat&, GpuMat&) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::download(const GpuMat&, OutputArray, OutputArray) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::release() {} +Ptr cv::gpu::GeneralizedHough::create(int) { throw_no_cuda(); return Ptr(); } #else /* !defined (HAVE_CUDA) */ @@ -644,7 +637,133 @@ namespace cv { namespace gpu { namespace cudev namespace { ///////////////////////////////////// - // Common + // GeneralizedHoughBase + + class GeneralizedHoughBase : public gpu::GeneralizedHough + { + public: + GeneralizedHoughBase(); + + void setTemplate(InputArray templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1)); + void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1)); + + void detect(InputArray image, OutputArray positions, int cannyThreshold = 100); + void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions); + + void downloadResults(InputArray d_positions, OutputArray h_positions, OutputArray h_votes = noArray()); + + protected: + virtual void setTemplateImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter) = 0; + virtual void detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, OutputArray positions) = 0; + + private: + GpuMat dx_, dy_; + GpuMat edges_; + Ptr canny_; + Ptr filterDx_; + Ptr filterDy_; + }; + + GeneralizedHoughBase::GeneralizedHoughBase() + { + canny_ = gpu::createCannyEdgeDetector(50, 100); + filterDx_ = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0); + filterDy_ = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1); + } + + void GeneralizedHoughBase::setTemplate(InputArray _templ, int cannyThreshold, Point templCenter) + { + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( templ.type() == CV_8UC1 ); + CV_Assert( cannyThreshold > 0 ); + + ensureSizeIsEnough(templ.size(), CV_32SC1, dx_); + ensureSizeIsEnough(templ.size(), CV_32SC1, dy_); + + filterDx_->apply(templ, dx_); + filterDy_->apply(templ, dy_); + + ensureSizeIsEnough(templ.size(), CV_8UC1, edges_); + + canny_->setLowThreshold(cannyThreshold / 2); + canny_->setHighThreshold(cannyThreshold); + canny_->detect(dx_, dy_, edges_); + + if (templCenter == Point(-1, -1)) + templCenter = Point(templ.cols / 2, templ.rows / 2); + + setTemplateImpl(edges_, dx_, dy_, templCenter); + } + + void GeneralizedHoughBase::setTemplate(InputArray _edges, InputArray _dx, InputArray _dy, Point templCenter) + { + GpuMat edges = _edges.getGpuMat(); + GpuMat dx = _dx.getGpuMat(); + GpuMat dy = _dy.getGpuMat(); + + if (templCenter == Point(-1, -1)) + templCenter = Point(edges.cols / 2, edges.rows / 2); + + setTemplateImpl(edges, dx, dy, templCenter); + } + + void GeneralizedHoughBase::detect(InputArray _image, OutputArray positions, int cannyThreshold) + { + GpuMat image = _image.getGpuMat(); + + CV_Assert( image.type() == CV_8UC1 ); + CV_Assert( cannyThreshold > 0 ); + + ensureSizeIsEnough(image.size(), CV_32SC1, dx_); + ensureSizeIsEnough(image.size(), CV_32SC1, dy_); + + filterDx_->apply(image, dx_); + filterDy_->apply(image, dy_); + + ensureSizeIsEnough(image.size(), CV_8UC1, edges_); + + canny_->setLowThreshold(cannyThreshold / 2); + canny_->setHighThreshold(cannyThreshold); + canny_->detect(dx_, dy_, edges_); + + detectImpl(edges_, dx_, dy_, positions); + } + + void GeneralizedHoughBase::detect(InputArray _edges, InputArray _dx, InputArray _dy, OutputArray positions) + { + GpuMat edges = _edges.getGpuMat(); + GpuMat dx = _dx.getGpuMat(); + GpuMat dy = _dy.getGpuMat(); + + detectImpl(edges, dx, dy, positions); + } + + void GeneralizedHoughBase::downloadResults(InputArray _d_positions, OutputArray h_positions, OutputArray h_votes) + { + GpuMat d_positions = _d_positions.getGpuMat(); + + if (d_positions.empty()) + { + h_positions.release(); + if (h_votes.needed()) + h_votes.release(); + return; + } + + CV_Assert( d_positions.rows == 2 && d_positions.type() == CV_32FC4 ); + + d_positions.row(0).download(h_positions); + + if (h_votes.needed()) + { + GpuMat d_votes(1, d_positions.cols, CV_32SC3, d_positions.ptr(1)); + d_votes.download(h_votes); + } + } + + ///////////////////////////////////// + // GHT_Pos template void releaseVector(std::vector& v) { @@ -652,14 +771,14 @@ namespace empty.swap(v); } - class GHT_Pos : public GeneralizedHough_GPU + class GHT_Pos : public GeneralizedHoughBase { public: GHT_Pos(); protected: void setTemplateImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter); - void detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions); + void detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, OutputArray positions); void releaseImpl(); virtual void processTempl() = 0; @@ -667,7 +786,7 @@ namespace void buildEdgePointList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy); void filterMinDist(); - void convertTo(GpuMat& positions); + void convertTo(OutputArray positions); int maxSize; double minDist; @@ -717,7 +836,7 @@ namespace processTempl(); } - void GHT_Pos::detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions) + void GHT_Pos::detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, OutputArray positions) { imageSize = edges.size(); @@ -892,7 +1011,7 @@ namespace cudaSafeCall( cudaMemcpy(outBuf.ptr(1), &newVoteBuf[0], posCount * sizeof(int3), cudaMemcpyHostToDevice) ); } - void GHT_Pos::convertTo(GpuMat& positions) + void GHT_Pos::convertTo(OutputArray positions) { ensureSizeIsEnough(2, posCount, CV_32FC4, positions); GpuMat(2, posCount, CV_32FC4, outBuf.data, outBuf.step).copyTo(positions); @@ -1541,7 +1660,7 @@ namespace } } -Ptr cv::gpu::GeneralizedHough_GPU::create(int method) +Ptr cv::gpu::GeneralizedHough::create(int method) { switch (method) { @@ -1562,104 +1681,8 @@ Ptr cv::gpu::GeneralizedHough_GPU::create(int method) return new GHT_Guil_Full(); } - CV_Error(cv::Error::StsBadArg, "Unsupported method"); - return Ptr(); -} - -cv::gpu::GeneralizedHough_GPU::GeneralizedHough_GPU() -{ - canny_ = gpu::createCannyEdgeDetector(50, 100); -} - -cv::gpu::GeneralizedHough_GPU::~GeneralizedHough_GPU() -{ -} - -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat& templ, int cannyThreshold, Point templCenter) -{ - CV_Assert(templ.type() == CV_8UC1); - CV_Assert(cannyThreshold > 0); - - ensureSizeIsEnough(templ.size(), CV_8UC1, edges_); - - canny_->setLowThreshold(cannyThreshold / 2); - canny_->setHighThreshold(cannyThreshold); - canny_->detect(templ, edges_); - - if (templCenter == Point(-1, -1)) - templCenter = Point(templ.cols / 2, templ.rows / 2); - - Ptr filterDX = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0); - Ptr filterDY = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1); - GpuMat dx, dy; - filterDX->apply(templ, dx); - filterDY->apply(templ, dy); - - setTemplateImpl(edges_, dx, dy, templCenter); -} - -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter) -{ - if (templCenter == Point(-1, -1)) - templCenter = Point(edges.cols / 2, edges.rows / 2); - - setTemplateImpl(edges, dx, dy, templCenter); -} - -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat& image, GpuMat& positions, int cannyThreshold) -{ - CV_Assert(image.type() == CV_8UC1); - CV_Assert(cannyThreshold > 0); - - ensureSizeIsEnough(image.size(), CV_8UC1, edges_); - - canny_->setLowThreshold(cannyThreshold / 2); - canny_->setHighThreshold(cannyThreshold); - canny_->detect(image, edges_); - - Ptr filterDX = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0); - Ptr filterDY = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1); - GpuMat dx, dy; - filterDX->apply(image, dx); - filterDY->apply(image, dy); - - detectImpl(edges_, dx, dy, positions); -} - -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions) -{ - detectImpl(edges, dx, dy, positions); -} - -void cv::gpu::GeneralizedHough_GPU::download(const GpuMat& d_positions, OutputArray h_positions_, OutputArray h_votes_) -{ - if (d_positions.empty()) - { - h_positions_.release(); - if (h_votes_.needed()) - h_votes_.release(); - return; - } - - CV_Assert(d_positions.rows == 2 && d_positions.type() == CV_32FC4); - - h_positions_.create(1, d_positions.cols, CV_32FC4); - Mat h_positions = h_positions_.getMat(); - d_positions.row(0).download(h_positions); - - if (h_votes_.needed()) - { - h_votes_.create(1, d_positions.cols, CV_32SC3); - Mat h_votes = h_votes_.getMat(); - GpuMat d_votes(1, d_positions.cols, CV_32SC3, const_cast(d_positions.ptr(1))); - d_votes.download(h_votes); - } -} - -void cv::gpu::GeneralizedHough_GPU::release() -{ - edges_.release(); - releaseImpl(); + CV_Error(Error::StsBadArg, "Unsupported method"); + return Ptr(); } #endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/test/test_hough.cpp b/modules/gpuimgproc/test/test_hough.cpp index d0482dc..e4319bd 100644 --- a/modules/gpuimgproc/test/test_hough.cpp +++ b/modules/gpuimgproc/test/test_hough.cpp @@ -218,7 +218,7 @@ GPU_TEST_P(GeneralizedHough, POSITION) templ.copyTo(imageROI); } - cv::Ptr hough = cv::gpu::GeneralizedHough_GPU::create(cv::GeneralizedHough::GHT_POSITION); + cv::Ptr hough = cv::gpu::GeneralizedHough::create(cv::GeneralizedHough::GHT_POSITION); hough->set("votesThreshold", 200); hough->setTemplate(loadMat(templ, useRoi)); @@ -227,7 +227,7 @@ GPU_TEST_P(GeneralizedHough, POSITION) hough->detect(loadMat(image, useRoi), d_pos); std::vector pos; - hough->download(d_pos, pos); + hough->downloadResults(d_pos, pos); ASSERT_EQ(gold_count, pos.size()); diff --git a/samples/gpu/generalized_hough.cpp b/samples/gpu/generalized_hough.cpp index a8f7cc6..dbd924f 100644 --- a/samples/gpu/generalized_hough.cpp +++ b/samples/gpu/generalized_hough.cpp @@ -11,7 +11,7 @@ using namespace std; using namespace cv; -using namespace cv::gpu; +using cv::gpu::GpuMat; static Mat loadImage(const string& name) { @@ -101,7 +101,7 @@ int main(int argc, const char* argv[]) GpuMat d_image(image); GpuMat d_position; - Ptr d_hough = GeneralizedHough_GPU::create(method); + Ptr d_hough = gpu::GeneralizedHough::create(method); d_hough->set("minDist", minDist); d_hough->set("levels", levels); d_hough->set("dp", dp); @@ -134,7 +134,7 @@ int main(int argc, const char* argv[]) tm.start(); d_hough->detect(d_image, d_position); - d_hough->download(d_position, position); + d_hough->downloadResults(d_position, position); tm.stop(); } -- 2.7.4