Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #include "precomp.hpp"
     44 
     45 using namespace cv;
     46 using namespace cv::cuda;
     47 
     48 #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) || !defined(HAVE_OPENCV_CUDAARITHM)
     49 
     50 Ptr<cuda::CornersDetector> cv::cuda::createGoodFeaturesToTrackDetector(int, int, double, double, int, bool, double) { throw_no_cuda(); return Ptr<cuda::CornersDetector>(); }
     51 
     52 #else /* !defined (HAVE_CUDA) */
     53 
     54 namespace cv { namespace cuda { namespace device
     55 {
     56     namespace gfft
     57     {
     58         int findCorners_gpu(PtrStepSzf eig, float threshold, PtrStepSzb mask, float2* corners, int max_count);
     59         void sortCorners_gpu(PtrStepSzf eig, float2* corners, int count);
     60     }
     61 }}}
     62 
     63 namespace
     64 {
     65     class GoodFeaturesToTrackDetector : public CornersDetector
     66     {
     67     public:
     68         GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
     69                                     int blockSize, bool useHarrisDetector, double harrisK);
     70 
     71         void detect(InputArray image, OutputArray corners, InputArray mask, Stream& stream);
     72 
     73     private:
     74         int maxCorners_;
     75         double qualityLevel_;
     76         double minDistance_;
     77 
     78         Ptr<cuda::CornernessCriteria> cornerCriteria_;
     79 
     80         GpuMat Dx_;
     81         GpuMat Dy_;
     82         GpuMat buf_;
     83         GpuMat eig_;
     84         GpuMat tmpCorners_;
     85     };
     86 
     87     GoodFeaturesToTrackDetector::GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
     88                                                              int blockSize, bool useHarrisDetector, double harrisK) :
     89         maxCorners_(maxCorners), qualityLevel_(qualityLevel), minDistance_(minDistance)
     90     {
     91         CV_Assert( qualityLevel_ > 0 && minDistance_ >= 0 && maxCorners_ >= 0 );
     92 
     93         cornerCriteria_ = useHarrisDetector ?
     94                     cuda::createHarrisCorner(srcType, blockSize, 3, harrisK) :
     95                     cuda::createMinEigenValCorner(srcType, blockSize, 3);
     96     }
     97 
     98     void GoodFeaturesToTrackDetector::detect(InputArray _image, OutputArray _corners, InputArray _mask, Stream& stream)
     99     {
    100         // TODO : implement async version
    101         (void) stream;
    102 
    103         using namespace cv::cuda::device::gfft;
    104 
    105         GpuMat image = _image.getGpuMat();
    106         GpuMat mask = _mask.getGpuMat();
    107 
    108         CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );
    109 
    110         ensureSizeIsEnough(image.size(), CV_32FC1, eig_);
    111         cornerCriteria_->compute(image, eig_);
    112 
    113         double maxVal = 0;
    114         cuda::minMax(eig_, 0, &maxVal);
    115 
    116         ensureSizeIsEnough(1, std::max(1000, static_cast<int>(image.size().area() * 0.05)), CV_32FC2, tmpCorners_);
    117 
    118         int total = findCorners_gpu(eig_, static_cast<float>(maxVal * qualityLevel_), mask, tmpCorners_.ptr<float2>(), tmpCorners_.cols);
    119 
    120         if (total == 0)
    121         {
    122             _corners.release();
    123             return;
    124         }
    125 
    126         sortCorners_gpu(eig_, tmpCorners_.ptr<float2>(), total);
    127 
    128         if (minDistance_ < 1)
    129         {
    130             tmpCorners_.colRange(0, maxCorners_ > 0 ? std::min(maxCorners_, total) : total).copyTo(_corners);
    131         }
    132         else
    133         {
    134             std::vector<Point2f> tmp(total);
    135             Mat tmpMat(1, total, CV_32FC2, (void*)&tmp[0]);
    136             tmpCorners_.colRange(0, total).download(tmpMat);
    137 
    138             std::vector<Point2f> tmp2;
    139             tmp2.reserve(total);
    140 
    141             const int cell_size = cvRound(minDistance_);
    142             const int grid_width = (image.cols + cell_size - 1) / cell_size;
    143             const int grid_height = (image.rows + cell_size - 1) / cell_size;
    144 
    145             std::vector< std::vector<Point2f> > grid(grid_width * grid_height);
    146 
    147             for (int i = 0; i < total; ++i)
    148             {
    149                 Point2f p = tmp[i];
    150 
    151                 bool good = true;
    152 
    153                 int x_cell = static_cast<int>(p.x / cell_size);
    154                 int y_cell = static_cast<int>(p.y / cell_size);
    155 
    156                 int x1 = x_cell - 1;
    157                 int y1 = y_cell - 1;
    158                 int x2 = x_cell + 1;
    159                 int y2 = y_cell + 1;
    160 
    161                 // boundary check
    162                 x1 = std::max(0, x1);
    163                 y1 = std::max(0, y1);
    164                 x2 = std::min(grid_width - 1, x2);
    165                 y2 = std::min(grid_height - 1, y2);
    166 
    167                 for (int yy = y1; yy <= y2; yy++)
    168                 {
    169                     for (int xx = x1; xx <= x2; xx++)
    170                     {
    171                         std::vector<Point2f>& m = grid[yy * grid_width + xx];
    172 
    173                         if (!m.empty())
    174                         {
    175                             for(size_t j = 0; j < m.size(); j++)
    176                             {
    177                                 float dx = p.x - m[j].x;
    178                                 float dy = p.y - m[j].y;
    179 
    180                                 if (dx * dx + dy * dy < minDistance_ * minDistance_)
    181                                 {
    182                                     good = false;
    183                                     goto break_out;
    184                                 }
    185                             }
    186                         }
    187                     }
    188                 }
    189 
    190                 break_out:
    191 
    192                 if(good)
    193                 {
    194                     grid[y_cell * grid_width + x_cell].push_back(p);
    195 
    196                     tmp2.push_back(p);
    197 
    198                     if (maxCorners_ > 0 && tmp2.size() == static_cast<size_t>(maxCorners_))
    199                         break;
    200                 }
    201             }
    202 
    203             _corners.create(1, static_cast<int>(tmp2.size()), CV_32FC2);
    204             GpuMat corners = _corners.getGpuMat();
    205 
    206             corners.upload(Mat(1, static_cast<int>(tmp2.size()), CV_32FC2, &tmp2[0]));
    207         }
    208     }
    209 }
    210 
    211 Ptr<cuda::CornersDetector> cv::cuda::createGoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance,
    212                                                                      int blockSize, bool useHarrisDetector, double harrisK)
    213 {
    214     return Ptr<cuda::CornersDetector>(
    215         new GoodFeaturesToTrackDetector(srcType, maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, harrisK));
    216 }
    217 
    218 #endif /* !defined (HAVE_CUDA) */
    219