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> 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 _PnPMaxVar(
Parameters::defaultVisPnPMaxVariance()),
73 _correspondencesApproach(
Parameters::defaultVisCorType()),
74 _flowWinSize(
Parameters::defaultVisCorFlowWinSize()),
75 _flowIterations(
Parameters::defaultVisCorFlowIterations()),
77 _flowMaxLevel(
Parameters::defaultVisCorFlowMaxLevel()),
80 _gmsWithRotation(
Parameters::defaultGMSWithRotation()),
81 _gmsWithScale(
Parameters::defaultGMSWithScale()),
82 _gmsThresholdFactor(
Parameters::defaultGMSThresholdFactor()),
83 _guessWinSize(
Parameters::defaultVisCorGuessWinSize()),
84 _guessMatchToProjection(
Parameters::defaultVisCorGuessMatchToProjection()),
85 _bundleAdjustment(
Parameters::defaultVisBundleAdjustment()),
86 _depthAsMask(
Parameters::defaultVisDepthAsMask()),
87 _minInliersDistributionThr(
Parameters::defaultVisMinInliersDistribution()),
88 _maxInliersMeanDistance(
Parameters::defaultVisMeanInliersDistance()),
149 UWARN(
"%s should be >= 6 but it is set to %d, setting to 6.", Parameters::kVisMinInliers().c_str(),
_minInliers);
158 #ifndef RTABMAP_PYTHON 159 UWARN(
"%s is set to 6 but RTAB-Map is not built with Python3 support, using default %d.",
160 Parameters::kVisCorNNType().c_str(), Parameters::defaultVisCorNNType());
161 _nnType = Parameters::defaultVisCorNNType();
163 int iterations = _pyMatcher?_pyMatcher->iterations():Parameters::defaultPyMatcherIterations();
164 float matchThr = _pyMatcher?_pyMatcher->matchThreshold():Parameters::defaultPyMatcherThreshold();
165 std::string path = _pyMatcher?_pyMatcher->path():Parameters::defaultPyMatcherPath();
166 bool cuda = _pyMatcher?_pyMatcher->cuda():Parameters::defaultPyMatcherCuda();
167 std::string
model = _pyMatcher?_pyMatcher->model():Parameters::defaultPyMatcherModel();
175 UERROR(
"%s parameter should be set to use Python3 matching (%s=6), using default %d.",
176 Parameters::kPyMatcherPath().c_str(),
177 Parameters::kVisCorNNType().c_str(),
178 Parameters::defaultVisCorNNType());
179 _nnType = Parameters::defaultVisCorNNType();
184 _pyMatcher =
new PyMatcher(path, matchThr, iterations, cuda, model);
188 #if !defined(HAVE_OPENCV_XFEATURES2D) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION<4 || CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<1)) 191 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.",
192 Parameters::kVisCorNNType().c_str(), Parameters::defaultVisCorNNType());
193 _nnType = Parameters::defaultVisCorNNType();
198 for(ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
200 std::string group =
uSplit(iter->first,
'/').front();
207 if(
uContains(parameters, Parameters::kVisCorNNType()))
214 if(
uContains(parameters, Parameters::kVisCorNNDR()))
218 if(
uContains(parameters, Parameters::kKpByteToFloat()))
222 if(
uContains(parameters, Parameters::kVisFeatureType()))
226 if(
uContains(parameters, Parameters::kVisMaxFeatures()))
230 if(
uContains(parameters, Parameters::kVisMaxDepth()))
234 if(
uContains(parameters, Parameters::kVisMinDepth()))
238 if(
uContains(parameters, Parameters::kVisRoiRatios()))
242 if(
uContains(parameters, Parameters::kVisSubPixEps()))
246 if(
uContains(parameters, Parameters::kVisSubPixIterations()))
250 if(
uContains(parameters, Parameters::kVisSubPixWinSize()))
254 if(
uContains(parameters, Parameters::kVisGridRows()))
258 if(
uContains(parameters, Parameters::kVisGridCols()))
273 #ifdef RTABMAP_PYTHON 298 UDEBUG(
"%s=%f", Parameters::kVisCorNNDR().c_str(),
_nndr);
299 UDEBUG(
"%s=%d", Parameters::kVisCorNNType().c_str(),
_nnType);
305 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",
307 (int)fromSignature.
getWords().size(),
318 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",
345 UDEBUG(
"Bypassing feature matching as descriptors and images are empty. We assume features are already matched.");
372 std::vector<cv::KeyPoint> kptsFrom;
376 std::vector<int> orignalWordsFromIds;
377 int kptsFromSource = 0;
378 if(fromSignature.
getWords().empty())
382 if(!imageFrom.empty())
384 if(imageFrom.channels() > 1)
387 cv::cvtColor(imageFrom, tmp, cv::COLOR_BGR2GRAY);
402 UWARN(
"%s is true, but RGB size (%dx%d) modulo depth size (%dx%d) is not 0. Ignoring depth mask for feature detection.",
403 Parameters::kVisDepthAsMask().c_str(),
423 orignalWordsFromIds.resize(fromSignature.
getWords().size());
425 bool allUniques =
true;
426 int previousIdAdded = 0;
428 for(std::multimap<int, int>::const_iterator iter=fromSignature.
getWords().begin(); iter!=fromSignature.
getWords().end(); ++iter)
430 UASSERT(iter->second>=0 && iter->second<(
int)orignalWordsFromIds.size());
431 orignalWordsFromIds[iter->second] = iter->first;
432 if(i>0 && iter->first==previousIdAdded)
436 previousIdAdded = iter->first;
441 UDEBUG(
"IDs are not unique, IDs will be regenerated!");
442 orignalWordsFromIds.clear();
446 std::multimap<int, int> wordsFrom;
447 std::multimap<int, int> wordsTo;
448 std::vector<cv::KeyPoint> wordsKptsFrom;
449 std::vector<cv::KeyPoint> wordsKptsTo;
450 std::vector<cv::Point3f> words3From;
451 std::vector<cv::Point3f> words3To;
452 cv::Mat wordsDescFrom;
458 if(imageFrom.channels() > 1)
461 cv::cvtColor(imageFrom, tmp, cv::COLOR_BGR2GRAY);
464 if(imageTo.channels() > 1)
467 cv::cvtColor(imageTo, tmp, cv::COLOR_BGR2GRAY);
471 std::vector<cv::Point3f> kptsFrom3D;
472 if(kptsFrom.size() == fromSignature.
getWords3().size())
485 if(!imageFrom.empty() && !imageTo.empty())
487 std::vector<cv::Point2f> cornersFrom;
488 cv::KeyPoint::convert(kptsFrom, cornersFrom);
489 std::vector<cv::Point2f> cornersTo;
497 cv::Mat R = (cv::Mat_<double>(3,3) <<
498 (
double)guessCameraRef.
r11(), (double)guessCameraRef.
r12(), (double)guessCameraRef.
r13(),
499 (double)guessCameraRef.
r21(), (double)guessCameraRef.
r22(), (double)guessCameraRef.
r23(),
500 (double)guessCameraRef.
r31(), (double)guessCameraRef.
r32(), (double)guessCameraRef.
r33());
501 cv::Mat rvec(1,3, CV_64FC1);
502 cv::Rodrigues(R, rvec);
503 cv::Mat tvec = (cv::Mat_<double>(1,3) << (
double)guessCameraRef.
x(), (double)guessCameraRef.
y(), (double)guessCameraRef.
z());
505 cv::projectPoints(kptsFrom3D, rvec, tvec, K, cv::Mat(), cornersTo);
509 UERROR(
"Optical flow guess with multi-cameras is not implemented, guess ignored...");
514 UDEBUG(
"guessSet = %d", guessSet?1:0);
515 std::vector<unsigned char> status;
516 std::vector<float> err;
517 UDEBUG(
"cv::calcOpticalFlowPyrLK() begin");
518 cv::calcOpticalFlowPyrLK(
528 cv::OPTFLOW_LK_GET_MIN_EIGENVALS | (guessSet?cv::OPTFLOW_USE_INITIAL_FLOW:0), 1
e-4);
529 UDEBUG(
"cv::calcOpticalFlowPyrLK() end");
531 UASSERT(kptsFrom.size() == kptsFrom3D.size());
532 std::vector<cv::KeyPoint> kptsTo(kptsFrom.size());
533 std::vector<cv::Point3f> kptsFrom3DKept(kptsFrom3D.size());
534 std::vector<int> orignalWordsFromIdsCpy = orignalWordsFromIds;
536 for(
unsigned int i=0; i<status.size(); ++i)
542 if(orignalWordsFromIdsCpy.size())
544 orignalWordsFromIds[ki] = orignalWordsFromIdsCpy[i];
546 kptsFrom[ki] = cv::KeyPoint(cornersFrom[i], 1);
547 kptsFrom3DKept[ki] = kptsFrom3D[i];
548 kptsTo[ki++] = cv::KeyPoint(cornersTo[i], 1);
551 if(orignalWordsFromIds.size())
553 orignalWordsFromIds.resize(ki);
557 kptsFrom3DKept.resize(ki);
558 kptsFrom3D = kptsFrom3DKept;
560 std::vector<cv::Point3f> kptsTo3D;
566 UASSERT(kptsFrom.size() == kptsFrom3DKept.size());
567 UASSERT(kptsFrom.size() == kptsTo.size());
568 UASSERT(kptsTo3D.size() == 0 || kptsTo.size() == kptsTo3D.size());
569 for(
unsigned int i=0; i< kptsFrom3DKept.size(); ++i)
571 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
572 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
573 wordsKptsFrom.push_back(kptsFrom[i]);
574 words3From.push_back(kptsFrom3DKept[i]);
576 wordsTo.insert(wordsTo.end(), std::make_pair(
id, wordsTo.size()));
577 wordsKptsTo.push_back(kptsTo[i]);
578 if(!kptsTo3D.empty())
580 words3To.push_back(kptsTo3D[i]);
587 if(imageFrom.empty())
589 UERROR(
"Optical flow correspondences requires images in data!");
591 UASSERT(kptsFrom.size() == kptsFrom3D.size());
592 for(
unsigned int i=0; i< kptsFrom3D.size(); ++i)
596 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
597 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
598 wordsKptsFrom.push_back(kptsFrom[i]);
599 words3From.push_back(kptsFrom3D[i]);
602 toSignature.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
610 std::vector<cv::KeyPoint> kptsTo;
611 int kptsToSource = 0;
617 if(imageTo.channels() > 1)
620 cv::cvtColor(imageTo, tmp, cv::COLOR_BGR2GRAY);
635 UWARN(
"%s is true, but RGB size (%dx%d) modulo depth size (%dx%d) is not 0. Ignoring depth mask for feature detection.",
636 Parameters::kVisDepthAsMask().c_str(),
659 UDEBUG(
"kptsFrom=%d kptsFromSource=%d", (
int)kptsFrom.size(), kptsFromSource);
660 UDEBUG(
"kptsTo=%d kptsToSource=%d", (
int)kptsTo.size(), kptsToSource);
661 cv::Mat descriptorsFrom;
662 if(kptsFromSource == 2 &&
669 else if(kptsFromSource == 1 &&
674 else if(!imageFrom.empty())
676 if(imageFrom.channels() > 1)
679 cv::cvtColor(imageFrom, tmp, cv::COLOR_BGR2GRAY);
682 UDEBUG(
"cleared orignalWordsFromIds");
683 orignalWordsFromIds.clear();
687 cv::Mat descriptorsTo;
690 if(kptsToSource == 2 &&
695 else if(kptsToSource == 1 &&
700 else if(!imageTo.empty())
702 if(imageTo.channels() > 1)
705 cv::cvtColor(imageTo, tmp, cv::COLOR_BGR2GRAY);
714 std::vector<cv::Point3f> kptsFrom3D;
715 std::vector<cv::Point3f> kptsTo3D;
716 if(kptsFromSource == 2 &&
717 kptsFrom.size() == fromSignature.
getWords3().size())
721 else if(kptsFromSource == 1 &&
728 if(fromSignature.
getWords3().size() && kptsFrom.size() != fromSignature.
getWords3().size())
730 UWARN(
"kptsFrom (%d) is not the same size as fromSignature.getWords3() (%d), there " 731 "is maybe a problem with the logic above (getWords3() should be null or equal to kptsfrom). Regenerating kptsFrom3D...",
737 UWARN(
"kptsFrom (%d) is not the same size as fromSignature.sensorData().keypoints3D() (%d), there " 738 "is maybe a problem with the logic above (keypoints3D should be null or equal to kptsfrom). Regenerating kptsFrom3D...",
743 UDEBUG(
"generated kptsFrom3D=%d", (
int)kptsFrom3D.size());
746 if(!kptsFrom3D.empty() &&
753 if(kptsToSource == 2 && kptsTo.size() == toSignature.
getWords3().size())
757 else if(kptsToSource == 1 &&
766 UWARN(
"kptsTo (%d) is not the same size as toSignature.getWords3() (%d), there " 767 "is maybe a problem with the logic above (getWords3() should be null or equal to kptsTo). Regenerating kptsTo3D...",
773 UWARN(
"kptsTo (%d) is not the same size as toSignature.sensorData().keypoints3D() (%d), there " 774 "is maybe a problem with the logic above (keypoints3D() should be null or equal to kptsTo). Regenerating kptsTo3D...",
781 if(kptsTo3D.size() &&
788 UASSERT(kptsFrom.empty() || descriptorsFrom.rows == 0 || int(kptsFrom.size()) == descriptorsFrom.rows);
793 UDEBUG(
"descriptorsFrom=%d", descriptorsFrom.rows);
794 UDEBUG(
"descriptorsTo=%d", descriptorsTo.rows);
795 UDEBUG(
"orignalWordsFromIds=%d", (
int)orignalWordsFromIds.size());
798 if(descriptorsFrom.rows > 0 && descriptorsTo.rows > 0)
800 std::vector<CameraModel> models;
813 bool isCalibrated = !models.empty();
814 for(
size_t i=0; i<models.size() && isCalibrated; ++i)
816 isCalibrated = models[i].isValidForProjection();
819 if(isCalibrated && (models[i].imageWidth()==0 || models[i].imageHeight()==0))
827 isCalibrated =
false;
840 UASSERT((
int)kptsTo.size() == descriptorsTo.rows);
841 UASSERT((
int)kptsFrom3D.size() == descriptorsFrom.rows);
843 std::vector<cv::Point2f> cornersProjected;
844 std::vector<int> projectedIndexToDescIndex;
845 float subImageWidth = models[0].imageWidth();
848 for(
size_t m=0; m<models.size(); ++m)
851 cv::Mat R = (cv::Mat_<double>(3,3) <<
852 (
double)guessCameraRef.
r11(), (double)guessCameraRef.
r12(), (double)guessCameraRef.
r13(),
853 (double)guessCameraRef.
r21(), (double)guessCameraRef.
r22(), (double)guessCameraRef.
r23(),
854 (double)guessCameraRef.
r31(), (double)guessCameraRef.
r32(), (double)guessCameraRef.
r33());
855 cv::Mat rvec(1,3, CV_64FC1);
856 cv::Rodrigues(R, rvec);
857 cv::Mat tvec = (cv::Mat_<double>(1,3) << (
double)guessCameraRef.
x(), (double)guessCameraRef.
y(), (double)guessCameraRef.
z());
858 cv::Mat K = models[m].K();
859 std::vector<cv::Point2f> projected;
860 cv::projectPoints(kptsFrom3D, rvec, tvec, K, cv::Mat(), projected);
861 UDEBUG(
"Projected points=%d", (
int)projected.size());
864 UASSERT((
int)projected.size() == descriptorsFrom.rows);
865 int cornersInFrame = 0;
866 for(
unsigned int i=0; i<projected.size(); ++i)
868 if(
uIsInBounds(projected[i].
x, 0.0
f,
float(models[m].imageWidth()-1)) &&
869 uIsInBounds(projected[i].y, 0.0
f,
float(models[m].imageHeight()-1)) &&
872 if(added.find(i) != added.end())
878 projectedIndexToDescIndex.push_back(i);
879 projected[i].x += subImageWidth*float(m);
880 cornersProjected.push_back(projected[i]);
885 UDEBUG(
"corners in frame=%d (camera index=%ld)", cornersInFrame, m);
891 UDEBUG(
"guessMatchToProjection=%d, cornersProjected=%d orignalWordsFromIds=%d (added=%ld, duplicates=%d)",
893 added.size(), duplicates);
894 if(cornersProjected.size())
898 UDEBUG(
"match frame to projected");
904 std::vector< std::vector<size_t> > indices;
905 std::vector<std::vector<float> > dists;
907 std::vector<cv::Point2f> pointsTo;
908 cv::KeyPoint::convert(kptsTo, pointsTo);
912 UASSERT(indices.size() == pointsToMat.rows);
913 UASSERT(descriptorsFrom.cols == descriptorsTo.cols);
914 UASSERT(descriptorsFrom.rows == (
int)kptsFrom.size());
915 UASSERT((
int)pointsToMat.rows == descriptorsTo.rows);
916 UASSERT(pointsToMat.rows == kptsTo.size());
917 UDEBUG(
"radius search done for guess");
920 int newToId = !orignalWordsFromIds.empty()?fromSignature.
getWords().rbegin()->first+1:descriptorsFrom.rows;
921 std::map<int,int> addedWordsFrom;
922 std::map<int, int> duplicates;
924 cv::Mat descriptors(10, descriptorsTo.cols, descriptorsTo.type());
925 for(
unsigned int i = 0; i < pointsToMat.rows; ++i)
927 int matchedIndex = -1;
928 if(indices[i].size() >= 2)
930 std::vector<int> descriptorsIndices(indices[i].size());
932 if((
int)indices[i].size() > descriptors.rows)
934 descriptors.resize(indices[i].size());
936 for(
unsigned int j=0; j<indices[i].size(); ++j)
938 descriptorsFrom.row(projectedIndexToDescIndex[indices[i].at(j)]).copyTo(descriptors.row(oi));
939 descriptorsIndices[oi++] = indices[i].at(j);
941 descriptorsIndices.resize(oi);
944 cv::BFMatcher
matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR,
_nnType == 5);
947 std::vector<cv::DMatch>
matches;
948 matcher.match(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches);
951 matchedIndex = descriptorsIndices.at(matches.at(0).trainIdx);
956 std::vector<std::vector<cv::DMatch> >
matches;
957 matcher.knnMatch(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
959 UASSERT(matches[0].size() == 2);
962 matchedIndex = descriptorsIndices.at(matches[0].at(0).trainIdx);
966 else if(indices[i].size() == 1)
968 matchedIndex = indices[i].at(0);
971 if(matchedIndex >= 0)
973 matchedIndex = projectedIndexToDescIndex[matchedIndex];
974 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndex]:matchedIndex;
976 if(addedWordsFrom.find(matchedIndex) != addedWordsFrom.end())
978 id = addedWordsFrom.at(matchedIndex);
979 duplicates.insert(std::make_pair(matchedIndex,
id));
983 addedWordsFrom.insert(std::make_pair(matchedIndex,
id));
985 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
986 if(!kptsFrom.empty())
988 wordsKptsFrom.push_back(kptsFrom[matchedIndex]);
990 words3From.push_back(kptsFrom3D[matchedIndex]);
991 wordsDescFrom.push_back(descriptorsFrom.row(matchedIndex));
994 wordsTo.insert(wordsTo.end(), std::make_pair(
id, wordsTo.size()));
995 wordsKptsTo.push_back(kptsTo[i]);
996 wordsDescTo.push_back(descriptorsTo.row(i));
997 if(!kptsTo3D.empty())
999 words3To.push_back(kptsTo3D[i]);
1005 wordsTo.insert(wordsTo.end(), std::make_pair(newToId, wordsTo.size()));
1006 wordsKptsTo.push_back(kptsTo[i]);
1007 wordsDescTo.push_back(descriptorsTo.row(i));
1008 if(!kptsTo3D.empty())
1010 words3To.push_back(kptsTo3D[i]);
1017 UDEBUG(
"addedWordsFrom=%d/%d (duplicates=%d, newWords=%d), kptsTo=%d, wordsTo=%d, words3From=%d",
1018 (
int)addedWordsFrom.size(), (int)cornersProjected.size(), (int)duplicates.size(), newWords,
1019 (int)kptsTo.size(), (int)wordsTo.size(), (int)words3From.size());
1022 int addWordsFromNotMatched = 0;
1023 for(
unsigned int i=0; i<kptsFrom3D.size(); ++i)
1025 if(
util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end())
1027 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
1028 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
1029 wordsKptsFrom.push_back(kptsFrom[i]);
1030 wordsDescFrom.push_back(descriptorsFrom.row(i));
1031 words3From.push_back(kptsFrom3D[i]);
1033 ++addWordsFromNotMatched;
1036 UDEBUG(
"addWordsFromNotMatched=%d -> words3From=%d", addWordsFromNotMatched, (
int)words3From.size());
1040 UDEBUG(
"match projected to frame");
1041 std::vector<cv::Point2f> pointsTo;
1042 cv::KeyPoint::convert(kptsTo, pointsTo);
1047 std::vector< std::vector<size_t> > indices;
1048 std::vector<std::vector<float> > dists;
1053 UASSERT(indices.size() == cornersProjectedMat.rows);
1054 UASSERT(descriptorsFrom.cols == descriptorsTo.cols);
1055 UASSERT(descriptorsFrom.rows == (
int)kptsFrom.size());
1056 UASSERT((
int)pointsToMat.rows == descriptorsTo.rows);
1057 UASSERT(pointsToMat.rows == kptsTo.size());
1058 UDEBUG(
"radius search done for guess");
1061 std::set<int> addedWordsTo;
1062 std::set<int> addedWordsFrom;
1063 double bruteForceTotalTime = 0.0;
1064 double bruteForceDescCopy = 0.0;
1066 cv::Mat descriptors(10, descriptorsTo.cols, descriptorsTo.type());
1067 for(
unsigned int i = 0; i < cornersProjectedMat.rows; ++i)
1069 int matchedIndexFrom = projectedIndexToDescIndex[i];
1071 if(indices[i].size())
1073 info.
projectedIDs.push_back(!orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom);
1078 int matchedIndexTo = -1;
1079 if(indices[i].size() >= 2)
1082 std::vector<int> descriptorsIndices(indices[i].size());
1084 if((
int)indices[i].size() > descriptors.rows)
1086 descriptors.resize(indices[i].size());
1088 for(
unsigned int j=0; j<indices[i].size(); ++j)
1090 descriptorsTo.row(indices[i].at(j)).copyTo(descriptors.row(oi));
1091 descriptorsIndices[oi++] = indices[i].at(j);
1093 bruteForceDescCopy += bruteForceTimer.
ticks();
1096 cv::BFMatcher
matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR,
_nnType==5);
1099 std::vector<cv::DMatch>
matches;
1100 matcher.match(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches);
1101 if(!matches.empty())
1103 matchedIndexTo = descriptorsIndices.at(matches.at(0).trainIdx);
1108 std::vector<std::vector<cv::DMatch> >
matches;
1109 matcher.knnMatch(descriptorsFrom.row(matchedIndexFrom), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
1111 UASSERT(matches[0].size() == 2);
1112 bruteForceTotalTime+=bruteForceTimer.
elapsed();
1115 matchedIndexTo = descriptorsIndices.at(matches[0].at(0).trainIdx);
1119 else if(indices[i].size() == 1)
1121 matchedIndexTo = indices[i].at(0);
1124 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom;
1125 addedWordsFrom.insert(addedWordsFrom.end(), matchedIndexFrom);
1127 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
1128 if(!kptsFrom.empty())
1130 wordsKptsFrom.push_back(kptsFrom[matchedIndexFrom]);
1132 words3From.push_back(kptsFrom3D[matchedIndexFrom]);
1133 wordsDescFrom.push_back(descriptorsFrom.row(matchedIndexFrom));
1135 if( matchedIndexTo >= 0 &&
1136 addedWordsTo.find(matchedIndexTo) == addedWordsTo.end())
1138 addedWordsTo.insert(matchedIndexTo);
1140 wordsTo.insert(wordsTo.end(), std::make_pair(
id, wordsTo.size()));
1141 wordsKptsTo.push_back(kptsTo[matchedIndexTo]);
1142 wordsDescTo.push_back(descriptorsTo.row(matchedIndexTo));
1143 if(!kptsTo3D.empty())
1145 words3To.push_back(kptsTo3D[matchedIndexTo]);
1150 UDEBUG(
"bruteForceDescCopy=%fs, bruteForceTotalTime=%fs", bruteForceDescCopy, bruteForceTotalTime);
1153 for(
unsigned int i=0; i<kptsFrom3D.size(); ++i)
1155 if(
util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end())
1157 int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
1158 wordsFrom.insert(wordsFrom.end(), std::make_pair(
id, wordsFrom.size()));
1159 wordsKptsFrom.push_back(kptsFrom[i]);
1160 wordsDescFrom.push_back(descriptorsFrom.row(i));
1161 words3From.push_back(kptsFrom3D[i]);
1165 int newToId = !orignalWordsFromIds.empty()?fromSignature.
getWords().rbegin()->first+1:descriptorsFrom.rows;
1166 for(
unsigned int i = 0; i < kptsTo.size(); ++i)
1168 if(addedWordsTo.find(i) == addedWordsTo.end())
1170 wordsTo.insert(wordsTo.end(), std::make_pair(newToId, wordsTo.size()));
1171 wordsKptsTo.push_back(kptsTo[i]);
1172 wordsDescTo.push_back(descriptorsTo.row(i));
1173 if(!kptsTo3D.empty())
1175 words3To.push_back(kptsTo3D[i]);
1184 UWARN(
"All projected points are outside the camera. Guess (%s) is wrong or images are not overlapping.", guess.
prettyPrint().c_str());
1190 if(guessSet &&
_guessWinSize > 0 && kptsFrom3D.size() && !isCalibrated)
1192 UWARN(
"Calibration not found! Finding correspondences " 1193 "with the guess cannot be done, global matching is " 1199 std::list<int> fromWordIds;
1200 std::list<int> toWordIds;
1201 #ifdef RTABMAP_PYTHON 1207 std::vector<int> fromWordIdsV(descriptorsFrom.rows);
1208 for (
int i = 0; i < descriptorsFrom.rows; ++i)
1211 if(!orignalWordsFromIds.empty())
1213 id = orignalWordsFromIds[i];
1215 fromWordIds.push_back(
id);
1216 fromWordIdsV[i] = id;
1218 if(descriptorsTo.rows)
1220 std::vector<int> toWordIdsV(descriptorsTo.rows, 0);
1221 std::vector<cv::DMatch>
matches;
1222 #ifdef RTABMAP_PYTHON 1223 if(
_nnType == 6 && _pyMatcher &&
1224 descriptorsTo.cols == descriptorsFrom.cols &&
1225 descriptorsTo.rows == (
int)kptsTo.size() &&
1226 descriptorsTo.type() == CV_32F &&
1227 descriptorsFrom.type() == CV_32F &&
1228 descriptorsFrom.rows == (int)kptsFrom.size() &&
1231 UDEBUG(
"Python matching");
1232 matches = _pyMatcher->match(descriptorsTo, descriptorsFrom, kptsTo, kptsFrom, models[0].imageSize());
1236 if(
_nnType == 6 && _pyMatcher)
1238 UDEBUG(
"Invalid inputs for Python matching (desc type=%d, only float descriptors supported, multicam not supported), doing bruteforce matching instead.", descriptorsFrom.type());
1243 bool doCrossCheck =
true;
1244 #ifdef HAVE_OPENCV_XFEATURES2D 1245 #if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1) 1246 cv::Size imageSizeFrom;
1249 imageSizeFrom = imageFrom.size();
1254 if(!models.empty() && models[0].imageSize().height > 0 && models[0].imageSize().width > 0 &&
1255 imageSizeFrom.height > 0 && imageSizeFrom.width > 0)
1257 doCrossCheck =
false;
1261 UDEBUG(
"Invalid inputs for GMS matching, image size should be set for both inputs, doing bruteforce matching instead.");
1267 UDEBUG(
"BruteForce matching%s",
_nnType!=7?
" with crosscheck":
" with GMS");
1268 cv::BFMatcher
matcher(descriptorsFrom.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR, doCrossCheck);
1269 matcher.match(descriptorsTo, descriptorsFrom, matches);
1271 #if defined(HAVE_OPENCV_XFEATURES2D) && (CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION==3 && CV_MINOR_VERSION >=4 && CV_SUBMINOR_VERSION >= 1)) 1275 std::vector<cv::DMatch> matchesGMS;
1277 matches = matchesGMS;
1281 for(
size_t i=0; i<matches.size(); ++i)
1283 toWordIdsV[matches[i].queryIdx] = fromWordIdsV[matches[i].trainIdx];
1285 for(
size_t i=0; i<toWordIdsV.size(); ++i)
1287 int toId = toWordIdsV[i];
1290 toId = fromWordIds.back()+i+1;
1292 toWordIds.push_back(toId);
1298 UDEBUG(
"VWDictionary knn matching");
1300 if(orignalWordsFromIds.empty())
1302 fromWordIds = dictionary.
addNewWords(descriptorsFrom, 1);
1306 for (
int i = 0; i < descriptorsFrom.rows; ++i)
1308 int id = orignalWordsFromIds[i];
1310 fromWordIds.push_back(
id);
1314 if(descriptorsTo.rows)
1317 toWordIds = dictionary.
addNewWords(descriptorsTo, 2);
1319 dictionary.
clear(
false);
1322 std::multiset<int> fromWordIdsSet(fromWordIds.begin(), fromWordIds.end());
1323 std::multiset<int> toWordIdsSet(toWordIds.begin(), toWordIds.end());
1325 UASSERT(kptsFrom3D.empty() || fromWordIds.size() == kptsFrom3D.size());
1326 UASSERT(
int(fromWordIds.size()) == descriptorsFrom.rows);
1328 for(std::list<int>::iterator iter=fromWordIds.begin(); iter!=fromWordIds.end(); ++iter)
1330 if(fromWordIdsSet.count(*iter) == 1)
1332 wordsFrom.insert(wordsFrom.end(), std::make_pair(*iter, wordsFrom.size()));
1333 if (!kptsFrom.empty())
1335 wordsKptsFrom.push_back(kptsFrom[i]);
1337 if(!kptsFrom3D.empty())
1339 words3From.push_back(kptsFrom3D[i]);
1341 wordsDescFrom.push_back(descriptorsFrom.row(i));
1345 UASSERT(kptsTo3D.size() == 0 || kptsTo3D.size() == kptsTo.size());
1346 UASSERT(toWordIds.size() == kptsTo.size());
1347 UASSERT(
int(toWordIds.size()) == descriptorsTo.rows);
1349 for(std::list<int>::iterator iter=toWordIds.begin(); iter!=toWordIds.end(); ++iter)
1351 if(toWordIdsSet.count(*iter) == 1)
1353 wordsTo.insert(wordsTo.end(), std::make_pair(*iter, wordsTo.size()));
1354 wordsKptsTo.push_back(kptsTo[i]);
1355 wordsDescTo.push_back(descriptorsTo.row(i));
1356 if(!kptsTo3D.empty())
1358 words3To.push_back(kptsTo3D[i]);
1365 else if(descriptorsFrom.rows)
1368 UASSERT(kptsFrom3D.empty() || int(kptsFrom3D.size()) == descriptorsFrom.rows);
1369 for(
int i=0; i<descriptorsFrom.rows; ++i)
1371 wordsFrom.insert(wordsFrom.end(), std::make_pair(i, wordsFrom.size()));
1372 wordsKptsFrom.push_back(kptsFrom[i]);
1373 wordsDescFrom.push_back(descriptorsFrom.row(i));
1374 if(!kptsFrom3D.empty())
1376 words3From.push_back(kptsFrom3D[i]);
1382 fromSignature.
setWords(wordsFrom, wordsKptsFrom, words3From, wordsDescFrom);
1383 toSignature.
setWords(wordsTo, wordsKptsTo, words3To, wordsDescTo);
1390 cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
1391 int inliersCount = 0;
1392 int matchesCount = 0;
1398 std::vector<int> inliers[2];
1400 cv::Mat covariances[2];
1401 covariances[0] = cv::Mat::eye(6,6,CV_64FC1);
1402 covariances[1] = cv::Mat::eye(6,6,CV_64FC1);
1410 signatureA = &fromSignature;
1411 signatureB = &toSignature;
1415 signatureA = &toSignature;
1416 signatureB = &fromSignature;
1426 UERROR(
"Calibrated camera required (multi-cameras not supported).");
1436 double variance = 1.0f;
1437 std::vector<int> matchesV;
1440 std::map<int, cv::KeyPoint> wordsA;
1441 std::map<int, cv::Point3f> words3A;
1442 std::map<int, cv::KeyPoint> wordsB;
1443 for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
1445 wordsA.insert(std::make_pair(iter->first, signatureA->
getWordsKpts()[iter->second]));
1448 words3A.insert(std::make_pair(iter->first, signatureA->
getWords3()[iter->second]));
1451 for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
1453 wordsB.insert(std::make_pair(iter->first, signatureB->
getWordsKpts()[iter->second]));
1465 covariances[dir] *= variance;
1466 inliers[dir] =
uKeys(inliers3D);
1467 matches[dir] = matchesV;
1469 if(!cameraTransform.
isNull())
1477 transforms[dir] = cameraTransform.
to3DoF();
1481 transforms[dir] = cameraTransform;
1486 msg =
uFormat(
"Variance is too high! (Max %s=%f, variance=%f)", Parameters::kVisEpipolarGeometryVar().c_str(),
_epipolarGeometryVar, variance);
1498 msg =
uFormat(
"No camera transform found");
1502 else if(signatureA->
getWords().size() == 0)
1504 msg =
uFormat(
"No enough features (%d)", (
int)signatureA->
getWords().size());
1509 msg =
uFormat(
"No camera model");
1519 UERROR(
"Calibrated camera required. Id=%d Models=%d StereoModels=%d weight=%d",
1525 #ifndef RTABMAP_OPENGV 1528 UERROR(
"Multi-camera 2D-3D PnP registration is only available if rtabmap is built " 1529 "with OpenGV dependency. Use 3D-3D registration approach instead for multi-camera.");
1539 std::vector<int> inliersV;
1540 std::vector<int> matchesV;
1543 std::map<int, cv::Point3f> words3A;
1544 std::map<int, cv::Point3f> words3B;
1545 std::map<int, cv::KeyPoint> wordsB;
1546 for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
1548 words3A.insert(std::make_pair(iter->first, signatureA->
getWords3()[iter->second]));
1550 for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
1552 wordsB.insert(std::make_pair(iter->first, signatureB->
getWordsKpts()[iter->second]));
1555 words3B.insert(std::make_pair(iter->first, signatureB->
getWords3()[iter->second]));
1559 std::vector<CameraModel> models;
1575 UASSERT(models[0].isValidForProjection());
1592 inliers[dir] = inliersV;
1593 matches[dir] = matchesV;
1597 UASSERT(models.size() == 1 && models[0].isValidForProjection());
1614 inliers[dir] = inliersV;
1615 matches[dir] = matchesV;
1617 UDEBUG(
"inliers: %d/%d", (
int)inliersV.size(), (int)matchesV.size());
1618 if(transforms[dir].
isNull())
1620 msg =
uFormat(
"Not enough inliers %d/%d (matches=%d) between %d and %d",
1621 (
int)inliers[dir].size(),
_minInliers, (
int)matches[dir].size(), signatureA->
id(), signatureB->
id());
1626 transforms[dir] = transforms[dir].
to3DoF();
1631 msg =
uFormat(
"Not enough features in images (old=%d, new=%d, min=%d)",
1645 std::vector<int> inliersV;
1646 std::vector<int> matchesV;
1649 std::map<int, cv::Point3f> words3A;
1650 std::map<int, cv::Point3f> words3B;
1651 for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
1653 words3A.insert(std::make_pair(iter->first, signatureA->
getWords3()[iter->second]));
1655 for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
1657 words3B.insert(std::make_pair(iter->first, signatureB->
getWords3()[iter->second]));
1669 inliers[dir] = inliersV;
1670 matches[dir] = matchesV;
1671 UDEBUG(
"inliers: %d/%d", (
int)inliersV.size(), (int)matchesV.size());
1672 if(transforms[dir].
isNull())
1674 msg =
uFormat(
"Not enough inliers %d/%d (matches=%d) between %d and %d",
1675 (
int)inliers[dir].size(),
_minInliers, (
int)matches[dir].size(), signatureA->
id(), signatureB->
id());
1680 transforms[dir] = transforms[dir].
to3DoF();
1685 msg =
uFormat(
"Not enough 3D features in images (old=%d, new=%d, min=%d)",
1694 UDEBUG(
"from->to=%s", transforms[0].prettyPrint().c_str());
1695 UDEBUG(
"to->from=%s", transforms[1].prettyPrint().c_str());
1698 std::vector<int> allInliers = inliers[0];
1699 if(inliers[1].size())
1701 std::set<int> allInliersSet(allInliers.begin(), allInliers.end());
1702 unsigned int oi = allInliers.size();
1703 allInliers.resize(allInliers.size() + inliers[1].size());
1704 for(
unsigned int i=0; i<inliers[1].size(); ++i)
1706 if(allInliersSet.find(inliers[1][i]) == allInliersSet.end())
1708 allInliers[oi++] = inliers[1][i];
1711 allInliers.resize(oi);
1713 std::vector<int> allMatches = matches[0];
1714 if(matches[1].size())
1716 std::set<int> allMatchesSet(allMatches.begin(), allMatches.end());
1717 unsigned int oi = allMatches.size();
1718 allMatches.resize(allMatches.size() + matches[1].size());
1719 for(
unsigned int i=0; i<matches[1].size(); ++i)
1721 if(allMatchesSet.find(matches[1][i]) == allMatchesSet.end())
1723 allMatches[oi++] = matches[1][i];
1726 allMatches.resize(oi);
1731 !transforms[0].
isNull() &&
1732 allInliers.size() &&
1738 UDEBUG(
"Refine with bundle adjustment");
1741 std::map<int, Transform> poses;
1742 std::multimap<int, Link> links;
1743 std::map<int, cv::Point3f> points3DMap;
1746 poses.insert(std::make_pair(2, transforms[0]));
1748 for(
int i=0;i<2;++i)
1750 UASSERT(covariances[i].cols==6 && covariances[i].rows == 6 && covariances[i].type() == CV_64FC1);
1765 cv::Mat cov = covariances[0].clone();
1768 if(!transforms[1].
isNull() && inliers[1].size())
1770 cov = covariances[1].clone();
1774 std::map<int, Transform> optimizedPoses;
1779 std::map<int, std::vector<CameraModel> > models;
1781 std::vector<CameraModel> cameraModelsFrom;
1795 cameraModelsFrom.push_back(cameraModel);
1803 std::vector<CameraModel> cameraModelsTo;
1817 cameraModelsTo.push_back(cameraModel);
1825 models.insert(std::make_pair(1, cameraModelsFrom));
1826 models.insert(std::make_pair(2, cameraModelsTo));
1828 std::map<int, std::map<int, FeatureBA> > wordReferences;
1829 std::set<int> sbaOutliers;
1831 for(
unsigned int i=0; i<allInliers.size(); ++i)
1833 int wordId = allInliers[i];
1834 int indexFrom = fromSignature.
getWords().find(wordId)->second;
1835 const cv::Point3f & pt3D = fromSignature.
getWords3()[indexFrom];
1839 sbaOutliers.insert(wordId);
1843 points3DMap.insert(std::make_pair(wordId, pt3D));
1845 std::map<int, FeatureBA> ptMap;
1848 cv::KeyPoint kpt = fromSignature.
getWordsKpts()[indexFrom];
1850 int cameraIndex = 0;
1851 const std::vector<CameraModel> &
cam = models.at(1);
1854 UASSERT(cam[0].imageWidth()>0);
1855 float subImageWidth = cam[0].imageWidth();
1856 cameraIndex = int(kpt.pt.x / subImageWidth);
1857 kpt.pt.x = kpt.pt.x - (subImageWidth*float(cameraIndex));
1860 UASSERT(cam[cameraIndex].isValidForProjection());
1863 ptMap.insert(std::make_pair(1,
FeatureBA(kpt, depthFrom, cv::Mat(), cameraIndex)));
1868 int indexTo = toSignature.
getWords().find(wordId)->second;
1869 cv::KeyPoint kpt = toSignature.
getWordsKpts()[indexTo];
1871 int cameraIndex = 0;
1872 const std::vector<CameraModel> &
cam = models.at(2);
1875 UASSERT(cam[0].imageWidth()>0);
1876 float subImageWidth = cam[0].imageWidth();
1877 cameraIndex = int(kpt.pt.x / subImageWidth);
1878 kpt.pt.x = kpt.pt.x - (subImageWidth*float(cameraIndex));
1881 UASSERT(cam[cameraIndex].isValidForProjection());
1883 float depthTo = 0.0f;
1889 ptMap.insert(std::make_pair(2,
FeatureBA(kpt, depthTo, cv::Mat(), cameraIndex)));
1892 wordReferences.insert(std::make_pair(wordId, ptMap));
1901 optimizedPoses = sba->
optimizeBA(1, poses, links, models, points3DMap, wordReferences, &sbaOutliers);
1905 if(optimizedPoses.size() == 2 &&
1906 !optimizedPoses.begin()->second.isNull() &&
1907 !optimizedPoses.rbegin()->second.isNull())
1909 UDEBUG(
"Pose optimization: %s -> %s", transforms[0].prettyPrint().c_str(), optimizedPoses.rbegin()->second.
prettyPrint().c_str());
1911 if(sbaOutliers.size())
1913 std::vector<int> newInliers(allInliers.size());
1915 for(
unsigned int i=0; i<allInliers.size(); ++i)
1917 if(sbaOutliers.find(allInliers[i]) == sbaOutliers.end())
1919 newInliers[oi++] = allInliers[i];
1922 newInliers.resize(oi);
1923 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(allInliers.size()));
1924 allInliers = newInliers;
1928 msg =
uFormat(
"Not enough inliers after bundle adjustment %d/%d (matches=%d) between %d and %d",
1929 (
int)allInliers.size(),
_minInliers, (int)allInliers.size()+sbaOutliers.size(), fromSignature.
id(), toSignature.
id());
1934 transforms[0] = optimizedPoses.rbegin()->second;
1960 inliersCount = (int)allInliers.size();
1961 matchesCount = (int)allMatches.size();
1962 if(!transforms[1].
isNull())
1964 transforms[1] = transforms[1].
inverse();
1965 if(transforms[0].
isNull())
1967 transform = transforms[1];
1968 covariance = covariances[1];
1972 transform = transforms[0].
interpolate(0.5
f, transforms[1]);
1973 covariance = (covariances[0]+covariances[1])/2.0
f;
1978 transform = transforms[0];
1979 covariance = covariances[0];
1985 std::vector<CameraModel> cameraModelsTo;
1999 if(cameraModelsTo.size() >= 1 && cameraModelsTo[0].isValidForReprojection())
2001 if(cameraModelsTo[0].imageWidth()>0 && cameraModelsTo[0].imageHeight()>0)
2003 pcaData = cv::Mat(allInliers.size(), 2, CV_32FC1);
2007 UERROR(
"Invalid calibration image size (%dx%d), cannot compute inliers distribution! (see %s=%f)", cameraModelsTo[0].imageWidth(), cameraModelsTo[0].imageHeight(), Parameters::kVisMinInliersDistribution().c_str(),
_minInliersDistributionThr);
2012 UERROR(
"Calibration not valid, cannot compute inliers distribution! (see %s=%f)", Parameters::kVisMinInliersDistribution().c_str(),
_minInliersDistributionThr);
2017 std::vector<float> distances;
2020 distances.reserve(allInliers.size());
2022 for(
unsigned int i=0; i<allInliers.size(); ++i)
2026 std::multimap<int, int>::const_iterator wordsIter = fromSignature.
getWords().find(allInliers[i]);
2027 if(wordsIter != fromSignature.
getWords().end() && !fromSignature.
getWords3().empty())
2029 const cv::Point3f & pt = fromSignature.
getWords3()[wordsIter->second];
2037 if(!pcaData.empty())
2039 std::multimap<int, int>::const_iterator wordsIter = toSignature.
getWords().find(allInliers[i]);
2041 float * ptr = pcaData.ptr<
float>(i, 0);
2042 const cv::KeyPoint & kpt = toSignature.
getWordsKpts()[wordsIter->second];
2043 int cameraIndex = (int)(kpt.pt.x / cameraModelsTo[0].imageWidth());
2044 UASSERT_MSG(cameraIndex < (
int)cameraModelsTo.size(),
uFormat(
"cameraIndex=%d (x=%f models=%d camera width = %d)", cameraIndex, kpt.pt.x, (
int)cameraModelsTo.size(), cameraModelsTo[0].imageWidth()).c_str());
2045 ptr[0] = (kpt.pt.x-cameraIndex*cameraModelsTo[cameraIndex].imageWidth()-cameraModelsTo[cameraIndex].cx()) / cameraModelsTo[cameraIndex].imageWidth();
2046 ptr[1] = (kpt.pt.y-cameraModelsTo[cameraIndex].cy()) / cameraModelsTo[cameraIndex].imageHeight();
2050 if(!distances.empty())
2056 msg =
uFormat(
"The mean distance of the inliers is over %s threshold (%f)",
2062 if(!transform.
isNull() && !pcaData.empty())
2064 cv::Mat pcaEigenVectors, pcaEigenValues;
2065 cv::PCA pca_analysis(pcaData, cv::Mat(), CV_PCA_DATA_AS_ROW);
2071 msg =
uFormat(
"The distribution (%f) of inliers is under %s threshold (%f)",
2080 msg =
uFormat(
"Missing correspondences for registration (%d->%d). fromWords = %d fromImageEmpty=%d toWords = %d toImageEmpty=%d",
2081 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)
static double COVARIANCE_ANGULAR_EPSILON
int _correspondencesApproach
float getMinDepth() const
rtabmap::CameraThread * cam
const cv::Size & imageSize() const
ParametersMap _bundleParameters
std::map< K, V > uMultimapToMapUnique(const std::multimap< K, V > &m)
virtual Feature2D::Type getType() const =0
T uMean(const T *v, unsigned int size)
float getMaxDepth() const
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
const std::vector< cv::Point3f > & keypoints3D() 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)
virtual ~RegistrationVis()
bool _forwardEstimateOnly
std::pair< std::string, std::string > ParametersPair
float _epipolarGeometryVar
const cv::Mat & getWordsDescriptors() const
float inliersMeanDistance
GLM_FUNC_DECL genType e()
const std::vector< StereoCameraModel > & stereoCameraModels() 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
const std::vector< cv::Point3f > & getWords3() const
Basic mathematics functions.
std::vector< int > inliersIDs
Some conversion functions.
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, std::vector< CameraModel > > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, FeatureBA > > &wordReferences, std::set< int > *outliers=0)
std::vector< cv::KeyPoint > generateKeypoints(const cv::Mat &image, const cv::Mat &mask=cv::Mat())
static double COVARIANCE_LINEAR_EPSILON
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)
const std::vector< cv::KeyPoint > & getWordsKpts() const
#define UASSERT(condition)
std::vector< cv::Point3f > generateKeypoints3D(const SensorData &data, const std::vector< cv::KeyPoint > &keypoints) const
Wrappers of STL for convenient functions.
std::list< std::string > uSplit(const std::string &str, char separator=' ')
Feature2D * _detectorFrom
const std::vector< CameraModel > & cameraModels() const
static Feature2D * create(const ParametersMap ¶meters=ParametersMap())
#define UASSERT_MSG(condition, msg_str)
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, float maxVariance=0, 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)
const cv::Mat & imageRaw() const
std::vector< int > projectedIDs
virtual void parseParameters(const ParametersMap ¶meters)
const cv::Mat & descriptors() const
const Transform & localTransform() const
static void filterKeypointsByDepth(std::vector< cv::KeyPoint > &keypoints, const cv::Mat &depth, float minDepth, float maxDepth)
void clear(bool printWarningsIfNotEmpty=true)
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
float inliersDistribution
bool uContains(const std::list< V > &list, const V &value)
static const ParametersMap & getDefaultParameters()
cv::Mat generateDescriptors(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) 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.
virtual Transform computeTransformationImpl(Signature &from, Signature &to, Transform guess, RegistrationInfo &info) const
ParametersMap _featureParameters
std::vector< int > matchesIDs
virtual void addWord(VisualWord *vw)
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)
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
const std::multimap< int, int > & getWords() const
GLM_FUNC_DECL matType< T, P > inverse(matType< T, P > const &m)