Features2d.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007     * Redistributions of source code must retain the above copyright
00008       notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright
00010       notice, this list of conditions and the following disclaimer in the
00011       documentation and/or other materials provided with the distribution.
00012     * Neither the name of the Universite de Sherbrooke nor the
00013       names of its contributors may be used to endorse or promote products
00014       derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
00020 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 */
00027 
00028 #include "rtabmap/core/Features2d.h"
00029 #include "rtabmap/core/util3d.h"
00030 #include "rtabmap/utilite/UStl.h"
00031 #include "rtabmap/utilite/UConversion.h"
00032 #include "rtabmap/utilite/ULogger.h"
00033 #include "rtabmap/utilite/UMath.h"
00034 #include "rtabmap/utilite/ULogger.h"
00035 #include "rtabmap/utilite/UTimer.h"
00036 #include <opencv2/imgproc/imgproc_c.h>
00037 #include <opencv2/gpu/gpu.hpp>
00038 #include <opencv2/core/version.hpp>
00039 
00040 #if RTABMAP_NONFREE == 1
00041 #if CV_MAJOR_VERSION > 2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
00042 #include <opencv2/nonfree/gpu.hpp>
00043 #include <opencv2/nonfree/features2d.hpp>
00044 #endif
00045 #endif
00046 
00047 namespace rtabmap {
00048 
00049 void Feature2D::filterKeypointsByDepth(
00050                 std::vector<cv::KeyPoint> & keypoints,
00051                 const cv::Mat & depth,
00052                 float maxDepth)
00053 {
00054         cv::Mat descriptors;
00055         filterKeypointsByDepth(keypoints, descriptors, depth, maxDepth);
00056 }
00057 
00058 void Feature2D::filterKeypointsByDepth(
00059                 std::vector<cv::KeyPoint> & keypoints,
00060                 cv::Mat & descriptors,
00061                 const cv::Mat & depth,
00062                 float maxDepth)
00063 {
00064         if(!depth.empty() && maxDepth > 0.0f && (descriptors.empty() || descriptors.rows == (int)keypoints.size()))
00065         {
00066                 std::vector<cv::KeyPoint> output(keypoints.size());
00067                 std::vector<int> indexes(keypoints.size(), 0);
00068                 int oi=0;
00069                 bool isInMM = depth.type() == CV_16UC1;
00070                 for(unsigned int i=0; i<keypoints.size(); ++i)
00071                 {
00072                         int u = int(keypoints[i].pt.x+0.5f);
00073                         int v = int(keypoints[i].pt.y+0.5f);
00074                         if(u >=0 && u<depth.cols && v >=0 && v<depth.rows)
00075                         {
00076                                 float d = isInMM?(float)depth.at<uint16_t>(v,u)*0.001f:depth.at<float>(v,u);
00077                                 if(d!=0.0f && uIsFinite(d) && d < maxDepth)
00078                                 {
00079                                         output[oi++] = keypoints[i];
00080                                         indexes[i] = 1;
00081                                 }
00082                         }
00083                 }
00084                 output.resize(oi);
00085                 keypoints = output;
00086 
00087                 if(!descriptors.empty() && (int)keypoints.size() != descriptors.rows)
00088                 {
00089                         if(keypoints.size() == 0)
00090                         {
00091                                 descriptors = cv::Mat();
00092                         }
00093                         else
00094                         {
00095                                 cv::Mat newDescriptors((int)keypoints.size(), descriptors.cols, descriptors.type());
00096                                 int di = 0;
00097                                 for(unsigned int i=0; i<indexes.size(); ++i)
00098                                 {
00099                                         if(indexes[i] == 1)
00100                                         {
00101                                                 if(descriptors.type() == CV_32FC1)
00102                                                 {
00103                                                         memcpy(newDescriptors.ptr<float>(di++), descriptors.ptr<float>(i), descriptors.cols*sizeof(float));
00104                                                 }
00105                                                 else // CV_8UC1
00106                                                 {
00107                                                         memcpy(newDescriptors.ptr<char>(di++), descriptors.ptr<char>(i), descriptors.cols*sizeof(char));
00108                                                 }
00109                                         }
00110                                 }
00111                                 descriptors = newDescriptors;
00112                         }
00113                 }
00114         }
00115 }
00116 
00117 void Feature2D::filterKeypointsByDisparity(
00118                 std::vector<cv::KeyPoint> & keypoints,
00119                 const cv::Mat & disparity,
00120                 float minDisparity)
00121 {
00122         cv::Mat descriptors;
00123         filterKeypointsByDisparity(keypoints, descriptors, disparity, minDisparity);
00124 }
00125 
00126 void Feature2D::filterKeypointsByDisparity(
00127                 std::vector<cv::KeyPoint> & keypoints,
00128                 cv::Mat & descriptors,
00129                 const cv::Mat & disparity,
00130                 float minDisparity)
00131 {
00132         if(!disparity.empty() && minDisparity > 0.0f && (descriptors.empty() || descriptors.rows == (int)keypoints.size()))
00133         {
00134                 std::vector<cv::KeyPoint> output(keypoints.size());
00135                 std::vector<int> indexes(keypoints.size(), 0);
00136                 int oi=0;
00137                 for(unsigned int i=0; i<keypoints.size(); ++i)
00138                 {
00139                         int u = int(keypoints[i].pt.x+0.5f);
00140                         int v = int(keypoints[i].pt.y+0.5f);
00141                         if(u >=0 && u<disparity.cols && v >=0 && v<disparity.rows)
00142                         {
00143                                 float d = disparity.type() == CV_16SC1?float(disparity.at<short>(v,u))/16.0f:disparity.at<float>(v,u);
00144                                 if(d!=0.0f && uIsFinite(d) && d >= minDisparity)
00145                                 {
00146                                         output[oi++] = keypoints[i];
00147                                         indexes[i] = 1;
00148                                 }
00149                         }
00150                 }
00151                 output.resize(oi);
00152                 keypoints = output;
00153 
00154                 if(!descriptors.empty() && (int)keypoints.size() != descriptors.rows)
00155                 {
00156                         if(keypoints.size() == 0)
00157                         {
00158                                 descriptors = cv::Mat();
00159                         }
00160                         else
00161                         {
00162                                 cv::Mat newDescriptors((int)keypoints.size(), descriptors.cols, descriptors.type());
00163                                 int di = 0;
00164                                 for(unsigned int i=0; i<indexes.size(); ++i)
00165                                 {
00166                                         if(indexes[i] == 1)
00167                                         {
00168                                                 if(descriptors.type() == CV_32FC1)
00169                                                 {
00170                                                         memcpy(newDescriptors.ptr<float>(di++), descriptors.ptr<float>(i), descriptors.cols*sizeof(float));
00171                                                 }
00172                                                 else // CV_8UC1
00173                                                 {
00174                                                         memcpy(newDescriptors.ptr<char>(di++), descriptors.ptr<char>(i), descriptors.cols*sizeof(char));
00175                                                 }
00176                                         }
00177                                 }
00178                                 descriptors = newDescriptors;
00179                         }
00180                 }
00181         }
00182 }
00183 
00184 void Feature2D::limitKeypoints(std::vector<cv::KeyPoint> & keypoints, int maxKeypoints)
00185 {
00186         cv::Mat descriptors;
00187         limitKeypoints(keypoints, descriptors, maxKeypoints);
00188 }
00189 
00190 void Feature2D::limitKeypoints(std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors, int maxKeypoints)
00191 {
00192         UASSERT_MSG((int)keypoints.size() == descriptors.rows || descriptors.rows == 0, uFormat("keypoints=%d descriptors=%d", (int)keypoints.size(), descriptors.rows).c_str());
00193         if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints)
00194         {
00195                 UTimer timer;
00196                 ULOGGER_DEBUG("too much words (%d), removing words with the hessian threshold", keypoints.size());
00197                 // Remove words under the new hessian threshold
00198 
00199                 // Sort words by hessian
00200                 std::multimap<float, int> hessianMap; // <hessian,id>
00201                 for(unsigned int i = 0; i <keypoints.size(); ++i)
00202                 {
00203                         //Keep track of the data, to be easier to manage the data in the next step
00204                         hessianMap.insert(std::pair<float, int>(fabs(keypoints[i].response), i));
00205                 }
00206 
00207                 // Remove them from the signature
00208                 int removed = (int)hessianMap.size()-maxKeypoints;
00209                 std::multimap<float, int>::reverse_iterator iter = hessianMap.rbegin();
00210                 std::vector<cv::KeyPoint> kptsTmp(maxKeypoints);
00211                 cv::Mat descriptorsTmp;
00212                 if(descriptors.rows)
00213                 {
00214                         descriptorsTmp = cv::Mat(maxKeypoints, descriptors.cols, descriptors.type());
00215                 }
00216                 for(unsigned int k=0; k < kptsTmp.size() && iter!=hessianMap.rend(); ++k, ++iter)
00217                 {
00218                         kptsTmp[k] = keypoints[iter->second];
00219                         if(descriptors.rows)
00220                         {
00221                                 if(descriptors.type() == CV_32FC1)
00222                                 {
00223                                         memcpy(descriptorsTmp.ptr<float>(k), descriptors.ptr<float>(iter->second), descriptors.cols*sizeof(float));
00224                                 }
00225                                 else
00226                                 {
00227                                         memcpy(descriptorsTmp.ptr<char>(k), descriptors.ptr<char>(iter->second), descriptors.cols*sizeof(char));
00228                                 }
00229                         }
00230                 }
00231                 ULOGGER_DEBUG("%d keypoints removed, (kept %d), minimum response=%f", removed, (int)keypoints.size(), kptsTmp.size()?kptsTmp.back().response:0.0f);
00232                 ULOGGER_DEBUG("removing words time = %f s", timer.ticks());
00233                 keypoints = kptsTmp;
00234                 if(descriptors.rows)
00235                 {
00236                         descriptors = descriptorsTmp;
00237                 }
00238         }
00239 }
00240 
00241 cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::string & roiRatios)
00242 {
00243         std::list<std::string> strValues = uSplit(roiRatios, ' ');
00244         if(strValues.size() != 4)
00245         {
00246                 UERROR("The number of values must be 4 (roi=\"%s\")", roiRatios.c_str());
00247         }
00248         else
00249         {
00250                 std::vector<float> values(4);
00251                 unsigned int i=0;
00252                 for(std::list<std::string>::iterator iter = strValues.begin(); iter!=strValues.end(); ++iter)
00253                 {
00254                         values[i] = uStr2Float(*iter);
00255                         ++i;
00256                 }
00257 
00258                 if(values[0] >= 0 && values[0] < 1 && values[0] < 1.0f-values[1] &&
00259                         values[1] >= 0 && values[1] < 1 && values[1] < 1.0f-values[0] &&
00260                         values[2] >= 0 && values[2] < 1 && values[2] < 1.0f-values[3] &&
00261                         values[3] >= 0 && values[3] < 1 && values[3] < 1.0f-values[2])
00262                 {
00263                         return computeRoi(image, values);
00264                 }
00265                 else
00266                 {
00267                         UERROR("The roi ratios are not valid (roi=\"%s\")", roiRatios.c_str());
00268                 }
00269         }
00270         return cv::Rect();
00271 }
00272 
00273 cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::vector<float> & roiRatios)
00274 {
00275         if(!image.empty() && roiRatios.size() == 4)
00276         {
00277                 float width = image.cols;
00278                 float height = image.rows;
00279                 cv::Rect roi(0, 0, width, height);
00280                 UDEBUG("roi ratios = %f, %f, %f, %f", roiRatios[0],roiRatios[1],roiRatios[2],roiRatios[3]);
00281                 UDEBUG("roi = %d, %d, %d, %d", roi.x, roi.y, roi.width, roi.height);
00282 
00283                 //left roi
00284                 if(roiRatios[0] > 0 && roiRatios[0] < 1 - roiRatios[1])
00285                 {
00286                         roi.x = width * roiRatios[0];
00287                 }
00288 
00289                 //right roi
00290                 roi.width = width - roi.x;
00291                 if(roiRatios[1] > 0 && roiRatios[1] < 1 - roiRatios[0])
00292                 {
00293                         roi.width -= width * roiRatios[1];
00294                 }
00295 
00296                 //top roi
00297                 if(roiRatios[2] > 0 && roiRatios[2] < 1 - roiRatios[3])
00298                 {
00299                         roi.y = height * roiRatios[2];
00300                 }
00301 
00302                 //bottom roi
00303                 roi.height = height - roi.y;
00304                 if(roiRatios[3] > 0 && roiRatios[3] < 1 - roiRatios[2])
00305                 {
00306                         roi.height -= height * roiRatios[3];
00307                 }
00308                 UDEBUG("roi = %d, %d, %d, %d", roi.x, roi.y, roi.width, roi.height);
00309 
00310                 return roi;
00311         }
00312         else
00313         {
00314                 UERROR("Image is null or _roiRatios(=%d) != 4", roiRatios.size());
00315                 return cv::Rect();
00316         }
00317 }
00318 
00320 // Feature2D
00322 Feature2D::Feature2D(const ParametersMap & parameters) :
00323                 maxFeatures_(Parameters::defaultKpWordsPerImage())
00324 {
00325         this->parseParameters(parameters);
00326 }
00327 void Feature2D::parseParameters(const ParametersMap & parameters)
00328 {
00329         Parameters::parse(parameters, Parameters::kKpWordsPerImage(), maxFeatures_);
00330 }
00331 Feature2D * Feature2D::create(Feature2D::Type & type, const ParametersMap & parameters)
00332 {
00333         if(RTABMAP_NONFREE == 0 &&
00334            (type == Feature2D::kFeatureSurf || type == Feature2D::kFeatureSift))
00335         {
00336                 UWARN("SURF/SIFT features cannot be used because OpenCV was not built with nonfree module. ORB is used instead.");
00337                 type = Feature2D::kFeatureOrb;
00338         }
00339         Feature2D * feature2D = 0;
00340         switch(type)
00341         {
00342         case Feature2D::kFeatureSurf:
00343                 feature2D = new SURF(parameters);
00344                 break;
00345         case Feature2D::kFeatureSift:
00346                 feature2D = new SIFT(parameters);
00347                 break;
00348         case Feature2D::kFeatureOrb:
00349                 feature2D = new ORB(parameters);
00350                 break;
00351         case Feature2D::kFeatureFastBrief:
00352                 feature2D = new FAST_BRIEF(parameters);
00353                 break;
00354         case Feature2D::kFeatureFastFreak:
00355                 feature2D = new FAST_FREAK(parameters);
00356                 break;
00357         case Feature2D::kFeatureGfttFreak:
00358                 feature2D = new GFTT_FREAK(parameters);
00359                 break;
00360         case Feature2D::kFeatureGfttBrief:
00361                 feature2D = new GFTT_BRIEF(parameters);
00362                 break;
00363         case Feature2D::kFeatureBrisk:
00364                 feature2D = new BRISK(parameters);
00365                 break;
00366 #if RTABMAP_NONFREE == 1
00367         default:
00368                 feature2D = new SURF(parameters);
00369                 type = Feature2D::kFeatureSurf;
00370                 break;
00371 #else
00372         default:
00373                 feature2D = new ORB(parameters);
00374                 type = Feature2D::kFeatureOrb;
00375                 break;
00376 #endif
00377 
00378         }
00379         return feature2D;
00380 }
00381 std::vector<cv::KeyPoint> Feature2D::generateKeypoints(const cv::Mat & image, const cv::Rect & roi) const
00382 {
00383         std::vector<cv::KeyPoint> keypoints;
00384         if(!image.empty() && image.channels() == 1 && image.type() == CV_8U)
00385         {
00386                 UTimer timer;
00387 
00388                 // Get keypoints
00389                 keypoints = this->generateKeypointsImpl(image, roi.width && roi.height?roi:cv::Rect(0,0,image.cols, image.rows));
00390                 ULOGGER_DEBUG("Keypoints extraction time = %f s, keypoints extracted = %d", timer.ticks(), keypoints.size());
00391 
00392                 limitKeypoints(keypoints, maxFeatures_);
00393 
00394                 if(roi.x || roi.y)
00395                 {
00396                         // Adjust keypoint position to raw image
00397                         for(std::vector<cv::KeyPoint>::iterator iter=keypoints.begin(); iter!=keypoints.end(); ++iter)
00398                         {
00399                                 iter->pt.x += roi.x;
00400                                 iter->pt.y += roi.y;
00401                         }
00402                 }
00403         }
00404         else if(image.empty())
00405         {
00406                 UERROR("Image is null!");
00407         }
00408         else
00409         {
00410                 UERROR("Image format must be mono8. Current has %d channels and type = %d, size=%d,%d",
00411                                 image.channels(), image.type(), image.cols, image.rows);
00412         }
00413 
00414         return keypoints;
00415 }
00416 
00417 cv::Mat Feature2D::generateDescriptors(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
00418 {
00419         cv::Mat descriptors = generateDescriptorsImpl(image, keypoints);
00420         UASSERT_MSG(descriptors.rows == (int)keypoints.size(), uFormat("descriptors=%d, keypoints=%d", descriptors.rows, (int)keypoints.size()).c_str());
00421         UDEBUG("Descriptors extracted = %d, remaining kpts=%d", descriptors.rows, (int)keypoints.size());
00422         return descriptors;
00423 }
00424 
00426 //SURF
00428 SURF::SURF(const ParametersMap & parameters) :
00429                 hessianThreshold_(Parameters::defaultSURFHessianThreshold()),
00430                 nOctaves_(Parameters::defaultSURFOctaves()),
00431                 nOctaveLayers_(Parameters::defaultSURFOctaveLayers()),
00432                 extended_(Parameters::defaultSURFExtended()),
00433                 upright_(Parameters::defaultSURFUpright()),
00434                 gpuKeypointsRatio_(Parameters::defaultSURFGpuKeypointsRatio()),
00435                 gpuVersion_(Parameters::defaultSURFGpuVersion()),
00436                 _surf(0),
00437                 _gpuSurf(0)
00438 {
00439         parseParameters(parameters);
00440 }
00441 
00442 SURF::~SURF()
00443 {
00444 #if RTABMAP_NONFREE == 1
00445         if(_surf)
00446         {
00447                 delete _surf;
00448         }
00449         if(_gpuSurf)
00450         {
00451                 delete _gpuSurf;
00452         }
00453 #endif
00454 }
00455 
00456 void SURF::parseParameters(const ParametersMap & parameters)
00457 {
00458         Feature2D::parseParameters(parameters);
00459 
00460         Parameters::parse(parameters, Parameters::kSURFExtended(), extended_);
00461         Parameters::parse(parameters, Parameters::kSURFHessianThreshold(), hessianThreshold_);
00462         Parameters::parse(parameters, Parameters::kSURFOctaveLayers(), nOctaveLayers_);
00463         Parameters::parse(parameters, Parameters::kSURFOctaves(), nOctaves_);
00464         Parameters::parse(parameters, Parameters::kSURFUpright(), upright_);
00465         Parameters::parse(parameters, Parameters::kSURFGpuKeypointsRatio(), gpuKeypointsRatio_);
00466         Parameters::parse(parameters, Parameters::kSURFGpuVersion(), gpuVersion_);
00467 
00468 #if RTABMAP_NONFREE == 1
00469         if(_gpuSurf)
00470         {
00471                 delete _gpuSurf;
00472                 _gpuSurf = 0;
00473         }
00474         if(_surf)
00475         {
00476                 delete _surf;
00477                 _surf = 0;
00478         }
00479 
00480         if(gpuVersion_ && cv::gpu::getCudaEnabledDeviceCount())
00481         {
00482                 _gpuSurf = new cv::gpu::SURF_GPU(hessianThreshold_, nOctaves_, nOctaveLayers_, extended_, gpuKeypointsRatio_, upright_);
00483         }
00484         else
00485         {
00486                 if(gpuVersion_)
00487                 {
00488                         UWARN("GPU version of SURF not available! Using CPU version instead...");
00489                 }
00490 
00491                 _surf = new cv::SURF(hessianThreshold_, nOctaves_, nOctaveLayers_, extended_, upright_);
00492         }
00493 #else
00494         UWARN("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
00495 #endif
00496 }
00497 
00498 std::vector<cv::KeyPoint> SURF::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
00499 {
00500         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00501         std::vector<cv::KeyPoint> keypoints;
00502 
00503 #if RTABMAP_NONFREE == 1
00504         cv::Mat imgRoi(image, roi);
00505         if(_gpuSurf)
00506         {
00507                 cv::gpu::GpuMat imgGpu(imgRoi);
00508                 (*_gpuSurf)(imgGpu, cv::gpu::GpuMat(), keypoints);
00509         }
00510         else
00511         {
00512                 _surf->detect(imgRoi, keypoints);
00513         }
00514 #else
00515         UWARN("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
00516 #endif
00517         return keypoints;
00518 }
00519 
00520 cv::Mat SURF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
00521 {
00522         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00523         cv::Mat descriptors;
00524 #if RTABMAP_NONFREE == 1
00525         if(_gpuSurf)
00526         {
00527                 cv::gpu::GpuMat imgGpu(image);
00528                 cv::gpu::GpuMat descriptorsGPU;
00529                 (*_gpuSurf)(imgGpu, cv::gpu::GpuMat(), keypoints, descriptorsGPU, true);
00530 
00531                 // Download descriptors
00532                 if (descriptorsGPU.empty())
00533                         descriptors = cv::Mat();
00534                 else
00535                 {
00536                         UASSERT(descriptorsGPU.type() == CV_32F);
00537                         descriptors = cv::Mat(descriptorsGPU.size(), CV_32F);
00538                         descriptorsGPU.download(descriptors);
00539                 }
00540         }
00541         else
00542         {
00543                 _surf->compute(image, keypoints, descriptors);
00544         }
00545 #else
00546         UWARN("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
00547 #endif
00548 
00549         return descriptors;
00550 }
00551 
00553 //SIFT
00555 SIFT::SIFT(const ParametersMap & parameters) :
00556         nfeatures_(Parameters::defaultSIFTNFeatures()),
00557         nOctaveLayers_(Parameters::defaultSIFTNOctaveLayers()),
00558         contrastThreshold_(Parameters::defaultSIFTContrastThreshold()),
00559         edgeThreshold_(Parameters::defaultSIFTEdgeThreshold()),
00560         sigma_(Parameters::defaultSIFTSigma()),
00561         _sift(0)
00562 {
00563         parseParameters(parameters);
00564 }
00565 
00566 SIFT::~SIFT()
00567 {
00568 #if RTABMAP_NONFREE == 1
00569         if(_sift)
00570         {
00571                 delete _sift;
00572         }
00573 #else
00574         UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
00575 #endif
00576 }
00577 
00578 void SIFT::parseParameters(const ParametersMap & parameters)
00579 {
00580         Feature2D::parseParameters(parameters);
00581 
00582         Parameters::parse(parameters, Parameters::kSIFTContrastThreshold(), contrastThreshold_);
00583         Parameters::parse(parameters, Parameters::kSIFTEdgeThreshold(), edgeThreshold_);
00584         Parameters::parse(parameters, Parameters::kSIFTNFeatures(), nfeatures_);
00585         Parameters::parse(parameters, Parameters::kSIFTNOctaveLayers(), nOctaveLayers_);
00586         Parameters::parse(parameters, Parameters::kSIFTSigma(), sigma_);
00587 
00588 #if RTABMAP_NONFREE == 1
00589         if(_sift)
00590         {
00591                 delete _sift;
00592                 _sift = 0;
00593         }
00594 
00595         _sift = new cv::SIFT(nfeatures_, nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_);
00596 #else
00597         UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
00598 #endif
00599 }
00600 
00601 std::vector<cv::KeyPoint> SIFT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
00602 {
00603         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00604         std::vector<cv::KeyPoint> keypoints;
00605 #if RTABMAP_NONFREE == 1
00606         cv::Mat imgRoi(image, roi);
00607         _sift->detect(imgRoi, keypoints); // Opencv keypoints
00608 #else
00609         UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
00610 #endif
00611         return keypoints;
00612 }
00613 
00614 cv::Mat SIFT::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
00615 {
00616         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00617         cv::Mat descriptors;
00618 #if RTABMAP_NONFREE == 1
00619         _sift->compute(image, keypoints, descriptors);
00620 #else
00621         UWARN("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
00622 #endif
00623         return descriptors;
00624 }
00625 
00627 //ORB
00629 ORB::ORB(const ParametersMap & parameters) :
00630                 nFeatures_(Parameters::defaultKpWordsPerImage()),
00631                 scaleFactor_(Parameters::defaultORBScaleFactor()),
00632                 nLevels_(Parameters::defaultORBNLevels()),
00633                 edgeThreshold_(Parameters::defaultORBEdgeThreshold()),
00634                 firstLevel_(Parameters::defaultORBFirstLevel()),
00635                 WTA_K_(Parameters::defaultORBWTA_K()),
00636                 scoreType_(Parameters::defaultORBScoreType()),
00637                 patchSize_(Parameters::defaultORBPatchSize()),
00638                 gpu_(Parameters::defaultORBGpu()),
00639                 fastThreshold_(Parameters::defaultFASTThreshold()),
00640                 nonmaxSuppresion_(Parameters::defaultFASTNonmaxSuppression()),
00641                 _orb(0),
00642                 _gpuOrb(0)
00643 {
00644         parseParameters(parameters);
00645 }
00646 
00647 ORB::~ORB()
00648 {
00649         if(_orb)
00650         {
00651                 delete _orb;
00652         }
00653         if(_gpuOrb)
00654         {
00655                 delete _gpuOrb;
00656         }
00657 }
00658 
00659 void ORB::parseParameters(const ParametersMap & parameters)
00660 {
00661         Feature2D::parseParameters(parameters);
00662 
00663         Parameters::parse(parameters, Parameters::kKpWordsPerImage(), nFeatures_);
00664         Parameters::parse(parameters, Parameters::kORBScaleFactor(), scaleFactor_);
00665         Parameters::parse(parameters, Parameters::kORBNLevels(), nLevels_);
00666         Parameters::parse(parameters, Parameters::kORBEdgeThreshold(), edgeThreshold_);
00667         Parameters::parse(parameters, Parameters::kORBFirstLevel(), firstLevel_);
00668         Parameters::parse(parameters, Parameters::kORBWTA_K(), WTA_K_);
00669         Parameters::parse(parameters, Parameters::kORBScoreType(), scoreType_);
00670         Parameters::parse(parameters, Parameters::kORBPatchSize(), patchSize_);
00671         Parameters::parse(parameters, Parameters::kORBGpu(), gpu_);
00672 
00673         Parameters::parse(parameters, Parameters::kFASTThreshold(), fastThreshold_);
00674         Parameters::parse(parameters, Parameters::kFASTNonmaxSuppression(), nonmaxSuppresion_);
00675 
00676         if(_gpuOrb)
00677         {
00678                 delete _gpuOrb;
00679                 _gpuOrb = 0;
00680         }
00681         if(_orb)
00682         {
00683                 delete _orb;
00684                 _orb = 0;
00685         }
00686 
00687         if(gpu_ && cv::gpu::getCudaEnabledDeviceCount())
00688         {
00689                 _gpuOrb = new cv::gpu::ORB_GPU(nFeatures_, scaleFactor_, nLevels_, edgeThreshold_, firstLevel_, WTA_K_, scoreType_, patchSize_);
00690                 _gpuOrb->setFastParams(fastThreshold_, nonmaxSuppresion_);
00691         }
00692         else
00693         {
00694                 if(gpu_)
00695                 {
00696                         UWARN("GPU version of ORB not available! Using CPU version instead...");
00697                 }
00698                 _orb = new cv::ORB(nFeatures_, scaleFactor_, nLevels_, edgeThreshold_, firstLevel_, WTA_K_, scoreType_, patchSize_);
00699         }
00700 }
00701 
00702 std::vector<cv::KeyPoint> ORB::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
00703 {
00704         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00705         std::vector<cv::KeyPoint> keypoints;
00706         cv::Mat imgRoi(image, roi);
00707         if(_gpuOrb)
00708         {
00709                 cv::gpu::GpuMat imgGpu(imgRoi);
00710                 (*_gpuOrb)(imgGpu, cv::gpu::GpuMat(), keypoints);
00711         }
00712         else
00713         {
00714                 _orb->detect(imgRoi, keypoints);
00715         }
00716 
00717         return keypoints;
00718 }
00719 
00720 cv::Mat ORB::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
00721 {
00722         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00723         cv::Mat descriptors;
00724         if(image.empty())
00725         {
00726                 ULOGGER_ERROR("Image is null ?!?");
00727                 return descriptors;
00728         }
00729         if(_gpuOrb)
00730         {
00731                 cv::gpu::GpuMat imgGpu(image);
00732                 cv::gpu::GpuMat descriptorsGPU;
00733                 (*_gpuOrb)(imgGpu, cv::gpu::GpuMat(), keypoints, descriptorsGPU);
00734 
00735                 // Download descriptors
00736                 if (descriptorsGPU.empty())
00737                         descriptors = cv::Mat();
00738                 else
00739                 {
00740                         UASSERT(descriptorsGPU.type() == CV_32F);
00741                         descriptors = cv::Mat(descriptorsGPU.size(), CV_32F);
00742                         descriptorsGPU.download(descriptors);
00743                 }
00744         }
00745         else
00746         {
00747                 _orb->compute(image, keypoints, descriptors);
00748         }
00749 
00750         return descriptors;
00751 }
00752 
00754 //FAST
00756 FAST::FAST(const ParametersMap & parameters) :
00757                 threshold_(Parameters::defaultFASTThreshold()),
00758                 nonmaxSuppression_(Parameters::defaultFASTNonmaxSuppression()),
00759                 gpu_(Parameters::defaultFASTGpu()),
00760                 gpuKeypointsRatio_(Parameters::defaultFASTGpuKeypointsRatio()),
00761                 _fast(0),
00762                 _gpuFast(0)
00763 {
00764         parseParameters(parameters);
00765 }
00766 
00767 FAST::~FAST()
00768 {
00769         if(_fast)
00770         {
00771                 delete _fast;
00772         }
00773         if(_gpuFast)
00774         {
00775                 delete _gpuFast;
00776         }
00777 }
00778 
00779 void FAST::parseParameters(const ParametersMap & parameters)
00780 {
00781         Feature2D::parseParameters(parameters);
00782 
00783         Parameters::parse(parameters, Parameters::kFASTThreshold(), threshold_);
00784         Parameters::parse(parameters, Parameters::kFASTNonmaxSuppression(), nonmaxSuppression_);
00785         Parameters::parse(parameters, Parameters::kFASTGpu(), gpu_);
00786         Parameters::parse(parameters, Parameters::kFASTGpuKeypointsRatio(), gpuKeypointsRatio_);
00787 
00788         if(_gpuFast)
00789         {
00790                 delete _gpuFast;
00791                 _gpuFast = 0;
00792         }
00793         if(_fast)
00794         {
00795                 delete _fast;
00796                 _fast = 0;
00797         }
00798 
00799         if(gpu_ && cv::gpu::getCudaEnabledDeviceCount())
00800         {
00801                 _gpuFast = new cv::gpu::FAST_GPU(threshold_, nonmaxSuppression_, gpuKeypointsRatio_);
00802         }
00803         else
00804         {
00805                 if(gpu_)
00806                 {
00807                         UWARN("GPU version of FAST not available! Using CPU version instead...");
00808                 }
00809                 _fast = new cv::FastFeatureDetector(threshold_, nonmaxSuppression_);
00810         }
00811 }
00812 
00813 std::vector<cv::KeyPoint> FAST::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
00814 {
00815         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00816         std::vector<cv::KeyPoint> keypoints;
00817         cv::Mat imgRoi(image, roi);
00818         if(_gpuFast)
00819         {
00820                 cv::gpu::GpuMat imgGpu(imgRoi);
00821                 (*_gpuFast)(imgGpu, cv::gpu::GpuMat(), keypoints);
00822         }
00823         else
00824         {
00825                 _fast->detect(imgRoi, keypoints); // Opencv keypoints
00826         }
00827         return keypoints;
00828 }
00829 
00831 //FAST-BRIEF
00833 FAST_BRIEF::FAST_BRIEF(const ParametersMap & parameters) :
00834         FAST(parameters),
00835         bytes_(Parameters::defaultBRIEFBytes()),
00836         _brief(0)
00837 {
00838         parseParameters(parameters);
00839 }
00840 
00841 FAST_BRIEF::~FAST_BRIEF()
00842 {
00843         if(_brief)
00844         {
00845                 delete _brief;
00846         }
00847 }
00848 
00849 void FAST_BRIEF::parseParameters(const ParametersMap & parameters)
00850 {
00851         FAST::parseParameters(parameters);
00852 
00853         Parameters::parse(parameters, Parameters::kBRIEFBytes(), bytes_);
00854         if(_brief)
00855         {
00856                 delete _brief;
00857                 _brief = 0;
00858         }
00859         _brief = new cv::BriefDescriptorExtractor(bytes_);
00860 }
00861 
00862 cv::Mat FAST_BRIEF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
00863 {
00864         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00865         cv::Mat descriptors;
00866         _brief->compute(image, keypoints, descriptors);
00867         return descriptors;
00868 }
00869 
00871 //FAST-FREAK
00873 FAST_FREAK::FAST_FREAK(const ParametersMap & parameters) :
00874         FAST(parameters),
00875         orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()),
00876         scaleNormalized_(Parameters::defaultFREAKScaleNormalized()),
00877         patternScale_(Parameters::defaultFREAKPatternScale()),
00878         nOctaves_(Parameters::defaultFREAKNOctaves()),
00879         _freak(0)
00880 {
00881         parseParameters(parameters);
00882 }
00883 
00884 FAST_FREAK::~FAST_FREAK()
00885 {
00886         if(_freak)
00887         {
00888                 delete _freak;
00889         }
00890 }
00891 
00892 void FAST_FREAK::parseParameters(const ParametersMap & parameters)
00893 {
00894         FAST::parseParameters(parameters);
00895 
00896         Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_);
00897         Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_);
00898         Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_);
00899         Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_);
00900 
00901         if(_freak)
00902         {
00903                 delete _freak;
00904                 _freak = 0;
00905         }
00906 
00907         _freak = new cv::FREAK(orientationNormalized_, scaleNormalized_, patternScale_, nOctaves_);
00908 }
00909 
00910 cv::Mat FAST_FREAK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
00911 {
00912         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00913         cv::Mat descriptors;
00914         _freak->compute(image, keypoints, descriptors);
00915         return descriptors;
00916 }
00917 
00919 //GFTT
00921 GFTT::GFTT(const ParametersMap & parameters) :
00922                 _maxCorners(Parameters::defaultKpWordsPerImage()),
00923                 _qualityLevel(Parameters::defaultGFTTQualityLevel()),
00924                 _minDistance(Parameters::defaultGFTTMinDistance()),
00925                 _blockSize(Parameters::defaultGFTTBlockSize()),
00926                 _useHarrisDetector(Parameters::defaultGFTTUseHarrisDetector()),
00927                 _k(Parameters::defaultGFTTK()),
00928                 _gftt(0)
00929 {
00930         parseParameters(parameters);
00931 }
00932 
00933 GFTT::~GFTT()
00934 {
00935         if(_gftt)
00936         {
00937                 delete _gftt;
00938         }
00939 }
00940 
00941 void GFTT::parseParameters(const ParametersMap & parameters)
00942 {
00943         Feature2D::parseParameters(parameters);
00944 
00945         Parameters::parse(parameters, Parameters::kKpWordsPerImage(), _maxCorners);
00946         Parameters::parse(parameters, Parameters::kGFTTQualityLevel(), _qualityLevel);
00947         Parameters::parse(parameters, Parameters::kGFTTMinDistance(), _minDistance);
00948         Parameters::parse(parameters, Parameters::kGFTTBlockSize(), _blockSize);
00949         Parameters::parse(parameters, Parameters::kGFTTUseHarrisDetector(), _useHarrisDetector);
00950         Parameters::parse(parameters, Parameters::kGFTTK(), _k);
00951 
00952         if(_gftt)
00953         {
00954                 delete _gftt;
00955                 _gftt = 0;
00956         }
00957         _gftt = new cv::GFTTDetector(_maxCorners, _qualityLevel, _minDistance, _blockSize, _useHarrisDetector ,_k);
00958 }
00959 
00960 std::vector<cv::KeyPoint> GFTT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
00961 {
00962         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
00963         std::vector<cv::KeyPoint> keypoints;
00964         cv::Mat imgRoi(image, roi);
00965         _gftt->detect(imgRoi, keypoints); // Opencv keypoints
00966         return keypoints;
00967 }
00968 
00970 //FAST-BRIEF
00972 GFTT_BRIEF::GFTT_BRIEF(const ParametersMap & parameters) :
00973         GFTT(parameters),
00974         bytes_(Parameters::defaultBRIEFBytes()),
00975         _brief(0)
00976 {
00977         parseParameters(parameters);
00978 }
00979 
00980 GFTT_BRIEF::~GFTT_BRIEF()
00981 {
00982         if(_brief)
00983         {
00984                 delete _brief;
00985         }
00986 }
00987 
00988 void GFTT_BRIEF::parseParameters(const ParametersMap & parameters)
00989 {
00990         GFTT::parseParameters(parameters);
00991 
00992         Parameters::parse(parameters, Parameters::kBRIEFBytes(), bytes_);
00993         if(_brief)
00994         {
00995                 delete _brief;
00996                 _brief = 0;
00997         }
00998         _brief = new cv::BriefDescriptorExtractor(bytes_);
00999 }
01000 
01001 cv::Mat GFTT_BRIEF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
01002 {
01003         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
01004         cv::Mat descriptors;
01005         _brief->compute(image, keypoints, descriptors);
01006         return descriptors;
01007 }
01008 
01010 //FAST-FREAK
01012 GFTT_FREAK::GFTT_FREAK(const ParametersMap & parameters) :
01013         GFTT(parameters),
01014         orientationNormalized_(Parameters::defaultFREAKOrientationNormalized()),
01015         scaleNormalized_(Parameters::defaultFREAKScaleNormalized()),
01016         patternScale_(Parameters::defaultFREAKPatternScale()),
01017         nOctaves_(Parameters::defaultFREAKNOctaves()),
01018         _freak(0)
01019 {
01020         parseParameters(parameters);
01021 }
01022 
01023 GFTT_FREAK::~GFTT_FREAK()
01024 {
01025         if(_freak)
01026         {
01027                 delete _freak;
01028         }
01029 }
01030 
01031 void GFTT_FREAK::parseParameters(const ParametersMap & parameters)
01032 {
01033         GFTT::parseParameters(parameters);
01034 
01035         Parameters::parse(parameters, Parameters::kFREAKOrientationNormalized(), orientationNormalized_);
01036         Parameters::parse(parameters, Parameters::kFREAKScaleNormalized(), scaleNormalized_);
01037         Parameters::parse(parameters, Parameters::kFREAKPatternScale(), patternScale_);
01038         Parameters::parse(parameters, Parameters::kFREAKNOctaves(), nOctaves_);
01039 
01040         if(_freak)
01041         {
01042                 delete _freak;
01043                 _freak = 0;
01044         }
01045 
01046         _freak = new cv::FREAK(orientationNormalized_, scaleNormalized_, patternScale_, nOctaves_);
01047 }
01048 
01049 cv::Mat GFTT_FREAK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
01050 {
01051         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
01052         cv::Mat descriptors;
01053         _freak->compute(image, keypoints, descriptors);
01054         return descriptors;
01055 }
01056 
01058 //BRISK
01060 BRISK::BRISK(const ParametersMap & parameters) :
01061         thresh_(Parameters::defaultBRISKThresh()),
01062         octaves_(Parameters::defaultBRISKOctaves()),
01063         patternScale_(Parameters::defaultBRISKPatternScale()),
01064         brisk_(0)
01065 {
01066         parseParameters(parameters);
01067 }
01068 
01069 BRISK::~BRISK()
01070 {
01071         if(brisk_)
01072         {
01073                 delete brisk_;
01074         }
01075 }
01076 
01077 void BRISK::parseParameters(const ParametersMap & parameters)
01078 {
01079         Feature2D::parseParameters(parameters);
01080 
01081         Parameters::parse(parameters, Parameters::kBRISKThresh(), thresh_);
01082         Parameters::parse(parameters, Parameters::kBRISKOctaves(), octaves_);
01083         Parameters::parse(parameters, Parameters::kBRISKPatternScale(), patternScale_);
01084 
01085         if(brisk_)
01086         {
01087                 delete brisk_;
01088                 brisk_ = 0;
01089         }
01090 
01091         brisk_ = new cv::BRISK(thresh_, octaves_, patternScale_);
01092 }
01093 
01094 std::vector<cv::KeyPoint> BRISK::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
01095 {
01096         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
01097         std::vector<cv::KeyPoint> keypoints;
01098         cv::Mat imgRoi(image, roi);
01099         brisk_->detect(imgRoi, keypoints); // Opencv keypoints
01100         return keypoints;
01101 }
01102 
01103 cv::Mat BRISK::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints) const
01104 {
01105         UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
01106         cv::Mat descriptors;
01107         brisk_->compute(image, keypoints, descriptors);
01108         return descriptors;
01109 }
01110 
01111 }


rtabmap
Author(s): Mathieu Labbe
autogenerated on Fri Aug 28 2015 12:51:31