refactored gpu::GeneralizedHough
authorVladislav Vinogradov <vlad.vinogradov@itseez.com>
Tue, 30 Apr 2013 09:59:10 +0000 (13:59 +0400)
committerVladislav Vinogradov <vlad.vinogradov@itseez.com>
Wed, 17 Jul 2013 07:39:55 +0000 (11:39 +0400)
modules/gpuimgproc/include/opencv2/gpuimgproc.hpp
modules/gpuimgproc/perf/perf_hough.cpp
modules/gpuimgproc/src/hough.cpp
modules/gpuimgproc/test/test_hough.cpp
samples/gpu/generalized_hough.cpp

index a4ed11e..d368ae0 100644 (file)
@@ -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<GeneralizedHough_GPU> create(int method);
-
-    GeneralizedHough_GPU();
-    virtual ~GeneralizedHough_GPU();
+    static Ptr<GeneralizedHough> 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<CannyEdgeDetector> canny_;
+    virtual void downloadResults(InputArray d_positions, OutputArray h_positions, OutputArray h_votes = noArray()) = 0;
 };
 
 ////////////////////////// Corners Detection ///////////////////////////
index b0f41e5..f72a820 100644 (file)
@@ -286,7 +286,7 @@ PERF_TEST_P(Method_Sz, GeneralizedHough,
         const cv::gpu::GpuMat d_dy(dy);
         cv::gpu::GpuMat posAndVotes;
 
-        cv::Ptr<cv::gpu::GeneralizedHough_GPU> d_hough = cv::gpu::GeneralizedHough_GPU::create(method);
+        cv::Ptr<cv::gpu::GeneralizedHough> d_hough = cv::gpu::GeneralizedHough::create(method);
         if (method & GHT_ROTATION)
         {
             d_hough->set("maxAngle", 90.0);
index 67d6e38..90b0261 100644 (file)
@@ -51,16 +51,9 @@ Ptr<gpu::HoughLinesDetector> cv::gpu::createHoughLinesDetector(float, float, int
 
 Ptr<gpu::HoughSegmentDetector> cv::gpu::createHoughSegmentDetector(float, float, int, int, int) { throw_no_cuda(); return Ptr<HoughSegmentDetector>(); }
 
-Ptr<HoughCirclesDetector> cv::gpu::createHoughCirclesDetector(float, float, int, int, int, int, int) { throw_no_cuda(); return Ptr<HoughCirclesDetector>(); }
+Ptr<gpu::HoughCirclesDetector> cv::gpu::createHoughCirclesDetector(float, float, int, int, int, int, int) { throw_no_cuda(); return Ptr<HoughCirclesDetector>(); }
 
-Ptr<GeneralizedHough_GPU> cv::gpu::GeneralizedHough_GPU::create(int) { throw_no_cuda(); return Ptr<GeneralizedHough_GPU>(); }
-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<gpu::GeneralizedHough> cv::gpu::GeneralizedHough::create(int) { throw_no_cuda(); return Ptr<GeneralizedHough>(); }
 
 #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<gpu::CannyEdgeDetector> canny_;
+        Ptr<gpu::Filter> filterDx_;
+        Ptr<gpu::Filter> 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<int3>(1));
+            d_votes.download(h_votes);
+        }
+    }
+
+    /////////////////////////////////////
+    // GHT_Pos
 
     template <typename T, class A> void releaseVector(std::vector<T, A>& 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<GeneralizedHough_GPU> cv::gpu::GeneralizedHough_GPU::create(int method)
+Ptr<gpu::GeneralizedHough> cv::gpu::GeneralizedHough::create(int method)
 {
     switch (method)
     {
@@ -1562,104 +1681,8 @@ Ptr<GeneralizedHough_GPU> cv::gpu::GeneralizedHough_GPU::create(int method)
         return new GHT_Guil_Full();
     }
 
-    CV_Error(cv::Error::StsBadArg, "Unsupported method");
-    return Ptr<GeneralizedHough_GPU>();
-}
-
-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<gpu::Filter> filterDX = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0);
-    Ptr<gpu::Filter> 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<gpu::Filter> filterDX = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0);
-    Ptr<gpu::Filter> 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<int3*>(d_positions.ptr<int3>(1)));
-        d_votes.download(h_votes);
-    }
-}
-
-void cv::gpu::GeneralizedHough_GPU::release()
-{
-    edges_.release();
-    releaseImpl();
+    CV_Error(Error::StsBadArg, "Unsupported method");
+    return Ptr<GeneralizedHough>();
 }
 
 #endif /* !defined (HAVE_CUDA) */
index d0482dc..e4319bd 100644 (file)
@@ -218,7 +218,7 @@ GPU_TEST_P(GeneralizedHough, POSITION)
         templ.copyTo(imageROI);
     }
 
-    cv::Ptr<cv::gpu::GeneralizedHough_GPU> hough = cv::gpu::GeneralizedHough_GPU::create(cv::GeneralizedHough::GHT_POSITION);
+    cv::Ptr<cv::gpu::GeneralizedHough> 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<cv::Vec4f> pos;
-    hough->download(d_pos, pos);
+    hough->downloadResults(d_pos, pos);
 
     ASSERT_EQ(gold_count, pos.size());
 
index a8f7cc6..dbd924f 100644 (file)
@@ -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<GeneralizedHough_GPU> d_hough = GeneralizedHough_GPU::create(method);
+        Ptr<gpu::GeneralizedHough> 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();
     }