refactored GoodFeaturesToTrackDetector
authorVladislav Vinogradov <vlad.vinogradov@itseez.com>
Tue, 30 Apr 2013 12:07:56 +0000 (16:07 +0400)
committerVladislav Vinogradov <vlad.vinogradov@itseez.com>
Wed, 17 Jul 2013 07:39:56 +0000 (11:39 +0400)
modules/gpu/perf4au/main.cpp
modules/gpuimgproc/include/opencv2/gpuimgproc.hpp
modules/gpuimgproc/perf/perf_gftt.cpp
modules/gpuimgproc/src/gftt.cpp
modules/gpuimgproc/test/test_gftt.cpp
modules/videostab/include/opencv2/videostab/global_motion.hpp
modules/videostab/src/global_motion.cpp
samples/gpu/performance/tests.cpp
samples/gpu/pyrlk_optical_flow.cpp

index df8a793..5e39c3d 100644 (file)
@@ -148,17 +148,17 @@ PERF_TEST_P(Image_Depth, GoodFeaturesToTrack,
 
     if (PERF_RUN_GPU())
     {
-        cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k);
+        cv::Ptr<cv::gpu::CornersDetector> detector = cv::gpu::createGoodFeaturesToTrackDetector(src.type(), maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k);
 
         cv::gpu::GpuMat d_src(src);
         cv::gpu::GpuMat d_mask(mask);
         cv::gpu::GpuMat d_pts;
 
-        d_detector(d_src, d_pts, d_mask);
+        detector->detect(d_src, d_pts, d_mask);
 
         TEST_CYCLE()
         {
-            d_detector(d_src, d_pts, d_mask);
+            detector->detect(d_src, d_pts, d_mask);
         }
     }
     else
index adb9a8e..2fd17d9 100644 (file)
@@ -394,54 +394,17 @@ inline void cornerMinEigenVal(InputArray src, OutputArray dst, int blockSize, in
     gpu::createMinEigenValCorner(src.type(), blockSize, ksize, borderType)->compute(src, dst, stream);
 }
 
-////////////////////////// Feature Detection ///////////////////////////
+////////////////////////// Corners Detection ///////////////////////////
 
-class CV_EXPORTS GoodFeaturesToTrackDetector_GPU
+class CV_EXPORTS CornersDetector : public Algorithm
 {
 public:
-    explicit GoodFeaturesToTrackDetector_GPU(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0,
-        int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04);
-
     //! return 1 rows matrix with CV_32FC2 type
-    void operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask = GpuMat());
-
-    int maxCorners;
-    double qualityLevel;
-    double minDistance;
-
-    int blockSize;
-    bool useHarrisDetector;
-    double harrisK;
-
-    void releaseMemory()
-    {
-        Dx_.release();
-        Dy_.release();
-        buf_.release();
-        eig_.release();
-        minMaxbuf_.release();
-        tmpCorners_.release();
-    }
-
-private:
-    GpuMat Dx_;
-    GpuMat Dy_;
-    GpuMat buf_;
-    GpuMat eig_;
-    GpuMat minMaxbuf_;
-    GpuMat tmpCorners_;
+    virtual void detect(InputArray image, OutputArray corners, InputArray mask = noArray()) = 0;
 };
 
-inline GoodFeaturesToTrackDetector_GPU::GoodFeaturesToTrackDetector_GPU(int maxCorners_, double qualityLevel_, double minDistance_,
-        int blockSize_, bool useHarrisDetector_, double harrisK_)
-{
-    maxCorners = maxCorners_;
-    qualityLevel = qualityLevel_;
-    minDistance = minDistance_;
-    blockSize = blockSize_;
-    useHarrisDetector = useHarrisDetector_;
-    harrisK = harrisK_;
-}
+CV_EXPORTS Ptr<CornersDetector> createGoodFeaturesToTrackDetector(int srcType, int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0,
+                                                                  int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04);
 
 ///////////////////////////// Mean Shift //////////////////////////////
 
index 982182d..ed8d6ac 100644 (file)
@@ -66,12 +66,12 @@ PERF_TEST_P(Image_MinDistance, GoodFeaturesToTrack,
 
     if (PERF_RUN_GPU())
     {
-        cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance);
+        cv::Ptr<cv::gpu::CornersDetector> d_detector = cv::gpu::createGoodFeaturesToTrackDetector(image.type(), maxCorners, qualityLevel, minDistance);
 
         const cv::gpu::GpuMat d_image(image);
         cv::gpu::GpuMat pts;
 
-        TEST_CYCLE() d_detector(d_image, pts);
+        TEST_CYCLE() d_detector->detect(d_image, pts);
 
         GPU_SANITY_CHECK(pts);
     }
index c441069..ff197d8 100644 (file)
@@ -45,9 +45,9 @@
 using namespace cv;
 using namespace cv::gpu;
 
-#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
+#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) || !defined(HAVE_OPENCV_GPUARITHM)
 
-void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat&, GpuMat&, const GpuMat&) { throw_no_cuda(); }
+Ptr<gpu::CornersDetector> cv::gpu::createGoodFeaturesToTrackDetector(int, int, double, double, int, bool, double) { throw_no_cuda(); return Ptr<gpu::CornersDetector>(); }
 
 #else /* !defined (HAVE_CUDA) */
 
@@ -60,119 +60,156 @@ namespace cv { namespace gpu { namespace cudev
     }
 }}}
 
-void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask)
+namespace
 {
-#ifndef HAVE_OPENCV_GPUARITHM
-    (void) image;
-    (void) corners;
-    (void) mask;
-    throw_no_cuda();
-#else
-    using namespace cv::gpu::cudev::gfft;
+    class GoodFeaturesToTrackDetector : public CornersDetector
+    {
+    public:
+        GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
+                                    int blockSize, bool useHarrisDetector, double harrisK);
+
+        void detect(InputArray image, OutputArray corners, InputArray mask = noArray());
+
+    private:
+        int maxCorners_;
+        double qualityLevel_;
+        double minDistance_;
+
+        Ptr<gpu::CornernessCriteria> cornerCriteria_;
+
+        GpuMat Dx_;
+        GpuMat Dy_;
+        GpuMat buf_;
+        GpuMat eig_;
+        GpuMat minMaxbuf_;
+        GpuMat tmpCorners_;
+    };
+
+    GoodFeaturesToTrackDetector::GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
+                                                             int blockSize, bool useHarrisDetector, double harrisK) :
+        maxCorners_(maxCorners), qualityLevel_(qualityLevel), minDistance_(minDistance)
+    {
+        CV_Assert( qualityLevel_ > 0 && minDistance_ >= 0 && maxCorners_ >= 0 );
 
-    CV_Assert(qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0);
-    CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()));
+        cornerCriteria_ = useHarrisDetector ?
+                    gpu::createHarrisCorner(srcType, blockSize, 3, harrisK) :
+                    gpu::createMinEigenValCorner(srcType, blockSize, 3);
+    }
 
-    ensureSizeIsEnough(image.size(), CV_32F, eig_);
+    void GoodFeaturesToTrackDetector::detect(InputArray _image, OutputArray _corners, InputArray _mask)
+    {
+        using namespace cv::gpu::cudev::gfft;
 
-    Ptr<gpu::CornernessCriteria> cornerCriteria =
-            useHarrisDetector ?
-                gpu::createHarrisCorner(image.type(), blockSize, 3, harrisK) :
-                gpu::createMinEigenValCorner(image.type(), blockSize, 3);
+        GpuMat image = _image.getGpuMat();
+        GpuMat mask = _mask.getGpuMat();
 
-    cornerCriteria->compute(image, eig_);
+        CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );
 
-    double maxVal = 0;
-    gpu::minMax(eig_, 0, &maxVal, GpuMat(), minMaxbuf_);
+        ensureSizeIsEnough(image.size(), CV_32FC1, eig_);
+        cornerCriteria_->compute(image, eig_);
 
-    ensureSizeIsEnough(1, std::max(1000, static_cast<int>(image.size().area() * 0.05)), CV_32FC2, tmpCorners_);
+        double maxVal = 0;
+        gpu::minMax(eig_, 0, &maxVal, noArray(), minMaxbuf_);
 
-    int total = findCorners_gpu(eig_, static_cast<float>(maxVal * qualityLevel), mask, tmpCorners_.ptr<float2>(), tmpCorners_.cols);
+        ensureSizeIsEnough(1, std::max(1000, static_cast<int>(image.size().area() * 0.05)), CV_32FC2, tmpCorners_);
 
-    if (total == 0)
-    {
-        corners.release();
-        return;
-    }
+        int total = findCorners_gpu(eig_, static_cast<float>(maxVal * qualityLevel_), mask, tmpCorners_.ptr<float2>(), tmpCorners_.cols);
 
-    sortCorners_gpu(eig_, tmpCorners_.ptr<float2>(), total);
+        if (total == 0)
+        {
+            _corners.release();
+            return;
+        }
 
-    if (minDistance < 1)
-        tmpCorners_.colRange(0, maxCorners > 0 ? std::min(maxCorners, total) : total).copyTo(corners);
-    else
-    {
-        std::vector<Point2f> tmp(total);
-        Mat tmpMat(1, total, CV_32FC2, (void*)&tmp[0]);
-        tmpCorners_.colRange(0, total).download(tmpMat);
+        sortCorners_gpu(eig_, tmpCorners_.ptr<float2>(), total);
 
-        std::vector<Point2f> tmp2;
-        tmp2.reserve(total);
+        if (minDistance_ < 1)
+        {
+            tmpCorners_.colRange(0, maxCorners_ > 0 ? std::min(maxCorners_, total) : total).copyTo(_corners);
+        }
+        else
+        {
+            std::vector<Point2f> tmp(total);
+            Mat tmpMat(1, total, CV_32FC2, (void*)&tmp[0]);
+            tmpCorners_.colRange(0, total).download(tmpMat);
 
-        const int cell_size = cvRound(minDistance);
-        const int grid_width = (image.cols + cell_size - 1) / cell_size;
-        const int grid_height = (image.rows + cell_size - 1) / cell_size;
+            std::vector<Point2f> tmp2;
+            tmp2.reserve(total);
 
-        std::vector< std::vector<Point2f> > grid(grid_width * grid_height);
+            const int cell_size = cvRound(minDistance_);
+            const int grid_width = (image.cols + cell_size - 1) / cell_size;
+            const int grid_height = (image.rows + cell_size - 1) / cell_size;
 
-        for (int i = 0; i < total; ++i)
-        {
-            Point2f p = tmp[i];
+            std::vector< std::vector<Point2f> > grid(grid_width * grid_height);
 
-            bool good = true;
+            for (int i = 0; i < total; ++i)
+            {
+                Point2f p = tmp[i];
 
-            int x_cell = static_cast<int>(p.x / cell_size);
-            int y_cell = static_cast<int>(p.y / cell_size);
+                bool good = true;
 
-            int x1 = x_cell - 1;
-            int y1 = y_cell - 1;
-            int x2 = x_cell + 1;
-            int y2 = y_cell + 1;
+                int x_cell = static_cast<int>(p.x / cell_size);
+                int y_cell = static_cast<int>(p.y / cell_size);
 
-            // boundary check
-            x1 = std::max(0, x1);
-            y1 = std::max(0, y1);
-            x2 = std::min(grid_width - 1, x2);
-            y2 = std::min(grid_height - 1, y2);
+                int x1 = x_cell - 1;
+                int y1 = y_cell - 1;
+                int x2 = x_cell + 1;
+                int y2 = y_cell + 1;
 
-            for (int yy = y1; yy <= y2; yy++)
-            {
-                for (int xx = x1; xx <= x2; xx++)
-                {
-                    std::vector<Point2f>& m = grid[yy * grid_width + xx];
+                // boundary check
+                x1 = std::max(0, x1);
+                y1 = std::max(0, y1);
+                x2 = std::min(grid_width - 1, x2);
+                y2 = std::min(grid_height - 1, y2);
 
-                    if (!m.empty())
+                for (int yy = y1; yy <= y2; yy++)
+                {
+                    for (int xx = x1; xx <= x2; xx++)
                     {
-                        for(size_t j = 0; j < m.size(); j++)
-                        {
-                            float dx = p.x - m[j].x;
-                            float dy = p.y - m[j].y;
+                        std::vector<Point2f>& m = grid[yy * grid_width + xx];
 
-                            if (dx * dx + dy * dy < minDistance * minDistance)
+                        if (!m.empty())
+                        {
+                            for(size_t j = 0; j < m.size(); j++)
                             {
-                                good = false;
-                                goto break_out;
+                                float dx = p.x - m[j].x;
+                                float dy = p.y - m[j].y;
+
+                                if (dx * dx + dy * dy < minDistance_ * minDistance_)
+                                {
+                                    good = false;
+                                    goto break_out;
+                                }
                             }
                         }
                     }
                 }
-            }
 
-            break_out:
+                break_out:
 
-            if(good)
-            {
-                grid[y_cell * grid_width + x_cell].push_back(p);
+                if(good)
+                {
+                    grid[y_cell * grid_width + x_cell].push_back(p);
 
-                tmp2.push_back(p);
+                    tmp2.push_back(p);
 
-                if (maxCorners > 0 && tmp2.size() == static_cast<size_t>(maxCorners))
-                    break;
+                    if (maxCorners_ > 0 && tmp2.size() == static_cast<size_t>(maxCorners_))
+                        break;
+                }
             }
-        }
 
-        corners.upload(Mat(1, static_cast<int>(tmp2.size()), CV_32FC2, &tmp2[0]));
+            _corners.create(1, static_cast<int>(tmp2.size()), CV_32FC2);
+            GpuMat corners = _corners.getGpuMat();
+
+            corners.upload(Mat(1, static_cast<int>(tmp2.size()), CV_32FC2, &tmp2[0]));
+        }
     }
-#endif
+}
+
+Ptr<gpu::CornersDetector> cv::gpu::createGoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
+                                                                     int blockSize, bool useHarrisDetector, double harrisK)
+{
+    return new GoodFeaturesToTrackDetector(srcType, maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, harrisK);
 }
 
 #endif /* !defined (HAVE_CUDA) */
index b20df33..6ba6e0c 100644 (file)
@@ -76,10 +76,10 @@ GPU_TEST_P(GoodFeaturesToTrack, Accuracy)
     int maxCorners = 1000;
     double qualityLevel = 0.01;
 
-    cv::gpu::GoodFeaturesToTrackDetector_GPU detector(maxCorners, qualityLevel, minDistance);
+    cv::Ptr<cv::gpu::CornersDetector> detector = cv::gpu::createGoodFeaturesToTrackDetector(image.type(), maxCorners, qualityLevel, minDistance);
 
     cv::gpu::GpuMat d_pts;
-    detector(loadMat(image), d_pts);
+    detector->detect(loadMat(image), d_pts);
 
     ASSERT_FALSE(d_pts.empty());
 
@@ -114,12 +114,12 @@ GPU_TEST_P(GoodFeaturesToTrack, EmptyCorners)
     int maxCorners = 1000;
     double qualityLevel = 0.01;
 
-    cv::gpu::GoodFeaturesToTrackDetector_GPU detector(maxCorners, qualityLevel, minDistance);
-
     cv::gpu::GpuMat src(100, 100, CV_8UC1, cv::Scalar::all(0));
     cv::gpu::GpuMat corners(1, maxCorners, CV_32FC2);
 
-    detector(src, corners);
+    cv::Ptr<cv::gpu::CornersDetector> detector = cv::gpu::createGoodFeaturesToTrackDetector(src.type(), maxCorners, qualityLevel, minDistance);
+
+    detector->detect(src, corners);
 
     ASSERT_TRUE(corners.empty());
 }
index 58b831b..8ccc067 100644 (file)
@@ -217,7 +217,7 @@ public:
 
 private:
     Ptr<MotionEstimatorBase> motionEstimator_;
-    gpu::GoodFeaturesToTrackDetector_GPU detector_;
+    Ptr<gpu::CornersDetector> detector_;
     SparsePyrLkOptFlowEstimatorGpu optFlowEstimator_;
     Ptr<IOutlierRejector> outlierRejector_;
 
index d6c291c..9a54b5a 100644 (file)
@@ -742,6 +742,8 @@ Mat KeypointBasedMotionEstimator::estimate(const Mat &frame0, const Mat &frame1,
 KeypointBasedMotionEstimatorGpu::KeypointBasedMotionEstimatorGpu(Ptr<MotionEstimatorBase> estimator)
     : ImageMotionEstimatorBase(estimator->motionModel()), motionEstimator_(estimator)
 {
+    detector_ = gpu::createGoodFeaturesToTrackDetector(CV_8UC1);
+
     CV_Assert(gpu::getCudaEnabledDeviceCount() > 0);
     setOutlierRejector(new NullOutlierRejector());
 }
@@ -769,7 +771,7 @@ Mat KeypointBasedMotionEstimatorGpu::estimate(const gpu::GpuMat &frame0, const g
     }
 
     // find keypoints
-    detector_(grayFrame0, pointsPrev_);
+    detector_->detect(grayFrame0, pointsPrev_);
 
     // find correspondences
     optFlowEstimator_.run(frame0, frame1, pointsPrev_, points_, status_);
index f95730e..da2d4e2 100644 (file)
@@ -1174,15 +1174,15 @@ TEST(GoodFeaturesToTrack)
     goodFeaturesToTrack(src, pts, 8000, 0.01, 0.0);
     CPU_OFF;
 
-    gpu::GoodFeaturesToTrackDetector_GPU detector(8000, 0.01, 0.0);
+    Ptr<gpu::CornersDetector> detector = gpu::createGoodFeaturesToTrackDetector(src.type(), 8000, 0.01, 0.0);
 
     gpu::GpuMat d_src(src);
     gpu::GpuMat d_pts;
 
-    detector(d_src, d_pts);
+    detector->detect(d_src, d_pts);
 
     GPU_ON;
-    detector(d_src, d_pts);
+    detector->detect(d_src, d_pts);
     GPU_OFF;
 }
 
index 2edb974..0871729 100644 (file)
@@ -176,12 +176,12 @@ int main(int argc, const char* argv[])
 
     // goodFeaturesToTrack
 
-    GoodFeaturesToTrackDetector_GPU detector(points, 0.01, minDist);
-
     GpuMat d_frame0Gray(frame0Gray);
     GpuMat d_prevPts;
 
-    detector(d_frame0Gray, d_prevPts);
+    Ptr<gpu::CornersDetector> detector = gpu::createGoodFeaturesToTrackDetector(d_frame0Gray.type(), points, 0.01, minDist);
+
+    detector->detect(d_frame0Gray, d_prevPts);
 
     // Sparse