45 #include <opencv2/core/core_c.h> 47 #if defined(HAVE_OPENCV_XFEATURES2D) && (CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1)) 48 #include <opencv2/xfeatures2d.hpp> 54 #ifdef RTABMAP_PYMATCHER 62 _minInliers(
Parameters::defaultVisMinInliers()),
63 _inlierDistance(
Parameters::defaultVisInlierDistance()),
64 _iterations(
Parameters::defaultVisIterations()),
65 _refineIterations(
Parameters::defaultVisRefineIterations()),
66 _epipolarGeometryVar(
Parameters::defaultVisEpipolarGeometryVar()),
67 _estimationType(
Parameters::defaultVisEstimationType()),
68 _forwardEstimateOnly(
Parameters::defaultVisForwardEstOnly()),
69 _PnPReprojError(
Parameters::defaultVisPnPReprojError()),
71 _PnPRefineIterations(
Parameters::defaultVisPnPRefineIterations()),
72 _correspondencesApproach(
Parameters::defaultVisCorType()),
73 _flowWinSize(
Parameters::defaultVisCorFlowWinSize()),
74 _flowIterations(
Parameters::defaultVisCorFlowIterations()),
76 _flowMaxLevel(
Parameters::defaultVisCorFlowMaxLevel()),
79 _gmsWithRotation(
Parameters::defaultGMSWithRotation()),
80 _gmsWithScale(
Parameters::defaultGMSWithScale()),
81 _gmsThresholdFactor(
Parameters::defaultGMSThresholdFactor()),
82 _guessWinSize(
Parameters::defaultVisCorGuessWinSize()),
83 _guessMatchToProjection(
Parameters::defaultVisCorGuessMatchToProjection()),
84 _bundleAdjustment(
Parameters::defaultVisBundleAdjustment()),
85 _depthAsMask(
Parameters::defaultVisDepthAsMask()),
86 _minInliersDistributionThr(
Parameters::defaultVisMinInliersDistribution()),
87 _maxInliersMeanDistance(
Parameters::defaultVisMeanInliersDistance()),
90 #ifdef RTABMAP_PYMATCHER
147 UWARN(
"%s should be >= 6 but it is set to %d, setting to 6.", Parameters::kVisMinInliers().c_str(),
_minInliers);
156 #ifndef RTABMAP_PYMATCHER 157 UWARN(
"%s is set to 6 but RTAB-Map is not built with Python3 support, using default %d.",
158 Parameters::kVisCorNNType().c_str(), Parameters::defaultVisCorNNType());
159 _nnType = Parameters::defaultVisCorNNType();
161 int iterations = _pyMatcher?_pyMatcher->iterations():Parameters::defaultPyMatcherIterations();
162 float matchThr = _pyMatcher?_pyMatcher->matchThreshold():Parameters::defaultPyMatcherThreshold();
163 std::string path = _pyMatcher?_pyMatcher->path():Parameters::defaultPyMatcherPath();
164 bool cuda = _pyMatcher?_pyMatcher->cuda():Parameters::defaultPyMatcherCuda();
165 std::string model = _pyMatcher?_pyMatcher->model():Parameters::defaultPyMatcherModel();
173 UERROR(
"%s parameter should be set to use Python3 matching (%s=6), using default %d.",
174 Parameters::kPyMatcherPath().c_str(),
175 Parameters::kVisCorNNType().c_str(),
176 Parameters::defaultVisCorNNType());
177 _nnType = Parameters::defaultVisCorNNType();
182 _pyMatcher =
new PyMatcher(path, matchThr, iterations, cuda, model);
186 #if !defined(HAVE_OPENCV_XFEATURES2D) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION<4 || CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<1)) 189 UWARN(
"%s is set to 7 but RTAB-Map is not built with OpenCV's xfeatures2d support (OpenCV >= 3.4.1 also required), using default %d.",
190 Parameters::kVisCorNNType().c_str(), Parameters::defaultVisCorNNType());
191 _nnType = Parameters::defaultVisCorNNType();
196 for(ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
198 std::string group =
uSplit(iter->first,
'/').front();
205 if(
uContains(parameters, Parameters::kVisCorNNType()))
212 if(
uContains(parameters, Parameters::kVisCorNNDR()))
216 if(
uContains(parameters, Parameters::kKpByteToFloat()))
220 if(
uContains(parameters, Parameters::kVisFeatureType()))
224 if(
uContains(parameters, Parameters::kVisMaxFeatures()))
228 if(
uContains(parameters, Parameters::kVisMaxDepth()))
232 if(
uContains(parameters, Parameters::kVisMinDepth()))
236 if(
uContains(parameters, Parameters::kVisRoiRatios()))
240 if(
uContains(parameters, Parameters::kVisSubPixEps()))
244 if(
uContains(parameters, Parameters::kVisSubPixIterations()))
248 if(
uContains(parameters, Parameters::kVisSubPixWinSize()))
252 if(
uContains(parameters, Parameters::kVisGridRows()))
256 if(
uContains(parameters, Parameters::kVisGridCols()))
271 #ifdef RTABMAP_PYMATCHER 295 UDEBUG(
"%s=%f", Parameters::kVisCorNNDR().c_str(),
_nndr);
296 UDEBUG(
"%s=%d", Parameters::kVisCorNNType().c_str(),
_nnType);
302 UDEBUG(
"Input(%d): from=%d words, %d 3D words, %d words descriptors, %d kpts, %d kpts3D, %d descriptors, image=%dx%d models=%d stereo=%d",
304 (int)fromSignature.
getWords().size(),
315 UDEBUG(
"Input(%d): to=%d words, %d 3D words, %d words descriptors, %d kpts, %d kpts3D, %d descriptors, image=%dx%d models=%d stereo=%d",
342 UDEBUG(
"Bypassing feature matching as descriptors and images are empty. We assume features are already matched.");
369 std::vector<cv::KeyPoint> kptsFrom;
373 std::vector<int> orignalWordsFromIds;
374 int kptsFromSource = 0;
375 if(fromSignature.
getWords().empty())
379 if(!imageFrom.empty())
381 if(imageFrom.channels() > 1)
384 cv::cvtColor(imageFrom, tmp, cv::COLOR_BGR2GRAY);
413 orignalWordsFromIds.resize(fromSignature.
getWords().size());
415 bool allUniques =
true;
416 int previousIdAdded = 0;
418 for(std::multimap<int, int>::const_iterator iter=fromSignature.
getWords().begin(); iter!=fromSignature.
getWords().end(); ++iter)
420 UASSERT(iter->second>=0 && iter->second<(
int)orignalWordsFromIds.size());
421 orignalWordsFromIds[iter->second] = iter->first;
422 if(i>0 && iter->first==previousIdAdded)
426 previousIdAdded = iter->first;
431 UDEBUG(
"IDs are not unique, IDs will be regenerated!");
432 orignalWordsFromIds.clear();
436 std::multimap<int, int> wordsFrom;
437 std::multimap<int, int> wordsTo;
438 std::vector<cv::KeyPoint> wordsKptsFrom;
439 std::vector<cv::KeyPoint> wordsKptsTo;
440 std::vector<cv::Point3f> words3From;
441 std::vector<cv::Point3f> words3To;
442 cv::Mat wordsDescFrom;
448 if(imageFrom.channels() > 1)
451 cv::cvtColor(imageFrom, tmp, cv::COLOR_BGR2GRAY);
454 if(imageTo.channels() > 1)
457 cv::cvtColor(imageTo, tmp, cv::COLOR_BGR2GRAY);
461 std::vector<cv::Point3f> kptsFrom3D;
462 if(kptsFrom.size() == fromSignature.
getWords3().size())
475 if(!imageFrom.empty() && !imageTo.empty())
477 std::vector<cv::Point2f> cornersFrom;
478 cv::KeyPoint::convert(kptsFrom, cornersFrom);
479 std::vector<cv::Point2f> cornersTo;
485 cv::Mat R = (cv::Mat_<double>(3,3) <<
486 (
double)guessCameraRef.
r11(), (double)guessCameraRef.
r12(), (double)guessCameraRef.
r13(),
487 (double)guessCameraRef.
r21(), (double)guessCameraRef.
r22(), (double)guessCameraRef.
r23(),
488 (double)guessCameraRef.
r31(), (double)guessCameraRef.
r32(), (double)guessCameraRef.
r33());
489 cv::Mat rvec(1,3, CV_64FC1);
490 cv::Rodrigues(R, rvec);
491 cv::Mat tvec = (cv::Mat_<double>(1,3) << (
double)guessCameraRef.
x(), (double)guessCameraRef.
y(), (double)guessCameraRef.
z());
493 cv::projectPoints(kptsFrom3D, rvec, tvec, K, cv::Mat(), cornersTo);
497 UDEBUG(
"guessSet = %d", guessSet?1:0);
498 std::vector<unsigned char> status;
499 std::vector<float> err;
500 UDEBUG(
"cv::calcOpticalFlowPyrLK() begin");
501 cv::calcOpticalFlowPyrLK(
511 cv::OPTFLOW_LK_GET_MIN_EIGENVALS | (guessSet?cv::OPTFLOW_USE_INITIAL_FLOW:0), 1
e-4);
512 UDEBUG(
"cv::calcOpticalFlowPyrLK() end");
514 UASSERT(kptsFrom.size() == kptsFrom3D.size());
515 std::vector<cv::KeyPoint> kptsTo(kptsFrom.size());
516 std::vector<cv::Point3f> kptsFrom3DKept(kptsFrom3D.size());
517 std::vector<int> orignalWordsFromIdsCpy = orignalWordsFromIds;
519 for(
unsigned int i=0; i<status.size(); ++i)
522 uIsInBounds(cornersTo[i].x, 0.0
f,
float(imageTo.cols)) &&
525 if(orignalWordsFromIdsCpy.size())
527 orignalWordsFromIds[ki] = orignalWordsFromIdsCpy[i];
529 kptsFrom[ki] = cv::KeyPoint(cornersFrom[i], 1);
530 kptsFrom3DKept[ki] = kptsFrom3D[i];
531 kptsTo[ki++] = cv::KeyPoint(cornersTo[i], 1);
534 if(orignalWordsFromIds.size())
536 orignalWordsFromIds.resize(ki);
540 kptsFrom3DKept.resize(ki);
541 kptsFrom3D = kptsFrom3DKept;
543 std::vector<cv::Point3f> kptsTo3D;
549 UASSERT(kptsFrom.size() == kptsFrom3DKept.size());
550 UASSERT(kptsFrom.size() == kptsTo.size());
551 UASSERT(kptsTo3D.size() == 0 || kptsTo.size() == kptsTo3D.size());
552 for(
unsigned int i=0; i< kptsFrom3DKept.size(); ++i)
554 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
555 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
556 wordsKptsFrom.push_back(kptsFrom[i]);
557 words3From.push_back(kptsFrom3DKept[i]);
559 wordsTo.insert(wordsTo.end(), std::make_pair(
id, wordsTo.size()));
560 wordsKptsTo.push_back(kptsTo[i]);
561 if(!kptsTo3D.empty())
563 words3To.push_back(kptsTo3D[i]);
570 if(imageFrom.empty())
572 UERROR(
"Optical flow correspondences requires images in data!");
574 UASSERT(kptsFrom.size() == kptsFrom3D.size());
575 for(
unsigned int i=0; i< kptsFrom3D.size(); ++i)
579 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
580 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
581 wordsKptsFrom.push_back(kptsFrom[i]);
582 words3From.push_back(kptsFrom3D[i]);
585 toSignature.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
593 std::vector<cv::KeyPoint> kptsTo;
594 int kptsToSource = 0;
600 if(imageTo.channels() > 1)
603 cv::cvtColor(imageTo, tmp, cv::COLOR_BGR2GRAY);
635 UDEBUG(
"kptsFrom=%d kptsFromSource=%d", (
int)kptsFrom.size(), kptsFromSource);
636 UDEBUG(
"kptsTo=%d kptsToSource=%d", (
int)kptsTo.size(), kptsToSource);
637 cv::Mat descriptorsFrom;
638 if(kptsFromSource == 2 &&
645 else if(kptsFromSource == 1 &&
650 else if(!imageFrom.empty())
652 if(imageFrom.channels() > 1)
655 cv::cvtColor(imageFrom, tmp, cv::COLOR_BGR2GRAY);
658 UDEBUG(
"cleared orignalWordsFromIds");
659 orignalWordsFromIds.clear();
663 cv::Mat descriptorsTo;
666 if(kptsToSource == 2 &&
671 else if(kptsToSource == 1 &&
676 else if(!imageTo.empty())
678 if(imageTo.channels() > 1)
681 cv::cvtColor(imageTo, tmp, cv::COLOR_BGR2GRAY);
690 std::vector<cv::Point3f> kptsFrom3D;
691 std::vector<cv::Point3f> kptsTo3D;
692 if(kptsFromSource == 2 &&
693 kptsFrom.size() == fromSignature.
getWords3().size())
697 else if(kptsFromSource == 1 &&
704 if(fromSignature.
getWords3().size() && kptsFrom.size() != fromSignature.
getWords3().size())
706 UWARN(
"kptsFrom (%d) is not the same size as fromSignature.getWords3() (%d), there " 707 "is maybe a problem with the logic above (getWords3() should be null or equal to kptsfrom). Regenerating kptsFrom3D...",
713 UWARN(
"kptsFrom (%d) is not the same size as fromSignature.sensorData().keypoints3D() (%d), there " 714 "is maybe a problem with the logic above (keypoints3D should be null or equal to kptsfrom). Regenerating kptsFrom3D...",
719 UDEBUG(
"generated kptsFrom3D=%d", (
int)kptsFrom3D.size());
722 if(!kptsFrom3D.empty() &&
729 if(kptsToSource == 2 && kptsTo.size() == toSignature.
getWords3().size())
733 else if(kptsToSource == 1 &&
742 UWARN(
"kptsTo (%d) is not the same size as toSignature.getWords3() (%d), there " 743 "is maybe a problem with the logic above (getWords3() should be null or equal to kptsTo). Regenerating kptsTo3D...",
749 UWARN(
"kptsTo (%d) is not the same size as toSignature.sensorData().keypoints3D() (%d), there " 750 "is maybe a problem with the logic above (keypoints3D() should be null or equal to kptsTo). Regenerating kptsTo3D...",
757 if(kptsTo3D.size() &&
764 UASSERT(kptsFrom.empty() || descriptorsFrom.rows == 0 || int(kptsFrom.size()) == descriptorsFrom.rows);
769 UDEBUG(
"descriptorsFrom=%d", descriptorsFrom.rows);
770 UDEBUG(
"descriptorsTo=%d", descriptorsTo.rows);
771 UDEBUG(
"orignalWordsFromIds=%d", (
int)orignalWordsFromIds.size());
774 if(descriptorsFrom.rows > 0 && descriptorsTo.rows > 0)
776 cv::Size imageSize = imageTo.size();
777 bool isCalibrated =
false;
778 if(imageSize.height == 0 || imageSize.width == 0)
783 isCalibrated = imageSize.height != 0 && imageSize.width != 0 &&
793 UASSERT((
int)kptsTo.size() == descriptorsTo.rows);
794 UASSERT((
int)kptsFrom3D.size() == descriptorsFrom.rows);
799 UFATAL(
"Guess reprojection feature matching is not supported for multiple cameras.");
804 cv::Mat R = (cv::Mat_<double>(3,3) <<
805 (
double)guessCameraRef.
r11(), (double)guessCameraRef.
r12(), (double)guessCameraRef.
r13(),
806 (double)guessCameraRef.
r21(), (double)guessCameraRef.
r22(), (double)guessCameraRef.
r23(),
807 (double)guessCameraRef.
r31(), (double)guessCameraRef.
r32(), (double)guessCameraRef.
r33());
808 cv::Mat rvec(1,3, CV_64FC1);
809 cv::Rodrigues(R, rvec);
810 cv::Mat tvec = (cv::Mat_<double>(1,3) << (
double)guessCameraRef.
x(), (double)guessCameraRef.
y(), (double)guessCameraRef.
z());
812 std::vector<cv::Point2f> projected;
813 cv::projectPoints(kptsFrom3D, rvec, tvec, K, cv::Mat(), projected);
814 UDEBUG(
"Projected points=%d", (
int)projected.size());
816 UASSERT((
int)projected.size() == descriptorsFrom.rows);
817 std::vector<cv::Point2f> cornersProjected(projected.size());
818 std::vector<int> projectedIndexToDescIndex(projected.size());
820 for(
unsigned int i=0; i<projected.size(); ++i)
822 if(
uIsInBounds(projected[i].x, 0.0
f,
float(imageSize.width-1)) &&
823 uIsInBounds(projected[i].y, 0.0
f,
float(imageSize.height-1)) &&
826 projectedIndexToDescIndex[oi] = i;
827 cornersProjected[oi++] = projected[i];
830 projectedIndexToDescIndex.resize(oi);
831 cornersProjected.resize(oi);
832 UDEBUG(
"corners in frame=%d", (
int)cornersProjected.size());
838 if(cornersProjected.size())
842 UDEBUG(
"match frame to projected");
848 std::vector< std::vector<size_t> > indices;
849 std::vector<std::vector<float> > dists;
851 std::vector<cv::Point2f> pointsTo;
852 cv::KeyPoint::convert(kptsTo, pointsTo);
856 UASSERT(indices.size() == pointsToMat.rows);
857 UASSERT(descriptorsFrom.cols == descriptorsTo.cols);
858 UASSERT(descriptorsFrom.rows == (
int)kptsFrom.size());
859 UASSERT((
int)pointsToMat.rows == descriptorsTo.rows);
860 UASSERT(pointsToMat.rows == kptsTo.size());
861 UDEBUG(
"radius search done for guess");
864 int newToId = !orignalWordsFromIds.empty()?fromSignature.
getWords().rbegin()->first+1:descriptorsFrom.rows;
865 std::map<int,int> addedWordsFrom;
866 std::map<int, int> duplicates;
868 cv::Mat descriptors(10, descriptorsTo.cols, descriptorsTo.type());
869 for(
unsigned int i = 0; i < pointsToMat.rows; ++i)
871 int matchedIndex = -1;
872 if(indices[i].size() >= 2)
874 std::vector<int> descriptorsIndices(indices[i].size());
876 if((
int)indices[i].size() > descriptors.rows)
878 descriptors.resize(indices[i].size());
880 for(
unsigned int j=0; j<indices[i].size(); ++j)
882 descriptorsFrom.row(projectedIndexToDescIndex[indices[i].at(j)]).copyTo(descriptors.row(oi));
883 descriptorsIndices[oi++] = indices[i].at(j);
885 descriptorsIndices.resize(oi);
888 cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR,
_nnType == 5);
891 std::vector<cv::DMatch> matches;
892 matcher.match(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches);
895 matchedIndex = descriptorsIndices.at(matches.at(0).trainIdx);
900 std::vector<std::vector<cv::DMatch> > matches;
901 matcher.knnMatch(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
903 UASSERT(matches[0].size() == 2);
906 matchedIndex = descriptorsIndices.at(matches[0].at(0).trainIdx);
910 else if(indices[i].size() == 1)
912 matchedIndex = indices[i].at(0);
915 if(matchedIndex >= 0)
917 matchedIndex = projectedIndexToDescIndex[matchedIndex];
918 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndex]:matchedIndex;
920 if(addedWordsFrom.find(matchedIndex) != addedWordsFrom.end())
922 id = addedWordsFrom.at(matchedIndex);
923 duplicates.insert(std::make_pair(matchedIndex,
id));
927 addedWordsFrom.insert(std::make_pair(matchedIndex,
id));
929 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
930 if(!kptsFrom.empty())
932 wordsKptsFrom.push_back(kptsFrom[matchedIndex]);
934 words3From.push_back(kptsFrom3D[matchedIndex]);
935 wordsDescFrom.push_back(descriptorsFrom.row(matchedIndex));
938 wordsTo.insert(wordsTo.end(), std::make_pair(
id, wordsTo.size()));
939 wordsKptsTo.push_back(kptsTo[i]);
940 wordsDescTo.push_back(descriptorsTo.row(i));
941 if(!kptsTo3D.empty())
943 words3To.push_back(kptsTo3D[i]);
949 wordsTo.insert(wordsTo.end(), std::make_pair(newToId, wordsTo.size()));
950 wordsKptsTo.push_back(kptsTo[i]);
951 wordsDescTo.push_back(descriptorsTo.row(i));
952 if(!kptsTo3D.empty())
954 words3To.push_back(kptsTo3D[i]);
961 UDEBUG(
"addedWordsFrom=%d/%d (duplicates=%d, newWords=%d), kptsTo=%d, wordsTo=%d, words3From=%d",
962 (
int)addedWordsFrom.size(), (int)cornersProjected.size(), (int)duplicates.size(), newWords,
963 (int)kptsTo.size(), (int)wordsTo.size(), (int)words3From.size());
966 int addWordsFromNotMatched = 0;
967 for(
unsigned int i=0; i<kptsFrom3D.size(); ++i)
969 if(
util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end())
971 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
972 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
973 wordsKptsFrom.push_back(kptsFrom[i]);
974 wordsDescFrom.push_back(descriptorsFrom.row(i));
975 words3From.push_back(kptsFrom3D[i]);
977 ++addWordsFromNotMatched;
980 UDEBUG(
"addWordsFromNotMatched=%d -> words3From=%d", addWordsFromNotMatched, (
int)words3From.size());
984 UDEBUG(
"match projected to frame");
985 std::vector<cv::Point2f> pointsTo;
986 cv::KeyPoint::convert(kptsTo, pointsTo);
991 std::vector< std::vector<size_t> > indices;
992 std::vector<std::vector<float> > dists;
997 UASSERT(indices.size() == cornersProjectedMat.rows);
998 UASSERT(descriptorsFrom.cols == descriptorsTo.cols);
999 UASSERT(descriptorsFrom.rows == (
int)kptsFrom.size());
1000 UASSERT((
int)pointsToMat.rows == descriptorsTo.rows);
1001 UASSERT(pointsToMat.rows == kptsTo.size());
1002 UDEBUG(
"radius search done for guess");
1005 std::set<int> addedWordsTo;
1006 std::set<int> addedWordsFrom;
1007 double bruteForceTotalTime = 0.0;
1008 double bruteForceDescCopy = 0.0;
1010 cv::Mat descriptors(10, descriptorsTo.cols, descriptorsTo.type());
1011 for(
unsigned int i = 0; i < cornersProjectedMat.rows; ++i)
1013 int matchedIndexFrom = projectedIndexToDescIndex[i];
1015 if(indices[i].size())
1017 info.
projectedIDs.push_back(!orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom);
1022 int matchedIndexTo = -1;
1023 if(indices[i].size() >= 2)
1026 std::vector<int> descriptorsIndices(indices[i].size());
1028 if((
int)indices[i].size() > descriptors.rows)
1030 descriptors.resize(indices[i].size());
1032 for(
unsigned int j=0; j<indices[i].size(); ++j)
1034 descriptorsTo.row(indices[i].at(j)).copyTo(descriptors.row(oi));
1035 descriptorsIndices[oi++] = indices[i].at(j);
1037 bruteForceDescCopy += bruteForceTimer.
ticks();
1040 cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR,
_nnType==5);
1043 std::vector<cv::DMatch> matches;
1044 matcher.match(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches);
1045 if(!matches.empty())
1047 matchedIndexTo = descriptorsIndices.at(matches.at(0).trainIdx);
1052 std::vector<std::vector<cv::DMatch> > matches;
1053 matcher.knnMatch(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
1055 UASSERT(matches[0].size() == 2);
1056 bruteForceTotalTime+=bruteForceTimer.
elapsed();
1059 matchedIndexTo = descriptorsIndices.at(matches[0].at(0).trainIdx);
1063 else if(indices[i].size() == 1)
1065 matchedIndexTo = indices[i].at(0);
1068 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom;
1069 addedWordsFrom.insert(addedWordsFrom.end(), matchedIndexFrom);
1071 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
1072 if(!kptsFrom.empty())
1074 wordsKptsFrom.push_back(kptsFrom[matchedIndexFrom]);
1076 words3From.push_back(kptsFrom3D[matchedIndexFrom]);
1077 wordsDescFrom.push_back(descriptorsFrom.row(matchedIndexFrom));
1079 if( matchedIndexTo >= 0 &&
1080 addedWordsTo.find(matchedIndexTo) == addedWordsTo.end())
1082 addedWordsTo.insert(matchedIndexTo);
1084 wordsTo.insert(wordsTo.end(), std::make_pair(
id, wordsTo.size()));
1085 wordsKptsTo.push_back(kptsTo[matchedIndexTo]);
1086 wordsDescTo.push_back(descriptorsTo.row(matchedIndexTo));
1087 if(!kptsTo3D.empty())
1089 words3To.push_back(kptsTo3D[matchedIndexTo]);
1094 UDEBUG(
"bruteForceDescCopy=%fs, bruteForceTotalTime=%fs", bruteForceDescCopy, bruteForceTotalTime);
1097 for(
unsigned int i=0; i<kptsFrom3D.size(); ++i)
1099 if(
util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end())
1101 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
1102 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
1103 wordsKptsFrom.push_back(kptsFrom[i]);
1104 wordsDescFrom.push_back(descriptorsFrom.row(i));
1105 words3From.push_back(kptsFrom3D[i]);
1109 int newToId = !orignalWordsFromIds.empty()?fromSignature.
getWords().rbegin()->first+1:descriptorsFrom.rows;
1110 for(
unsigned int i = 0; i < kptsTo.size(); ++i)
1112 if(addedWordsTo.find(i) == addedWordsTo.end())
1114 wordsTo.insert(wordsTo.end(), std::make_pair(newToId, wordsTo.size()));
1115 wordsKptsTo.push_back(kptsTo[i]);
1116 wordsDescTo.push_back(descriptorsTo.row(i));
1117 if(!kptsTo3D.empty())
1119 words3To.push_back(kptsTo3D[i]);
1128 UWARN(
"All projected points are outside the camera. Guess (%s) is wrong or images are not overlapping.", guess.
prettyPrint().c_str());
1134 if(guessSet &&
_guessWinSize > 0 && kptsFrom3D.size() && !isCalibrated)
1138 UWARN(
"Finding correspondences with the guess cannot " 1139 "be done with multiple cameras, global matching is " 1140 "done instead. Please set \"%s\" to 0 to avoid this warning.",
1141 Parameters::kVisCorGuessWinSize().c_str());
1145 UWARN(
"Calibration not found! Finding correspondences " 1146 "with the guess cannot be done, global matching is " 1153 std::list<int> fromWordIds;
1154 std::list<int> toWordIds;
1155 #ifdef RTABMAP_PYMATCHER 1161 std::vector<int> fromWordIdsV(descriptorsFrom.rows);
1162 for (
int i = 0; i < descriptorsFrom.rows; ++i)
1165 if(!orignalWordsFromIds.empty())
1167 id = orignalWordsFromIds[i];
1169 fromWordIds.push_back(
id);
1170 fromWordIdsV[i] = id;
1172 if(descriptorsTo.rows)
1174 std::vector<int> toWordIdsV(descriptorsTo.rows, 0);
1175 std::vector<cv::DMatch> matches;
1176 #ifdef RTABMAP_PYMATCHER 1177 if(
_nnType == 6 && _pyMatcher &&
1178 descriptorsTo.cols == descriptorsFrom.cols &&
1179 descriptorsTo.rows == (
int)kptsTo.size() &&
1180 descriptorsTo.type() == CV_32F &&
1181 descriptorsFrom.type() == CV_32F &&
1182 descriptorsFrom.rows == (int)kptsFrom.size() &&
1183 imageSize.width > 0 && imageSize.height > 0)
1185 UDEBUG(
"Python matching");
1186 matches = _pyMatcher->match(descriptorsTo, descriptorsFrom, kptsTo, kptsFrom, imageSize);
1190 if(
_nnType == 6 && _pyMatcher)
1192 UDEBUG(
"Invalid inputs for Python matching (desc type=%d, only float descriptors supported), doing bruteforce matching instead.", descriptorsFrom.type());
1197 bool doCrossCheck =
true;
1198 #ifdef HAVE_OPENCV_XFEATURES2D 1199 #if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1) 1200 cv::Size imageSizeFrom;
1203 imageSizeFrom = imageFrom.size();
1204 if(imageSizeFrom.height == 0 || imageSizeFrom.width == 0)
1208 if(imageSize.height > 0 && imageSize.width > 0 &&
1209 imageSizeFrom.height > 0 && imageSizeFrom.width > 0)
1211 doCrossCheck =
false;
1215 UDEBUG(
"Invalid inputs for GMS matching, image size should be set for both inputs, doing bruteforce matching instead.");
1221 UDEBUG(
"BruteForce matching%s",
_nnType!=7?
" with crosscheck":
" with GMS");
1222 cv::BFMatcher matcher(descriptorsFrom.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, doCrossCheck);
1223 matcher.match(descriptorsTo, descriptorsFrom, matches);
1225 #if defined(HAVE_OPENCV_XFEATURES2D) && (CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1)) 1228 std::vector<cv::DMatch> matchesGMS;
1230 matches = matchesGMS;
1234 for(
size_t i=0; i<matches.size(); ++i)
1236 toWordIdsV[matches[i].queryIdx] = fromWordIdsV[matches[i].trainIdx];
1238 for(
size_t i=0; i<toWordIdsV.size(); ++i)
1240 int toId = toWordIdsV[i];
1243 toId = fromWordIds.back()+i+1;
1245 toWordIds.push_back(toId);
1251 UDEBUG(
"VWDictionary knn matching");
1253 if(orignalWordsFromIds.empty())
1255 fromWordIds = dictionary.
addNewWords(descriptorsFrom, 1);
1259 for (
int i = 0; i < descriptorsFrom.rows; ++i)
1261 int id = orignalWordsFromIds[i];
1263 fromWordIds.push_back(
id);
1267 if(descriptorsTo.rows)
1270 toWordIds = dictionary.
addNewWords(descriptorsTo, 2);
1272 dictionary.
clear(
false);
1275 std::multiset<int> fromWordIdsSet(fromWordIds.begin(), fromWordIds.end());
1276 std::multiset<int> toWordIdsSet(toWordIds.begin(), toWordIds.end());
1278 UASSERT(kptsFrom3D.empty() || fromWordIds.size() == kptsFrom3D.size());
1279 UASSERT(
int(fromWordIds.size()) == descriptorsFrom.rows);
1281 for(std::list<int>::iterator iter=fromWordIds.begin(); iter!=fromWordIds.end(); ++iter)
1283 if(fromWordIdsSet.count(*iter) == 1)
1285 wordsFrom.insert(wordsFrom.end(), std::make_pair(*iter, wordsFrom.size()));
1286 if (!kptsFrom.empty())
1288 wordsKptsFrom.push_back(kptsFrom[i]);
1290 if(!kptsFrom3D.empty())
1292 words3From.push_back(kptsFrom3D[i]);
1294 wordsDescFrom.push_back(descriptorsFrom.row(i));
1298 UASSERT(kptsTo3D.size() == 0 || kptsTo3D.size() == kptsTo.size());
1299 UASSERT(toWordIds.size() == kptsTo.size());
1300 UASSERT(
int(toWordIds.size()) == descriptorsTo.rows);
1302 for(std::list<int>::iterator iter=toWordIds.begin(); iter!=toWordIds.end(); ++iter)
1304 if(toWordIdsSet.count(*iter) == 1)
1306 wordsTo.insert(wordsTo.end(), std::make_pair(*iter, wordsTo.size()));
1307 wordsKptsTo.push_back(kptsTo[i]);
1308 wordsDescTo.push_back(descriptorsTo.row(i));
1309 if(!kptsTo3D.empty())
1311 words3To.push_back(kptsTo3D[i]);
1318 else if(descriptorsFrom.rows)
1321 UASSERT(kptsFrom3D.empty() || int(kptsFrom3D.size()) == descriptorsFrom.rows);
1322 for(
int i=0; i<descriptorsFrom.rows; ++i)
1324 wordsFrom.insert(wordsFrom.end(), std::make_pair(i, wordsFrom.size()));
1325 wordsKptsFrom.push_back(kptsFrom[i]);
1326 wordsDescFrom.push_back(descriptorsFrom.row(i));
1327 if(!kptsFrom3D.empty())
1329 words3From.push_back(kptsFrom3D[i]);
1335 fromSignature.
setWords(wordsFrom, wordsKptsFrom, words3From, wordsDescFrom);
1336 toSignature.
setWords(wordsTo, wordsKptsTo, words3To, wordsDescTo);
1343 cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
1344 int inliersCount = 0;
1345 int matchesCount = 0;
1351 std::vector<int> inliers[2];
1352 std::vector<int> matches[2];
1353 cv::Mat covariances[2];
1354 covariances[0] = cv::Mat::eye(6,6,CV_64FC1);
1355 covariances[1] = cv::Mat::eye(6,6,CV_64FC1);
1363 signatureA = &fromSignature;
1364 signatureB = &toSignature;
1368 signatureA = &toSignature;
1369 signatureB = &fromSignature;
1378 UERROR(
"Calibrated camera required (multi-cameras not supported).");
1388 double variance = 1.0f;
1389 std::vector<int> matchesV;
1392 std::map<int, cv::KeyPoint> wordsA;
1393 std::map<int, cv::Point3f> words3A;
1394 std::map<int, cv::KeyPoint> wordsB;
1395 for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
1397 wordsA.insert(std::make_pair(iter->first, signatureA->
getWordsKpts()[iter->second]));
1400 words3A.insert(std::make_pair(iter->first, signatureA->
getWords3()[iter->second]));
1403 for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
1405 wordsB.insert(std::make_pair(iter->first, signatureB->
getWordsKpts()[iter->second]));
1417 covariances[dir] *= variance;
1418 inliers[dir] =
uKeys(inliers3D);
1419 matches[dir] = matchesV;
1421 if(!cameraTransform.
isNull())
1429 transforms[dir] = cameraTransform.
to3DoF();
1433 transforms[dir] = cameraTransform;
1438 msg =
uFormat(
"Variance is too high! (Max %s=%f, variance=%f)", Parameters::kVisEpipolarGeometryVar().c_str(),
_epipolarGeometryVar, variance);
1450 msg =
uFormat(
"No camera transform found");
1454 else if(signatureA->
getWords().size() == 0)
1456 msg =
uFormat(
"No enough features (%d)", (
int)signatureA->
getWords().size());
1461 msg =
uFormat(
"No camera model");
1472 UERROR(
"Calibrated camera required (multi-cameras not supported). Id=%d Models=%d StereoModel=%d weight=%d",
1488 std::vector<int> inliersV;
1489 std::vector<int> matchesV;
1492 std::map<int, cv::Point3f> words3A;
1493 std::map<int, cv::Point3f> words3B;
1494 std::map<int, cv::KeyPoint> wordsB;
1495 for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
1497 words3A.insert(std::make_pair(iter->first, signatureA->
getWords3()[iter->second]));
1499 for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
1501 wordsB.insert(std::make_pair(iter->first, signatureB->
getWordsKpts()[iter->second]));
1504 words3B.insert(std::make_pair(iter->first, signatureB->
getWords3()[iter->second]));
1521 inliers[dir] = inliersV;
1522 matches[dir] = matchesV;
1523 UDEBUG(
"inliers: %d/%d", (
int)inliersV.size(), (int)matchesV.size());
1524 if(transforms[dir].
isNull())
1526 msg =
uFormat(
"Not enough inliers %d/%d (matches=%d) between %d and %d",
1527 (
int)inliers[dir].size(),
_minInliers, (
int)matches[dir].size(), signatureA->
id(), signatureB->
id());
1532 transforms[dir] = transforms[dir].
to3DoF();
1537 msg =
uFormat(
"Not enough features in images (old=%d, new=%d, min=%d)",
1551 std::vector<int> inliersV;
1552 std::vector<int> matchesV;
1555 std::map<int, cv::Point3f> words3A;
1556 std::map<int, cv::Point3f> words3B;
1557 for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
1559 words3A.insert(std::make_pair(iter->first, signatureA->
getWords3()[iter->second]));
1561 for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
1563 words3B.insert(std::make_pair(iter->first, signatureB->
getWords3()[iter->second]));
1575 inliers[dir] = inliersV;
1576 matches[dir] = matchesV;
1577 UDEBUG(
"inliers: %d/%d", (
int)inliersV.size(), (int)matchesV.size());
1578 if(transforms[dir].
isNull())
1580 msg =
uFormat(
"Not enough inliers %d/%d (matches=%d) between %d and %d",
1581 (
int)inliers[dir].size(),
_minInliers, (
int)matches[dir].size(), signatureA->
id(), signatureB->
id());
1586 transforms[dir] = transforms[dir].
to3DoF();
1591 msg =
uFormat(
"Not enough 3D features in images (old=%d, new=%d, min=%d)",
1600 UDEBUG(
"from->to=%s", transforms[0].prettyPrint().c_str());
1601 UDEBUG(
"to->from=%s", transforms[1].prettyPrint().c_str());
1604 std::vector<int> allInliers = inliers[0];
1605 if(inliers[1].size())
1607 std::set<int> allInliersSet(allInliers.begin(), allInliers.end());
1608 unsigned int oi = allInliers.size();
1609 allInliers.resize(allInliers.size() + inliers[1].size());
1610 for(
unsigned int i=0; i<inliers[1].size(); ++i)
1612 if(allInliersSet.find(inliers[1][i]) == allInliersSet.end())
1614 allInliers[oi++] = inliers[1][i];
1617 allInliers.resize(oi);
1619 std::vector<int> allMatches = matches[0];
1620 if(matches[1].size())
1622 std::set<int> allMatchesSet(allMatches.begin(), allMatches.end());
1623 unsigned int oi = allMatches.size();
1624 allMatches.resize(allMatches.size() + matches[1].size());
1625 for(
unsigned int i=0; i<matches[1].size(); ++i)
1627 if(allMatchesSet.find(matches[1][i]) == allMatchesSet.end())
1629 allMatches[oi++] = matches[1][i];
1632 allMatches.resize(oi);
1637 !transforms[0].
isNull() &&
1638 allInliers.size() &&
1644 UDEBUG(
"Refine with bundle adjustment");
1647 std::map<int, Transform> poses;
1648 std::multimap<int, Link> links;
1649 std::map<int, cv::Point3f> points3DMap;
1652 poses.insert(std::make_pair(2, transforms[0]));
1654 for(
int i=0;i<2;++i)
1656 UASSERT(covariances[i].cols==6 && covariances[i].rows == 6 && covariances[i].type() == CV_64FC1);
1671 cv::Mat cov = covariances[0].clone();
1674 if(!transforms[1].
isNull() && inliers[1].size())
1676 cov = covariances[1].clone();
1680 std::map<int, Transform> optimizedPoses;
1685 std::map<int, CameraModel> models;
1694 cameraModelFrom.
fy(),
1695 cameraModelFrom.
cx(),
1696 cameraModelFrom.
cy(),
1726 if(invLocalTransformFrom.
isNull())
1728 invLocalTransformFrom = invLocalTransformTo;
1731 models.insert(std::make_pair(1, cameraModelFrom.
isValidForProjection()?cameraModelFrom:cameraModelTo));
1732 models.insert(std::make_pair(2, cameraModelTo));
1734 std::map<int, std::map<int, FeatureBA> > wordReferences;
1735 std::set<int> sbaOutliers;
1736 for(
unsigned int i=0; i<allInliers.size(); ++i)
1738 int wordId = allInliers[i];
1739 int indexFrom = fromSignature.
getWords().find(wordId)->second;
1740 const cv::Point3f & pt3D = fromSignature.
getWords3()[indexFrom];
1744 sbaOutliers.insert(wordId);
1748 points3DMap.insert(std::make_pair(wordId, pt3D));
1750 std::map<int, FeatureBA> ptMap;
1754 const cv::KeyPoint & kpt = fromSignature.
getWordsKpts()[indexFrom];
1755 ptMap.insert(std::make_pair(1,
FeatureBA(kpt, depthFrom)));
1759 int indexTo = toSignature.
getWords().find(wordId)->second;
1760 float depthTo = 0.0f;
1765 const cv::KeyPoint & kpt = toSignature.
getWordsKpts()[indexTo];
1766 ptMap.insert(std::make_pair(2,
FeatureBA(kpt, depthTo)));
1769 wordReferences.insert(std::make_pair(wordId, ptMap));
1778 optimizedPoses = sba->
optimizeBA(1, poses, links, models, points3DMap, wordReferences, &sbaOutliers);
1782 if(optimizedPoses.size() == 2 &&
1783 !optimizedPoses.begin()->second.isNull() &&
1784 !optimizedPoses.rbegin()->second.isNull())
1786 UDEBUG(
"Pose optimization: %s -> %s", transforms[0].prettyPrint().c_str(), optimizedPoses.rbegin()->second.
prettyPrint().c_str());
1788 if(sbaOutliers.size())
1790 std::vector<int> newInliers(allInliers.size());
1792 for(
unsigned int i=0; i<allInliers.size(); ++i)
1794 if(sbaOutliers.find(allInliers[i]) == sbaOutliers.end())
1796 newInliers[oi++] = allInliers[i];
1799 newInliers.resize(oi);
1800 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(allInliers.size()));
1801 allInliers = newInliers;
1805 msg =
uFormat(
"Not enough inliers after bundle adjustment %d/%d (matches=%d) between %d and %d",
1806 (
int)allInliers.size(),
_minInliers, (int)allInliers.size()+sbaOutliers.size(), fromSignature.
id(), toSignature.
id());
1811 transforms[0] = optimizedPoses.rbegin()->second;
1837 inliersCount = (int)allInliers.size();
1838 matchesCount = (int)allMatches.size();
1839 if(!transforms[1].
isNull())
1841 transforms[1] = transforms[1].
inverse();
1842 if(transforms[0].
isNull())
1844 transform = transforms[1];
1845 covariance = covariances[1];
1849 transform = transforms[0].
interpolate(0.5
f, transforms[1]);
1850 covariance = (covariances[0]+covariances[1])/2.0
f;
1855 transform = transforms[0];
1856 covariance = covariances[0];
1862 float cx=0, cy=0, w=0, h=0;
1869 cx = cameraModel.
cx();
1870 cy = cameraModel.
cy();
1876 pcaData = cv::Mat(allInliers.size(), 2, CV_32FC1);
1880 UERROR(
"Invalid calibration image size (%dx%d), cannot compute inliers distribution! (see %s=%f)", w, h, Parameters::kVisMinInliersDistribution().c_str(),
_minInliersDistributionThr);
1885 UERROR(
"Multi-camera not supported when computing inliers distribution! (see %s=%f)", Parameters::kVisMinInliersDistribution().c_str(),
_minInliersDistributionThr);
1889 UERROR(
"Calibration not valid, cannot compute inliers distribution! (see %s=%f)", Parameters::kVisMinInliersDistribution().c_str(),
_minInliersDistributionThr);
1894 std::vector<float> distances;
1897 distances.reserve(allInliers.size());
1899 for(
unsigned int i=0; i<allInliers.size(); ++i)
1903 std::multimap<int, int>::const_iterator wordsIter = fromSignature.
getWords().find(allInliers[i]);
1904 if(wordsIter != fromSignature.
getWords().end() && !fromSignature.
getWords3().empty())
1906 const cv::Point3f & pt = fromSignature.
getWords3()[wordsIter->second];
1914 if(!pcaData.empty())
1916 std::multimap<int, int>::const_iterator wordsIter = fromSignature.
getWords().find(allInliers[i]);
1918 float * ptr = pcaData.ptr<
float>(i, 0);
1919 const cv::KeyPoint & kpt = fromSignature.
getWordsKpts()[wordsIter->second];
1920 ptr[0] = (kpt.pt.x-cx) / w;
1921 ptr[1] = (kpt.pt.y-cy) / h;
1925 if(!distances.empty())
1931 msg =
uFormat(
"The mean distance of the inliers is over %s threshold (%f)",
1937 if(!transform.
isNull() && !pcaData.empty())
1939 cv::Mat pcaEigenVectors, pcaEigenValues;
1940 cv::PCA pca_analysis(pcaData, cv::Mat(), CV_PCA_DATA_AS_ROW);
1946 msg =
uFormat(
"The distribution (%f) of inliers is under %s threshold (%f)",
1955 msg =
uFormat(
"Missing correspondences for registration (%d->%d). fromWords = %d fromImageEmpty=%d toWords = %d toImageEmpty=%d",
1956 fromSignature.
id(), toSignature.
id(),
static bool isFeatureParameter(const std::string ¶m)
float _minInliersDistributionThr
float _maxInliersMeanDistance
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
int _correspondencesApproach
ParametersMap _bundleParameters
std::map< K, V > uMultimapToMapUnique(const std::multimap< K, V > &m)
Transform RTABMAP_EXP estimateMotion3DTo2D(const std::map< int, cv::Point3f > &words3A, const std::map< int, cv::KeyPoint > &words2B, const CameraModel &cameraModel, int minInliers=10, int iterations=100, double reprojError=5., int flagsPnP=0, int pnpRefineIterations=1, const Transform &guess=Transform::getIdentity(), const std::map< int, cv::Point3f > &words3B=std::map< int, cv::Point3f >(), cv::Mat *covariance=0, std::vector< int > *matchesOut=0, std::vector< int > *inliersOut=0)
virtual Feature2D::Type getType() const =0
T uMean(const T *v, unsigned int size)
const cv::Size & imageSize() const
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
std::vector< cv::Point3f > generateKeypoints3D(const SensorData &data, const std::vector< cv::KeyPoint > &keypoints) const
std::vector< K > uKeys(const std::multimap< K, V > &mm)
bool _guessMatchToProjection
std::map< int, cv::Point3f > RTABMAP_EXP generateWords3DMono(const std::map< int, cv::KeyPoint > &kpts, const std::map< int, cv::KeyPoint > &previousKpts, const CameraModel &cameraModel, Transform &cameraTransform, float ransacReprojThreshold=3.0f, float ransacConfidence=0.99f, const std::map< int, cv::Point3f > &refGuess3D=std::map< int, cv::Point3f >(), double *variance=0, std::vector< int > *matchesOut=0)
bool uIsInBounds(const T &value, const T &low, const T &high)
cv::Mat generateDescriptors(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, CameraModel > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, FeatureBA > > &wordReferences, std::set< int > *outliers=0)
virtual ~RegistrationVis()
bool _forwardEstimateOnly
static double COVARIANCE_EPSILON
float getMinDepth() const
std::pair< std::string, std::string > ParametersPair
float _epipolarGeometryVar
float inliersMeanDistance
GLM_FUNC_DECL genType e()
const cv::Mat & descriptors() const
virtual std::list< int > addNewWords(const cv::Mat &descriptors, int signatureId)
std::map< std::string, std::string > ParametersMap
GLM_FUNC_DECL genType::value_type distance(genType const &p0, genType const &p1)
const std::vector< cv::KeyPoint > & keypoints() const
Basic mathematics functions.
std::vector< int > inliersIDs
Some conversion functions.
const cv::Mat & imageRaw() const
std::vector< cv::KeyPoint > generateKeypoints(const cv::Mat &image, const cv::Mat &mask=cv::Mat())
float getMaxDepth() const
const std::vector< cv::KeyPoint > & getWordsKpts() const
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
GLM_FUNC_DECL bool isNull(detail::tmat2x2< T, P > const &m, T const &epsilon)
cv::Mat RTABMAP_EXP interpolate(const cv::Mat &image, int factor, float depthErrorRatio=0.02f)
bool uIsFinite(const T &value)
#define UASSERT(condition)
Wrappers of STL for convenient functions.
Feature2D * _detectorFrom
bool isValidForProjection() const
const CameraModel & left() const
const std::multimap< int, int > & getWords() const
static Feature2D * create(const ParametersMap ¶meters=ParametersMap())
#define UASSERT_MSG(condition, msg_str)
std::vector< int > projectedIDs
virtual void parseParameters(const ParametersMap ¶meters)
static void filterKeypointsByDepth(std::vector< cv::KeyPoint > &keypoints, const cv::Mat &depth, float minDepth, float maxDepth)
void clear(bool printWarningsIfNotEmpty=true)
const cv::Mat & getWordsDescriptors() const
Transform RTABMAP_EXP estimateMotion3DTo3D(const std::map< int, cv::Point3f > &words3A, const std::map< int, cv::Point3f > &words3B, int minInliers=10, double inliersDistance=0.1, int iterations=100, int refineIterations=5, cv::Mat *covariance=0, std::vector< int > *matchesOut=0, std::vector< int > *inliersOut=0)
double _gmsThresholdFactor
virtual Transform computeTransformationImpl(Signature &from, Signature &to, Transform guess, RegistrationInfo &info) const
float inliersDistribution
bool uContains(const std::list< V > &list, const V &value)
bool isValidForProjection() const
static const ParametersMap & getDefaultParameters()
const std::vector< CameraModel > & cameraModels() const
const std::vector< cv::Point3f > & getWords3() const
SensorData & sensorData()
void setWords(const std::multimap< int, int > &words, const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &words3, const cv::Mat &descriptors)
virtual void parseParameters(const ParametersMap ¶meters)
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
ParametersMap _featureParameters
std::vector< int > matchesIDs
virtual void addWord(VisualWord *vw)
const Transform & localTransform() const
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
static Optimizer * create(const ParametersMap ¶meters)
void setFeatures(const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &keypoints3D, const cv::Mat &descriptors)
RegistrationVis(const ParametersMap ¶meters=ParametersMap(), Registration *child=0)
const std::vector< cv::Point3f > & keypoints3D() const
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
const Transform & localTransform() const
GLM_FUNC_DECL matType< T, P > inverse(matType< T, P > const &m)