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)
     49 
     50 Ptr<cv::cuda::FastFeatureDetector> cv::cuda::FastFeatureDetector::create(int, bool, int, int) { throw_no_cuda(); return Ptr<cv::cuda::FastFeatureDetector>(); }
     51 
     52 #else /* !defined (HAVE_CUDA) */
     53 
     54 namespace cv { namespace cuda { namespace device
     55 {
     56     namespace fast
     57     {
     58         int calcKeypoints_gpu(PtrStepSzb img, PtrStepSzb mask, short2* kpLoc, int maxKeypoints, PtrStepSzi score, int threshold, cudaStream_t stream);
     59         int nonmaxSuppression_gpu(const short2* kpLoc, int count, PtrStepSzi score, short2* loc, float* response, cudaStream_t stream);
     60     }
     61 }}}
     62 
     63 namespace
     64 {
     65     class FAST_Impl : public cv::cuda::FastFeatureDetector
     66     {
     67     public:
     68         FAST_Impl(int threshold, bool nonmaxSuppression, int max_npoints);
     69 
     70         virtual void detect(InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask);
     71         virtual void detectAsync(InputArray _image, OutputArray _keypoints, InputArray _mask, Stream& stream);
     72 
     73         virtual void convert(InputArray _gpu_keypoints, std::vector<KeyPoint>& keypoints);
     74 
     75         virtual void setThreshold(int threshold) { threshold_ = threshold; }
     76         virtual int getThreshold() const { return threshold_; }
     77 
     78         virtual void setNonmaxSuppression(bool f) { nonmaxSuppression_ = f; }
     79         virtual bool getNonmaxSuppression() const { return nonmaxSuppression_; }
     80 
     81         virtual void setMaxNumPoints(int max_npoints) { max_npoints_ = max_npoints; }
     82         virtual int getMaxNumPoints() const { return max_npoints_; }
     83 
     84         virtual void setType(int type) { CV_Assert( type == TYPE_9_16 ); }
     85         virtual int getType() const { return TYPE_9_16; }
     86 
     87     private:
     88         int threshold_;
     89         bool nonmaxSuppression_;
     90         int max_npoints_;
     91     };
     92 
     93     FAST_Impl::FAST_Impl(int threshold, bool nonmaxSuppression, int max_npoints) :
     94         threshold_(threshold), nonmaxSuppression_(nonmaxSuppression), max_npoints_(max_npoints)
     95     {
     96     }
     97 
     98     void FAST_Impl::detect(InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask)
     99     {
    100         if (_image.empty())
    101         {
    102             keypoints.clear();
    103             return;
    104         }
    105 
    106         BufferPool pool(Stream::Null());
    107         GpuMat d_keypoints = pool.getBuffer(ROWS_COUNT, max_npoints_, CV_16SC2);
    108 
    109         detectAsync(_image, d_keypoints, _mask, Stream::Null());
    110         convert(d_keypoints, keypoints);
    111     }
    112 
    113     void FAST_Impl::detectAsync(InputArray _image, OutputArray _keypoints, InputArray _mask, Stream& stream)
    114     {
    115         using namespace cv::cuda::device::fast;
    116 
    117         const GpuMat img = _image.getGpuMat();
    118         const GpuMat mask = _mask.getGpuMat();
    119 
    120         CV_Assert( img.type() == CV_8UC1 );
    121         CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == img.size()) );
    122 
    123         BufferPool pool(stream);
    124 
    125         GpuMat kpLoc = pool.getBuffer(1, max_npoints_, CV_16SC2);
    126 
    127         GpuMat score;
    128         if (nonmaxSuppression_)
    129         {
    130             score = pool.getBuffer(img.size(), CV_32SC1);
    131             score.setTo(Scalar::all(0), stream);
    132         }
    133 
    134         int count = calcKeypoints_gpu(img, mask, kpLoc.ptr<short2>(), max_npoints_, score, threshold_, StreamAccessor::getStream(stream));
    135         count = std::min(count, max_npoints_);
    136 
    137         if (count == 0)
    138         {
    139             _keypoints.release();
    140             return;
    141         }
    142 
    143         ensureSizeIsEnough(ROWS_COUNT, count, CV_32FC1, _keypoints);
    144         GpuMat& keypoints = _keypoints.getGpuMatRef();
    145 
    146         if (nonmaxSuppression_)
    147         {
    148             count = nonmaxSuppression_gpu(kpLoc.ptr<short2>(), count, score, keypoints.ptr<short2>(LOCATION_ROW), keypoints.ptr<float>(RESPONSE_ROW), StreamAccessor::getStream(stream));
    149             if (count == 0)
    150             {
    151                 keypoints.release();
    152             }
    153             else
    154             {
    155                 keypoints.cols = count;
    156             }
    157         }
    158         else
    159         {
    160             GpuMat locRow(1, count, kpLoc.type(), keypoints.ptr(0));
    161             kpLoc.colRange(0, count).copyTo(locRow, stream);
    162             keypoints.row(1).setTo(Scalar::all(0), stream);
    163         }
    164     }
    165 
    166     void FAST_Impl::convert(InputArray _gpu_keypoints, std::vector<KeyPoint>& keypoints)
    167     {
    168         if (_gpu_keypoints.empty())
    169         {
    170             keypoints.clear();
    171             return;
    172         }
    173 
    174         Mat h_keypoints;
    175         if (_gpu_keypoints.kind() == _InputArray::CUDA_GPU_MAT)
    176         {
    177             _gpu_keypoints.getGpuMat().download(h_keypoints);
    178         }
    179         else
    180         {
    181             h_keypoints = _gpu_keypoints.getMat();
    182         }
    183 
    184         CV_Assert( h_keypoints.rows == ROWS_COUNT );
    185         CV_Assert( h_keypoints.elemSize() == 4 );
    186 
    187         const int npoints = h_keypoints.cols;
    188 
    189         keypoints.resize(npoints);
    190 
    191         const short2* loc_row = h_keypoints.ptr<short2>(LOCATION_ROW);
    192         const float* response_row = h_keypoints.ptr<float>(RESPONSE_ROW);
    193 
    194         for (int i = 0; i < npoints; ++i)
    195         {
    196             KeyPoint kp(loc_row[i].x, loc_row[i].y, static_cast<float>(FEATURE_SIZE), -1, response_row[i]);
    197             keypoints[i] = kp;
    198         }
    199     }
    200 }
    201 
    202 Ptr<cv::cuda::FastFeatureDetector> cv::cuda::FastFeatureDetector::create(int threshold, bool nonmaxSuppression, int type, int max_npoints)
    203 {
    204     CV_Assert( type == TYPE_9_16 );
    205     return makePtr<FAST_Impl>(threshold, nonmaxSuppression, max_npoints);
    206 }
    207 
    208 #endif /* !defined (HAVE_CUDA) */
    209