Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gr-peach-opencv-project-sd-card by
featureselect.cpp
00001 /*M/////////////////////////////////////////////////////////////////////////////////////// 00002 // 00003 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 00004 // 00005 // By downloading, copying, installing or using the software you agree to this license. 00006 // If you do not agree to this license, do not download, install, 00007 // copy or use the software. 00008 // 00009 // 00010 // Intel License Agreement 00011 // For Open Source Computer Vision Library 00012 // 00013 // Copyright (C) 2000, Intel Corporation, all rights reserved. 00014 // Third party copyrights are property of their respective owners. 00015 // 00016 // Redistribution and use in source and binary forms, with or without modification, 00017 // are permitted provided that the following conditions are met: 00018 // 00019 // * Redistribution's of source code must retain the above copyright notice, 00020 // this list of conditions and the following disclaimer. 00021 // 00022 // * Redistribution's in binary form must reproduce the above copyright notice, 00023 // this list of conditions and the following disclaimer in the documentation 00024 // and/or other materials provided with the distribution. 00025 // 00026 // * The name of Intel Corporation may not be used to endorse or promote products 00027 // derived from this software without specific prior written permission. 00028 // 00029 // This software is provided by the copyright holders and contributors "as is" and 00030 // any express or implied warranties, including, but not limited to, the implied 00031 // warranties of merchantability and fitness for a particular purpose are disclaimed. 00032 // In no event shall the Intel Corporation or contributors be liable for any direct, 00033 // indirect, incidental, special, exemplary, or consequential damages 00034 // (including, but not limited to, procurement of substitute goods or services; 00035 // loss of use, data, or profits; or business interruption) however caused 00036 // and on any theory of liability, whether in contract, strict liability, 00037 // or tort (including negligence or otherwise) arising in any way out of 00038 // the use of this software, even if advised of the possibility of such damage. 00039 // 00040 //M*/ 00041 00042 #include "precomp.hpp" 00043 #include "opencl_kernels_imgproc.hpp" 00044 00045 #include <cstdio> 00046 #include <vector> 00047 #include <iostream> 00048 #include <functional> 00049 00050 namespace cv 00051 { 00052 00053 struct greaterThanPtr : 00054 public std::binary_function<const float *, const float *, bool> 00055 { 00056 bool operator () (const float * a, const float * b) const 00057 { return *a > *b; } 00058 }; 00059 00060 #ifdef HAVE_OPENCL 00061 00062 struct Corner 00063 { 00064 float val; 00065 short y; 00066 short x; 00067 00068 bool operator < (const Corner & c) const 00069 { return val > c.val; } 00070 }; 00071 00072 static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, 00073 int maxCorners, double qualityLevel, double minDistance, 00074 InputArray _mask, int blockSize, 00075 bool useHarrisDetector, double harrisK ) 00076 { 00077 UMat eig, maxEigenValue; 00078 if( useHarrisDetector ) 00079 cornerHarris( _image, eig, blockSize, 3, harrisK ); 00080 else 00081 cornerMinEigenVal( _image, eig, blockSize, 3 ); 00082 00083 Size imgsize = _image.size(); 00084 size_t total, i, j, ncorners = 0, possibleCornersCount = 00085 std::max(1024, static_cast<int>(imgsize.area() * 0.1)); 00086 bool haveMask = !_mask.empty(); 00087 UMat corners_buffer(1, (int)possibleCornersCount + 1, CV_32FC2); 00088 CV_Assert(sizeof(Corner) == corners_buffer.elemSize()); 00089 Mat tmpCorners; 00090 00091 // find threshold 00092 { 00093 CV_Assert(eig.type() == CV_32FC1); 00094 int dbsize = ocl::Device::getDefault().maxComputeUnits(); 00095 size_t wgs = ocl::Device::getDefault().maxWorkGroupSize(); 00096 00097 int wgs2_aligned = 1; 00098 while (wgs2_aligned < (int)wgs) 00099 wgs2_aligned <<= 1; 00100 wgs2_aligned >>= 1; 00101 00102 ocl::Kernel k("maxEigenVal", ocl::imgproc::gftt_oclsrc, 00103 format("-D OP_MAX_EIGEN_VAL -D WGS=%d -D groupnum=%d -D WGS2_ALIGNED=%d%s", 00104 (int)wgs, dbsize, wgs2_aligned, haveMask ? " -D HAVE_MASK" : "")); 00105 if (k.empty()) 00106 return false; 00107 00108 UMat mask = _mask.getUMat(); 00109 maxEigenValue.create(1, dbsize, CV_32FC1); 00110 00111 ocl::KernelArg eigarg = ocl::KernelArg::ReadOnlyNoSize(eig), 00112 dbarg = ocl::KernelArg::PtrWriteOnly(maxEigenValue), 00113 maskarg = ocl::KernelArg::ReadOnlyNoSize(mask), 00114 cornersarg = ocl::KernelArg::PtrWriteOnly(corners_buffer); 00115 00116 if (haveMask) 00117 k.args(eigarg, eig.cols, (int)eig.total(), dbarg, maskarg); 00118 else 00119 k.args(eigarg, eig.cols, (int)eig.total(), dbarg); 00120 00121 size_t globalsize = dbsize * wgs; 00122 if (!k.run(1, &globalsize, &wgs, false)) 00123 return false; 00124 00125 ocl::Kernel k2("maxEigenValTask", ocl::imgproc::gftt_oclsrc, 00126 format("-D OP_MAX_EIGEN_VAL -D WGS=%d -D WGS2_ALIGNED=%d -D groupnum=%d", 00127 wgs, wgs2_aligned, dbsize)); 00128 if (k2.empty()) 00129 return false; 00130 00131 k2.args(dbarg, (float)qualityLevel, cornersarg); 00132 00133 if (!k2.runTask(false)) 00134 return false; 00135 } 00136 00137 // collect list of pointers to features - put them into temporary image 00138 { 00139 ocl::Kernel k("findCorners", ocl::imgproc::gftt_oclsrc, 00140 format("-D OP_FIND_CORNERS%s", haveMask ? " -D HAVE_MASK" : "")); 00141 if (k.empty()) 00142 return false; 00143 00144 ocl::KernelArg eigarg = ocl::KernelArg::ReadOnlyNoSize(eig), 00145 cornersarg = ocl::KernelArg::PtrWriteOnly(corners_buffer), 00146 thresholdarg = ocl::KernelArg::PtrReadOnly(maxEigenValue); 00147 00148 if (!haveMask) 00149 k.args(eigarg, cornersarg, eig.rows - 2, eig.cols - 2, thresholdarg, 00150 (int)possibleCornersCount); 00151 else 00152 { 00153 UMat mask = _mask.getUMat(); 00154 k.args(eigarg, ocl::KernelArg::ReadOnlyNoSize(mask), 00155 cornersarg, eig.rows - 2, eig.cols - 2, 00156 thresholdarg, (int)possibleCornersCount); 00157 } 00158 00159 size_t globalsize[2] = { (size_t)eig.cols - 2, (size_t)eig.rows - 2 }; 00160 if (!k.run(2, globalsize, NULL, false)) 00161 return false; 00162 00163 tmpCorners = corners_buffer.getMat(ACCESS_RW); 00164 total = std::min<size_t>(tmpCorners.at<Vec2i>(0, 0)[0], possibleCornersCount); 00165 if (total == 0) 00166 { 00167 _corners.release(); 00168 return true; 00169 } 00170 } 00171 00172 Corner* corner_ptr = tmpCorners.ptr<Corner>() + 1; 00173 std::sort(corner_ptr, corner_ptr + total); 00174 00175 std::vector<Point2f> corners; 00176 corners.reserve(total); 00177 00178 if (minDistance >= 1) 00179 { 00180 // Partition the image into larger grids 00181 int w = imgsize.width, h = imgsize.height; 00182 00183 const int cell_size = cvRound(minDistance); 00184 const int grid_width = (w + cell_size - 1) / cell_size; 00185 const int grid_height = (h + cell_size - 1) / cell_size; 00186 00187 std::vector<std::vector<Point2f> > grid(grid_width*grid_height); 00188 minDistance *= minDistance; 00189 00190 for( i = 0; i < total; i++ ) 00191 { 00192 const Corner & c = corner_ptr[i]; 00193 bool good = true; 00194 00195 int x_cell = c.x / cell_size; 00196 int y_cell = c.y / cell_size; 00197 00198 int x1 = x_cell - 1; 00199 int y1 = y_cell - 1; 00200 int x2 = x_cell + 1; 00201 int y2 = y_cell + 1; 00202 00203 // boundary check 00204 x1 = std::max(0, x1); 00205 y1 = std::max(0, y1); 00206 x2 = std::min(grid_width - 1, x2); 00207 y2 = std::min(grid_height - 1, y2); 00208 00209 for( int yy = y1; yy <= y2; yy++ ) 00210 for( int xx = x1; xx <= x2; xx++ ) 00211 { 00212 std::vector<Point2f> &m = grid[yy * grid_width + xx]; 00213 00214 if( m.size() ) 00215 { 00216 for(j = 0; j < m.size(); j++) 00217 { 00218 float dx = c.x - m[j].x; 00219 float dy = c.y - m[j].y; 00220 00221 if( dx*dx + dy*dy < minDistance ) 00222 { 00223 good = false; 00224 goto break_out; 00225 } 00226 } 00227 } 00228 } 00229 00230 break_out: 00231 00232 if (good) 00233 { 00234 grid[y_cell*grid_width + x_cell].push_back(Point2f((float)c.x, (float)c.y)); 00235 00236 corners.push_back(Point2f((float)c.x, (float)c.y)); 00237 ++ncorners; 00238 00239 if( maxCorners > 0 && (int)ncorners == maxCorners ) 00240 break; 00241 } 00242 } 00243 } 00244 else 00245 { 00246 for( i = 0; i < total; i++ ) 00247 { 00248 const Corner & c = corner_ptr[i]; 00249 00250 corners.push_back(Point2f((float)c.x, (float)c.y)); 00251 ++ncorners; 00252 if( maxCorners > 0 && (int)ncorners == maxCorners ) 00253 break; 00254 } 00255 } 00256 00257 Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); 00258 return true; 00259 } 00260 00261 #endif 00262 00263 } 00264 00265 void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, 00266 int maxCorners, double qualityLevel, double minDistance, 00267 InputArray _mask, int blockSize, 00268 bool useHarrisDetector, double harrisK ) 00269 { 00270 CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); 00271 CV_Assert( _mask.empty() || (_mask.type() == CV_8UC1 && _mask.sameSize(_image)) ); 00272 00273 #ifdef HAVE_OPENCL 00274 CV_OCL_RUN(_image.dims() <= 2 && _image.isUMat(), 00275 ocl_goodFeaturesToTrack(_image, _corners, maxCorners, qualityLevel, minDistance, 00276 _mask, blockSize, useHarrisDetector, harrisK)) 00277 #endif 00278 00279 Mat image = _image.getMat(), eig, tmp; 00280 if (image.empty()) 00281 { 00282 _corners.release(); 00283 return; 00284 } 00285 00286 if( useHarrisDetector ) 00287 cornerHarris( image, eig, blockSize, 3, harrisK ); 00288 else 00289 cornerMinEigenVal( image, eig, blockSize, 3 ); 00290 00291 double maxVal = 0; 00292 minMaxLoc( eig, 0, &maxVal, 0, 0, _mask ); 00293 threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO ); 00294 dilate( eig, tmp, Mat()); 00295 00296 Size imgsize = image.size(); 00297 std::vector<const float*> tmpCorners; 00298 00299 // collect list of pointers to features - put them into temporary image 00300 Mat mask = _mask.getMat(); 00301 for( int y = 1; y < imgsize.height - 1; y++ ) 00302 { 00303 const float* eig_data = (const float*)eig.ptr(y); 00304 const float* tmp_data = (const float*)tmp.ptr(y); 00305 const uchar* mask_data = mask.data ? mask.ptr(y) : 0; 00306 00307 for( int x = 1; x < imgsize.width - 1; x++ ) 00308 { 00309 float val = eig_data[x]; 00310 if( val != 0 && val == tmp_data[x] && (!mask_data || mask_data[x]) ) 00311 tmpCorners.push_back(eig_data + x); 00312 } 00313 } 00314 00315 std::vector<Point2f> corners; 00316 size_t i, j, total = tmpCorners.size(), ncorners = 0; 00317 00318 if (total == 0) 00319 { 00320 _corners.release(); 00321 return; 00322 } 00323 00324 std::sort( tmpCorners.begin(), tmpCorners.end(), greaterThanPtr() ); 00325 00326 if (minDistance >= 1) 00327 { 00328 // Partition the image into larger grids 00329 int w = image.cols; 00330 int h = image.rows; 00331 00332 const int cell_size = cvRound(minDistance); 00333 const int grid_width = (w + cell_size - 1) / cell_size; 00334 const int grid_height = (h + cell_size - 1) / cell_size; 00335 00336 std::vector<std::vector<Point2f> > grid(grid_width*grid_height); 00337 00338 minDistance *= minDistance; 00339 00340 for( i = 0; i < total; i++ ) 00341 { 00342 int ofs = (int)((const uchar*)tmpCorners[i] - eig.ptr()); 00343 int y = (int)(ofs / eig.step); 00344 int x = (int)((ofs - y*eig.step)/sizeof(float)); 00345 00346 bool good = true; 00347 00348 int x_cell = x / cell_size; 00349 int y_cell = y / cell_size; 00350 00351 int x1 = x_cell - 1; 00352 int y1 = y_cell - 1; 00353 int x2 = x_cell + 1; 00354 int y2 = y_cell + 1; 00355 00356 // boundary check 00357 x1 = std::max(0, x1); 00358 y1 = std::max(0, y1); 00359 x2 = std::min(grid_width-1, x2); 00360 y2 = std::min(grid_height-1, y2); 00361 00362 for( int yy = y1; yy <= y2; yy++ ) 00363 { 00364 for( int xx = x1; xx <= x2; xx++ ) 00365 { 00366 std::vector <Point2f> &m = grid[yy*grid_width + xx]; 00367 00368 if( m.size() ) 00369 { 00370 for(j = 0; j < m.size(); j++) 00371 { 00372 float dx = x - m[j].x; 00373 float dy = y - m[j].y; 00374 00375 if( dx*dx + dy*dy < minDistance ) 00376 { 00377 good = false; 00378 goto break_out; 00379 } 00380 } 00381 } 00382 } 00383 } 00384 00385 break_out: 00386 00387 if (good) 00388 { 00389 grid[y_cell*grid_width + x_cell].push_back(Point2f ((float)x, (float)y)); 00390 00391 corners.push_back(Point2f ((float)x, (float)y)); 00392 ++ncorners; 00393 00394 if( maxCorners > 0 && (int)ncorners == maxCorners ) 00395 break; 00396 } 00397 } 00398 } 00399 else 00400 { 00401 for( i = 0; i < total; i++ ) 00402 { 00403 int ofs = (int)((const uchar*)tmpCorners[i] - eig.ptr()); 00404 int y = (int)(ofs / eig.step); 00405 int x = (int)((ofs - y*eig.step)/sizeof(float)); 00406 00407 corners.push_back(Point2f ((float)x, (float)y)); 00408 ++ncorners; 00409 if( maxCorners > 0 && (int)ncorners == maxCorners ) 00410 break; 00411 } 00412 } 00413 00414 Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); 00415 } 00416 00417 CV_IMPL void 00418 cvGoodFeaturesToTrack( const void* _image, void*, void*, 00419 CvPoint2D32f* _corners, int *_corner_count, 00420 double quality_level, double min_distance, 00421 const void* _maskImage, int block_size, 00422 int use_harris, double harris_k ) 00423 { 00424 cv::Mat image = cv::cvarrToMat(_image), mask; 00425 std::vector<cv::Point2f> corners; 00426 00427 if( _maskImage ) 00428 mask = cv::cvarrToMat(_maskImage); 00429 00430 CV_Assert( _corners && _corner_count ); 00431 cv::goodFeaturesToTrack( image, corners, *_corner_count, quality_level, 00432 min_distance, mask, block_size, use_harris != 0, harris_k ); 00433 00434 size_t i, ncorners = corners.size(); 00435 for( i = 0; i < ncorners; i++ ) 00436 _corners[i] = corners[i]; 00437 *_corner_count = (int)ncorners; 00438 } 00439 00440 /* End of file. */ 00441
Generated on Tue Jul 12 2022 14:46:36 by
