45 #include <opencv2/imgproc/imgproc.hpp>
46 #include <opencv2/calib3d/calib3d.hpp>
47 #include <opencv2/video/tracking.hpp>
48 #include <pcl/common/centroid.h>
54 flowWinSize_(
Parameters::defaultVisCorFlowWinSize()),
55 flowIterations_(
Parameters::defaultVisCorFlowIterations()),
57 flowMaxLevel_(
Parameters::defaultVisCorFlowMaxLevel()),
58 minInliers_(
Parameters::defaultVisMinInliers()),
59 iterations_(
Parameters::defaultVisIterations()),
60 pnpReprojError_(
Parameters::defaultVisPnPReprojError()),
62 pnpRefineIterations_(
Parameters::defaultVisPnPRefineIterations()),
63 localHistoryMaxSize_(
Parameters::defaultOdomF2MMaxSize()),
64 initMinFlow_(
Parameters::defaultOdomMonoInitMinFlow()),
65 initMinTranslation_(
Parameters::defaultOdomMonoInitMinTranslation()),
66 minTranslation_(
Parameters::defaultOdomMonoMinTranslation()),
67 fundMatrixReprojError_(
Parameters::defaultVhEpRansacParam1()),
68 fundMatrixConfidence_(
Parameters::defaultVhEpRansacParam2()),
69 maxVariance_(
Parameters::defaultOdomMonoMaxVariance()),
95 std::string roi = Parameters::defaultVisRoiRatios();
97 customParameters.insert(
ParametersPair(Parameters::kMemDepthAsMask(),
"false"));
98 customParameters.insert(
ParametersPair(Parameters::kKpRoiRatios(), roi));
99 customParameters.insert(
ParametersPair(Parameters::kMemRehearsalSimilarity(),
"1.0"));
100 customParameters.insert(
ParametersPair(Parameters::kMemBinDataKept(),
"false"));
101 customParameters.insert(
ParametersPair(Parameters::kMemSTMSize(),
"0"));
102 customParameters.insert(
ParametersPair(Parameters::kMemNotLinkedNodesKept(),
"false"));
103 customParameters.insert(
ParametersPair(Parameters::kKpTfIdfLikelihoodUsed(),
"false"));
104 int nn = Parameters::defaultVisCorNNType();
105 float nndr = Parameters::defaultVisCorNNDR();
106 int featureType = Parameters::defaultVisFeatureType();
107 int maxFeatures = Parameters::defaultVisMaxFeatures();
117 int subPixWinSize = Parameters::defaultVisSubPixWinSize();
118 int subPixIterations = Parameters::defaultVisSubPixIterations();
119 double subPixEps = Parameters::defaultVisSubPixEps();
121 Parameters::parse(parameters, Parameters::kVisSubPixIterations(), subPixIterations);
128 for(ParametersMap::const_iterator
iter=parameters.begin();
iter!=parameters.end(); ++
iter)
132 customParameters.insert(*
iter);
139 UERROR(
"Error initializing the memory for Mono Odometry.");
167 if(
data.imageRaw().empty())
169 UERROR(
"Image empty! Cannot compute odometry...");
173 if(!((
data.cameraModels().size() == 1 &&
data.cameraModels()[0].isValidForProjection()) ||
174 (
data.stereoCameraModels().size() == 1 &&
data.stereoCameraModels()[0].isValidForProjection())))
176 UERROR(
"Odometry cannot be done without calibration or on multi-camera!");
182 if(
data.stereoCameraModels().size())
184 cameraModel =
data.stereoCameraModels()[0].left();
191 -
data.stereoCameraModels()[0].baseline()*cameraModel.
fx(),
196 cameraModel =
data.cameraModels()[0];
198 std::vector<CameraModel> newModel;
199 newModel.push_back(cameraModel);
204 int correspondences = 0;
208 if(
data.imageRaw().channels() > 1 ||
data.rightRaw().channels() > 1)
210 cv::Mat newFrame =
data.imageRaw();
211 cv::Mat newFrameRight =
data.rightRaw();
212 if(
data.imageRaw().channels() > 1)
213 cv::cvtColor(
data.imageRaw(), newFrame, cv::COLOR_BGR2GRAY);
214 if(
data.rightRaw().channels() > 1)
215 cv::cvtColor(
data.rightRaw(), newFrameRight, cv::COLOR_BGR2GRAY);
216 if(!
data.stereoCameraModels().empty())
218 data.setStereoImage(newFrame, newFrameRight,
data.stereoCameraModels());
222 data.setRGBDImage(newFrame, newFrameRight,
data.cameraModels());
241 bool newPtsAdded =
false;
247 cv::Mat
K = cameraModel.
K();
249 cv::Mat
R = (cv::Mat_<double>(3,3) <<
250 (double)pnpGuess.
r11(), (double)pnpGuess.
r12(), (double)pnpGuess.
r13(),
251 (double)pnpGuess.
r21(), (double)pnpGuess.
r22(), (double)pnpGuess.
r23(),
252 (double)pnpGuess.
r31(), (double)pnpGuess.
r32(), (double)pnpGuess.
r33());
253 cv::Mat rvec(1,3, CV_64FC1);
254 cv::Rodrigues(
R, rvec);
255 cv::Mat tvec = (cv::Mat_<double>(1,3) << (double)pnpGuess.
x(), (double)pnpGuess.
y(), (double)pnpGuess.
z());
257 std::vector<cv::Point3f> objectPoints;
258 std::vector<cv::Point2f> imagePoints;
261 UDEBUG(
"compute PnP from optical flow");
267 UDEBUG(
"project points to previous image");
268 std::vector<cv::Point2f> prevImagePoints;
271 cv::Mat prevR = (cv::Mat_<double>(3,3) <<
272 (double)prevGuess.
r11(), (double)prevGuess.
r12(), (double)prevGuess.
r13(),
273 (double)prevGuess.
r21(), (double)prevGuess.
r22(), (double)prevGuess.
r23(),
274 (double)prevGuess.
r31(), (double)prevGuess.
r32(), (double)prevGuess.
r33());
275 cv::Mat prevRvec(1,3, CV_64FC1);
276 cv::Rodrigues(prevR, prevRvec);
277 cv::Mat prevTvec = (cv::Mat_<double>(1,3) << (double)prevGuess.
x(), (double)prevGuess.
y(), (double)prevGuess.
z());
278 cv::projectPoints(objectPoints, prevRvec, prevTvec,
K, cv::Mat(), prevImagePoints);
281 UDEBUG(
"project points to current image");
282 cv::projectPoints(objectPoints, rvec, tvec,
K, cv::Mat(), imagePoints);
285 std::vector<cv::Point3f> objectPointsTmp(objectPoints.size());
286 std::vector<cv::Point2f> refCorners(objectPoints.size());
287 std::vector<cv::Point2f> newCorners(objectPoints.size());
288 matches.resize(objectPoints.size());
290 for(
unsigned int i=0;
i<objectPoints.size(); ++
i)
297 refCorners[oi] = prevImagePoints[
i];
298 newCorners[oi] = imagePoints[
i];
312 objectPointsTmp[oi] = objectPoints[
i];
317 objectPointsTmp.resize(oi);
318 refCorners.resize(oi);
319 newCorners.resize(oi);
323 std::vector<unsigned char> statusFlowInliers;
324 std::vector<float> err;
325 UDEBUG(
"cv::calcOpticalFlowPyrLK() begin");
326 cv::calcOpticalFlowPyrLK(
335 cv::OPTFLOW_LK_GET_MIN_EIGENVALS | cv::OPTFLOW_USE_INITIAL_FLOW, 1
e-4);
336 UDEBUG(
"cv::calcOpticalFlowPyrLK() end");
338 objectPoints.resize(statusFlowInliers.size());
339 imagePoints.resize(statusFlowInliers.size());
340 std::vector<int> matchesTmp(statusFlowInliers.size());
342 for(
unsigned int i=0;
i<statusFlowInliers.size(); ++
i)
344 if(statusFlowInliers[
i] &&
348 objectPoints[oi] = objectPointsTmp[
i];
349 imagePoints[oi] = newCorners[
i];
360 kpt.pt = newCorners[
i];
365 UDEBUG(
"Flow inliers= %d/%d", oi, (
int)statusFlowInliers.size());
366 objectPoints.resize(oi);
367 imagePoints.resize(oi);
368 matchesTmp.resize(oi);
384 std::vector<int> inliersV;
400 UDEBUG(
"inliers=%d/%d", (
int)inliersV.size(), (
int)objectPoints.size());
402 inliers = (
int)inliersV.size();
405 UWARN(
"PnP not enough inliers (%d < %d), rejecting the transform...", (
int)inliersV.size(),
minInliers_);
409 cv::Mat
R(3,3,CV_64FC1);
410 cv::Rodrigues(rvec,
R);
411 Transform pnp =
Transform(
R.at<
double>(0,0),
R.at<
double>(0,1),
R.at<
double>(0,2), tvec.at<
double>(0),
412 R.at<
double>(1,0),
R.at<
double>(1,1),
R.at<
double>(1,2), tvec.at<
double>(1),
413 R.at<
double>(2,0),
R.at<
double>(2,1),
R.at<
double>(2,2), tvec.at<
double>(2));
418 info->reg.inliersIDs.resize(inliersV.size());
419 for(
unsigned int i=0;
i<inliersV.size(); ++
i)
426 cv::Mat covariance = cv::Mat::eye(6, 6, CV_64FC1);
427 std::vector<cv::Point2f> imagePointsReproj;
428 cv::projectPoints(objectPoints, rvec, tvec,
K, cv::Mat(), imagePointsReproj);
430 for(
unsigned int i=0;
i<inliersV.size(); ++
i)
432 err +=
uNormSquared(imagePoints.at(inliersV[
i]).x - imagePointsReproj.at(inliersV[
i]).x, imagePoints.at(inliersV[
i]).y - imagePointsReproj.at(inliersV[
i]).y);
435 covariance *=
std::sqrt(err/
float(inliersV.size()));
442 poses.insert(std::make_pair(newS->
id(),
this->getPose()*output));
445 UWARN(
"Bundle adjustment: fill arguments");
448 links.insert(std::make_pair(
keyFramePoses_.rbegin()->first, newLink));
449 models.insert(std::make_pair(newS->
id(), newModel));
450 std::map<int, std::map<int, FeatureBA> > wordReferences;
455 for(std::multimap<int, int>::const_iterator jter=
s->getWords().begin(); jter!=
s->getWords().end(); ++jter)
457 if(
s->getWords().count(jter->first) == 1 &&
localMap_.find(jter->first)!=
localMap_.end() && !
s->getWordsKpts().empty())
459 if(wordReferences.find(jter->first)==wordReferences.end())
461 wordReferences.insert(std::make_pair(jter->first, std::map<int, FeatureBA>()));
469 const cv::KeyPoint & kpts =
s->getWordsKpts()[jter->second];
470 wordReferences.at(jter->first).insert(std::make_pair(
s->id(),
FeatureBA(kpts, depth, cv::Mat())));
475 std::set<int> outliers;
476 UWARN(
"Bundle adjustment begin");
477 poses = ba->
optimizeBA(poses.begin()->first, poses, links, models,
localMap_, wordReferences, &outliers);
478 UWARN(
"Bundle adjustment end");
488 stMem.erase(newS->
id());
490 int maxLikelihoodId = -1;
491 float maxLikelihood = 0;
492 for(std::map<int, float>::iterator
iter=likelihood.begin();
iter!=likelihood.end(); ++
iter)
494 if(
iter->second > maxLikelihood)
496 maxLikelihood =
iter->second;
497 maxLikelihoodId =
iter->first;
500 if(maxLikelihoodId == -1)
502 UWARN(
"Cannot find a keyframe similar enough to generate new 3D points!");
504 else if(poses.size())
512 UINFO(
"Inliers= %d/%d (%f)", inliers, (
int)imagePoints.size(),
float(inliers)/
float(imagePoints.size()));
516 UINFO(
"Translation with the nearest frame is too small (%f<%f) to add new points to local map",
519 else if(
float(inliers)/
float(imagePoints.size()) <
keyFrameThr_)
523 std::map<int, cv::KeyPoint> wordsPrevious;
524 std::map<int, cv::KeyPoint> wordsNew;
525 for(std::map<int, int>::iterator
iter=uniqueWordsPrevious.begin();
iter!=uniqueWordsPrevious.end(); ++
iter)
529 for(std::map<int, int>::iterator
iter=uniqueWordsNew.begin();
iter!=uniqueWordsNew.end(); ++
iter)
543 UWARN(
"Epipolar geometry not enough inliers (%d < %d), rejecting the transform (%s)...",
551 std::multimap<int, cv::Point3f> wordsToAdd;
552 for(std::map<int, cv::Point3f>::iterator
iter=inliers3D.begin();
553 iter != inliers3D.end();
563 wordsToAdd.insert(std::make_pair(
iter->first, newPt));
567 if((
int)wordsToAdd.size())
569 localMap_.insert(wordsToAdd.begin(), wordsToAdd.end());
571 UWARN(
"Added %d words", (
int)wordsToAdd.size());
577 std::vector<cv::Point3f> newCorners3;
578 if(!
data.depthOrRightRaw().empty())
580 std::vector<cv::KeyPoint> newKeypoints(imagePoints.size());
581 for(
size_t i=0;
i<imagePoints.size(); ++
i)
583 newKeypoints[
i] = cv::KeyPoint(imagePoints[
i], 3);
586 for(
size_t i=0;
i<newCorners3.size(); ++
i)
589 inliers3D.find(
matches[
i])!=inliers3D.end())
591 inliers3D.at(
matches[
i]) = newCorners3[
i];
600 if(!inliers3D.empty())
602 UDEBUG(
"Added %d/%d valid 3D features", (
int)inliers3D.size(), (
int)wordsToAdd.size());
613 std::list<int> removedPts;
619 for(std::list<int>::iterator
iter = removedPts.begin();
iter!=removedPts.end(); ++
iter)
657 std::multimap<int, int>::const_iterator jter=refS->
getWords().find(
iter->first);
660 refCornersGuess[ii] =
iter->second;
661 cornerIds[ii] =
iter->first;
667 std::vector<unsigned char> statusFlowInliers;
668 std::vector<float> err;
669 UDEBUG(
"cv::calcOpticalFlowPyrLK() begin");
670 cv::calcOpticalFlowPyrLK(
679 cv::OPTFLOW_LK_GET_MIN_EIGENVALS | cv::OPTFLOW_USE_INITIAL_FLOW, 1
e-4);
680 UDEBUG(
"cv::calcOpticalFlowPyrLK() end");
682 UDEBUG(
"Filtering optical flow outliers...");
687 info->refCorners = refCorners;
688 info->newCorners = refCornersGuess;
692 std::vector<cv::Point2f> tmpRefCorners(statusFlowInliers.size());
693 std::vector<cv::Point2f> newCorners(statusFlowInliers.size());
694 std::vector<int> inliersV(statusFlowInliers.size());
695 std::vector<int> tmpCornersId(statusFlowInliers.size());
696 UASSERT(refCornersGuess.size() == statusFlowInliers.size());
697 UASSERT(refCorners.size() == statusFlowInliers.size());
698 UASSERT(cornerIds.size() == statusFlowInliers.size());
699 for(
unsigned int i=0;
i<statusFlowInliers.size(); ++
i)
701 if(statusFlowInliers[
i])
703 float dx = refCorners[
i].x - refCornersGuess[
i].x;
704 float dy = refCorners[
i].y - refCornersGuess[
i].y;
708 tmpRefCorners[oi] = refCorners[
i];
709 newCorners[oi] = refCornersGuess[
i];
714 tmpCornersId[oi] = cornerIds[
i];
727 tmpRefCorners.resize(oi);
728 newCorners.resize(oi);
729 inliersV.resize((oi));
730 tmpCornersId.resize(oi);
731 refCorners= tmpRefCorners;
732 cornerIds = tmpCornersId;
737 info->cornerInliers = inliersV;
738 inliers = (
int)inliersV.size();
741 UDEBUG(
"Filtering optical flow outliers...done! (inliers=%d/%d)", oi, (
int)statusFlowInliers.size());
746 std::vector<cv::Point3f> refCorners3;
749 std::vector<cv::KeyPoint> refKeypoints(refCorners.size());
750 for(
size_t i=0;
i<refCorners.size(); ++
i)
752 refKeypoints[
i] = cv::KeyPoint(refCorners[
i], 3);
757 std::map<int, cv::KeyPoint> refWords;
758 std::map<int, cv::KeyPoint> newWords;
759 std::map<int, cv::Point3f> refWords3Guess;
760 for(
unsigned int i=0;
i<cornerIds.size(); ++
i)
762 refWords.insert(std::make_pair(cornerIds[
i], cv::KeyPoint(refCorners[
i], 3)));
763 newWords.insert(std::make_pair(cornerIds[
i], cv::KeyPoint(newCorners[
i], 3)));
764 if(!refCorners3.empty())
766 refWords3Guess.insert(std::make_pair(cornerIds[
i], refCorners3[
i]));
782 UWARN(
"Camera must be moved at least %f m for initialization (current=%f)",
789 for(std::map<int, cv::Point3f>::iterator
iter=refWords3.begin();
iter!=refWords3.end();)
791 std::map<int, cv::Point3f>::iterator jterGuess3D = refWords3Guess.find(
iter->first);
792 if(jterGuess3D != refWords3Guess.end() &&
795 iter->second = jterGuess3D->second;
800 refWords3.erase(
iter++);
803 if(!refWords3.empty())
805 UDEBUG(
"Added %d/%d valid 3D features", (
int)refWords3.size(), (
int)
localMap_.size());
814 UWARN(
"Flow not enough high! flow=%f ki=%d", flow, oi);
825 info->reg.covariance = cv::Mat::eye(6,6,CV_64FC1)*9999.0;
832 const std::multimap<int, int> & words =
s->getWords();
833 if((
int)words.size() >
minInliers_ && !
s->getWordsKpts().empty())
835 for(std::multimap<int, int>::const_iterator
iter=words.begin();
iter!=words.end(); ++
iter)
837 if(words.count(
iter->first) == 1)
850 UERROR(
"Failed creating signature");
859 info->reg.inliers = inliers;
860 info->reg.matches = correspondences;
861 info->features = nFeatures;
866 UINFO(
"Odom update=%fs tf=[%s] inliers=%d/%d, local_map[%d]=%d, accepted=%s",
873 !output.
isNull()?
"true":
"false");