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