Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers featureselect.cpp Source File

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