00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
00198
00199
00200 std::multimap<float, int> hessianMap;
00201 for(unsigned int i = 0; i <keypoints.size(); ++i)
00202 {
00203
00204 hessianMap.insert(std::pair<float, int>(fabs(keypoints[i].response), i));
00205 }
00206
00207
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
00284 if(roiRatios[0] > 0 && roiRatios[0] < 1 - roiRatios[1])
00285 {
00286 roi.x = width * roiRatios[0];
00287 }
00288
00289
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
00297 if(roiRatios[2] > 0 && roiRatios[2] < 1 - roiRatios[3])
00298 {
00299 roi.y = height * roiRatios[2];
00300 }
00301
00302
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
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
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
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
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
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
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);
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
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
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
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);
00826 }
00827 return keypoints;
00828 }
00829
00831
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
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
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);
00966 return keypoints;
00967 }
00968
00970
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
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
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);
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 }