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.");
169 UERROR(
"Image empty! Cannot compute odometry...");
175 UERROR(
"Odometry cannot be done without calibration or on multi-camera!");
200 int correspondences = 0;
207 cv::cvtColor(data.
imageRaw(), newFrame, cv::COLOR_BGR2GRAY);
208 data.setImageRaw(newFrame);
226 bool newPtsAdded =
false;
229 nFeatures = (int)newS->
getWords().size();
232 cv::Mat K = cameraModel.
K();
234 cv::Mat R = (cv::Mat_<double>(3,3) <<
235 (
double)pnpGuess.
r11(), (double)pnpGuess.
r12(), (double)pnpGuess.
r13(),
236 (double)pnpGuess.
r21(), (double)pnpGuess.
r22(), (double)pnpGuess.
r23(),
237 (double)pnpGuess.
r31(), (double)pnpGuess.
r32(), (double)pnpGuess.
r33());
238 cv::Mat rvec(1,3, CV_64FC1);
239 cv::Rodrigues(R, rvec);
240 cv::Mat tvec = (cv::Mat_<double>(1,3) << (
double)pnpGuess.
x(), (double)pnpGuess.
y(), (double)pnpGuess.
z());
242 std::vector<cv::Point3f> objectPoints;
243 std::vector<cv::Point2f> imagePoints;
244 std::vector<int> matches;
246 UDEBUG(
"compute PnP from optical flow");
252 UDEBUG(
"project points to previous image");
253 std::vector<cv::Point2f> prevImagePoints;
256 cv::Mat prevR = (cv::Mat_<double>(3,3) <<
257 (
double)prevGuess.
r11(), (double)prevGuess.
r12(), (double)prevGuess.
r13(),
258 (double)prevGuess.
r21(), (double)prevGuess.
r22(), (double)prevGuess.
r23(),
259 (double)prevGuess.
r31(), (double)prevGuess.
r32(), (double)prevGuess.
r33());
260 cv::Mat prevRvec(1,3, CV_64FC1);
261 cv::Rodrigues(prevR, prevRvec);
262 cv::Mat prevTvec = (cv::Mat_<double>(1,3) << (
double)prevGuess.
x(), (double)prevGuess.
y(), (double)prevGuess.
z());
263 cv::projectPoints(objectPoints, prevRvec, prevTvec, K, cv::Mat(), prevImagePoints);
266 UDEBUG(
"project points to current image");
267 cv::projectPoints(objectPoints, rvec, tvec, K, cv::Mat(), imagePoints);
270 std::vector<cv::Point3f> objectPointsTmp(objectPoints.size());
271 std::vector<cv::Point2f> refCorners(objectPoints.size());
272 std::vector<cv::Point2f> newCorners(objectPoints.size());
273 matches.resize(objectPoints.size());
275 for(
unsigned int i=0; i<objectPoints.size(); ++i)
282 refCorners[oi] = prevImagePoints[i];
283 newCorners[oi] = imagePoints[i];
297 objectPointsTmp[oi] = objectPoints[i];
298 matches[oi] = ids[i];
302 objectPointsTmp.resize(oi);
303 refCorners.resize(oi);
304 newCorners.resize(oi);
308 std::vector<unsigned char> statusFlowInliers;
309 std::vector<float> err;
310 UDEBUG(
"cv::calcOpticalFlowPyrLK() begin");
311 cv::calcOpticalFlowPyrLK(
320 cv::OPTFLOW_LK_GET_MIN_EIGENVALS | cv::OPTFLOW_USE_INITIAL_FLOW, 1
e-4);
321 UDEBUG(
"cv::calcOpticalFlowPyrLK() end");
323 objectPoints.resize(statusFlowInliers.size());
324 imagePoints.resize(statusFlowInliers.size());
325 std::vector<int> matchesTmp(statusFlowInliers.size());
327 for(
unsigned int i=0; i<statusFlowInliers.size(); ++i)
329 if(statusFlowInliers[i] &&
333 objectPoints[oi] = objectPointsTmp[i];
334 imagePoints[oi] = newCorners[i];
335 matchesTmp[oi] = matches[i];
345 kpt.pt = newCorners[i];
346 info->
words.insert(std::make_pair(matches[i], kpt));
350 UDEBUG(
"Flow inliers= %d/%d", oi, (
int)statusFlowInliers.size());
351 objectPoints.resize(oi);
352 imagePoints.resize(oi);
353 matchesTmp.resize(oi);
354 matches = matchesTmp;
360 correspondences = (int)matches.size();
369 std::vector<int> inliersV;
385 UDEBUG(
"inliers=%d/%d", (
int)inliersV.size(), (int)objectPoints.size());
387 inliers = (int)inliersV.size();
390 UWARN(
"PnP not enough inliers (%d < %d), rejecting the transform...", (
int)inliersV.size(),
minInliers_);
394 cv::Mat R(3,3,CV_64FC1);
395 cv::Rodrigues(rvec, R);
396 Transform pnp =
Transform(R.at<
double>(0,0), R.at<
double>(0,1), R.at<
double>(0,2), tvec.at<
double>(0),
397 R.at<
double>(1,0), R.at<
double>(1,1), R.at<
double>(1,2), tvec.at<
double>(1),
398 R.at<
double>(2,0), R.at<
double>(2,1), R.at<
double>(2,2), tvec.at<
double>(2));
404 for(
unsigned int i=0; i<inliersV.size(); ++i)
411 cv::Mat covariance = cv::Mat::eye(6, 6, CV_64FC1);
412 std::vector<cv::Point2f> imagePointsReproj;
413 cv::projectPoints(objectPoints, rvec, tvec, K, cv::Mat(), imagePointsReproj);
415 for(
unsigned int i=0; i<inliersV.size(); ++i)
417 err +=
uNormSquared(imagePoints.at(inliersV[i]).x - imagePointsReproj.at(inliersV[i]).x, imagePoints.at(inliersV[i]).y - imagePointsReproj.at(inliersV[i]).y);
420 covariance *=
std::sqrt(err/
float(inliersV.size()));
427 poses.insert(std::make_pair(newS->
id(), this->
getPose()*output));
430 UWARN(
"Bundle adjustment: fill arguments");
433 links.insert(std::make_pair(
keyFramePoses_.rbegin()->first, newLink));
434 models.insert(std::make_pair(newS->
id(), cameraModel));
435 std::map<int, std::map<int, FeatureBA> > wordReferences;
440 for(std::multimap<int, int>::const_iterator jter=s->
getWords().begin(); jter!=s->
getWords().end(); ++jter)
444 if(wordReferences.find(jter->first)==wordReferences.end())
446 wordReferences.insert(std::make_pair(jter->first, std::map<int, FeatureBA>()));
454 const cv::KeyPoint & kpts = s->
getWordsKpts()[jter->second];
455 wordReferences.at(jter->first).insert(std::make_pair(s->
id(),
FeatureBA(kpts, depth, cv::Mat())));
460 std::set<int> outliers;
461 UWARN(
"Bundle adjustment begin");
462 poses = ba->optimizeBA(poses.begin()->first, poses, links, models,
localMap_, wordReferences, &outliers);
463 UWARN(
"Bundle adjustment end");
473 stMem.erase(newS->
id());
475 int maxLikelihoodId = -1;
476 float maxLikelihood = 0;
477 for(std::map<int, float>::iterator iter=likelihood.begin(); iter!=likelihood.end(); ++iter)
479 if(iter->second > maxLikelihood)
481 maxLikelihood = iter->second;
482 maxLikelihoodId = iter->first;
485 if(maxLikelihoodId == -1)
487 UWARN(
"Cannot find a keyframe similar enough to generate new 3D points!");
489 else if(poses.size())
497 UINFO(
"Inliers= %d/%d (%f)", inliers, (
int)imagePoints.size(), float(inliers)/float(imagePoints.size()));
501 UINFO(
"Translation with the nearest frame is too small (%f<%f) to add new points to local map",
504 else if(
float(inliers)/float(imagePoints.size()) <
keyFrameThr_)
508 std::map<int, cv::KeyPoint> wordsPrevious;
509 std::map<int, cv::KeyPoint> wordsNew;
510 for(std::map<int, int>::iterator iter=uniqueWordsPrevious.begin(); iter!=uniqueWordsPrevious.end(); ++iter)
512 wordsPrevious.insert(std::make_pair(iter->first, previousS->
getWordsKpts()[iter->second]));
514 for(std::map<int, int>::iterator iter=uniqueWordsNew.begin(); iter!=uniqueWordsNew.end(); ++iter)
516 wordsNew.insert(std::make_pair(iter->first, newS->
getWordsKpts()[iter->second]));
528 UWARN(
"Epipolar geometry not enough inliers (%d < %d), rejecting the transform (%s)...",
536 std::multimap<int, cv::Point3f> wordsToAdd;
537 for(std::map<int, cv::Point3f>::iterator iter=inliers3D.begin();
538 iter != inliers3D.end();
548 wordsToAdd.insert(std::make_pair(iter->first, newPt));
552 if((
int)wordsToAdd.size())
554 localMap_.insert(wordsToAdd.begin(), wordsToAdd.end());
556 UWARN(
"Added %d words", (
int)wordsToAdd.size());
562 std::vector<cv::Point3f> newCorners3;
565 std::vector<cv::KeyPoint> newKeypoints(imagePoints.size());
566 for(
size_t i=0;i<imagePoints.size(); ++i)
568 newKeypoints[i] = cv::KeyPoint(imagePoints[i], 3);
571 for(
size_t i=0;i<newCorners3.size(); ++i)
574 inliers3D.find(matches[i])!=inliers3D.end())
576 inliers3D.at(matches[i]) = newCorners3[i];
580 inliers3D.erase(matches[i]);
585 if(!inliers3D.empty())
587 UDEBUG(
"Added %d/%d valid 3D features", (
int)inliers3D.size(), (int)wordsToAdd.size());
598 std::list<int> removedPts;
604 for(std::list<int>::iterator iter = removedPts.begin(); iter!=removedPts.end(); ++iter)
642 std::multimap<int, int>::const_iterator jter=refS->
getWords().find(iter->first);
645 refCornersGuess[ii] = iter->second;
646 cornerIds[ii] = iter->first;
652 std::vector<unsigned char> statusFlowInliers;
653 std::vector<float> err;
654 UDEBUG(
"cv::calcOpticalFlowPyrLK() begin");
655 cv::calcOpticalFlowPyrLK(
664 cv::OPTFLOW_LK_GET_MIN_EIGENVALS | cv::OPTFLOW_USE_INITIAL_FLOW, 1
e-4);
665 UDEBUG(
"cv::calcOpticalFlowPyrLK() end");
667 UDEBUG(
"Filtering optical flow outliers...");
677 std::vector<cv::Point2f> tmpRefCorners(statusFlowInliers.size());
678 std::vector<cv::Point2f> newCorners(statusFlowInliers.size());
679 std::vector<int> inliersV(statusFlowInliers.size());
680 std::vector<int> tmpCornersId(statusFlowInliers.size());
681 UASSERT(refCornersGuess.size() == statusFlowInliers.size());
682 UASSERT(refCorners.size() == statusFlowInliers.size());
683 UASSERT(cornerIds.size() == statusFlowInliers.size());
684 for(
unsigned int i=0; i<statusFlowInliers.size(); ++i)
686 if(statusFlowInliers[i])
688 float dx = refCorners[i].x - refCornersGuess[i].x;
689 float dy = refCorners[i].y - refCornersGuess[i].y;
693 tmpRefCorners[oi] = refCorners[i];
694 newCorners[oi] = refCornersGuess[i];
699 tmpCornersId[oi] = cornerIds[i];
712 tmpRefCorners.resize(oi);
713 newCorners.resize(oi);
714 inliersV.resize((oi));
715 tmpCornersId.resize(oi);
716 refCorners= tmpRefCorners;
717 cornerIds = tmpCornersId;
723 inliers = (int)inliersV.size();
726 UDEBUG(
"Filtering optical flow outliers...done! (inliers=%d/%d)", oi, (
int)statusFlowInliers.size());
731 std::vector<cv::Point3f> refCorners3;
734 std::vector<cv::KeyPoint> refKeypoints(refCorners.size());
735 for(
size_t i=0;i<refCorners.size(); ++i)
737 refKeypoints[i] = cv::KeyPoint(refCorners[i], 3);
742 std::map<int, cv::KeyPoint> refWords;
743 std::map<int, cv::KeyPoint> newWords;
744 std::map<int, cv::Point3f> refWords3Guess;
745 for(
unsigned int i=0; i<cornerIds.size(); ++i)
747 refWords.insert(std::make_pair(cornerIds[i], cv::KeyPoint(refCorners[i], 3)));
748 newWords.insert(std::make_pair(cornerIds[i], cv::KeyPoint(newCorners[i], 3)));
749 if(!refCorners3.empty())
751 refWords3Guess.insert(std::make_pair(cornerIds[i], refCorners3[i]));
767 UWARN(
"Camera must be moved at least %f m for initialization (current=%f)",
774 for(std::map<int, cv::Point3f>::iterator iter=refWords3.begin(); iter!=refWords3.end();)
776 std::map<int, cv::Point3f>::iterator jterGuess3D = refWords3Guess.find(iter->first);
777 if(jterGuess3D != refWords3Guess.end() &&
780 iter->second = jterGuess3D->second;
785 refWords3.erase(iter++);
788 if(!refWords3.empty())
790 UDEBUG(
"Added %d/%d valid 3D features", (
int)refWords3.size(), (int)
localMap_.size());
799 UWARN(
"Flow not enough high! flow=%f ki=%d", flow, oi);
817 const std::multimap<int, int> & words = s->
getWords();
820 for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
822 if(words.count(iter->first) == 1)
835 UERROR(
"Failed creating signature");
851 UINFO(
"Odom update=%fs tf=[%s] inliers=%d/%d, local_map[%d]=%d, accepted=%s",
858 !output.
isNull()?
"true":
"false");
static bool isFeatureParameter(const std::string ¶m)
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
std::map< K, V > uMultimapToMapUnique(const std::multimap< K, V > &m)
std::vector< cv::Point2f > refCorners
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)
std::map< int, cv::Point2f > firstFrameGuessCorners_
bool isInfoDataFilled() const
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 void reset(const Transform &initialPose=Transform::getIdentity())
const Signature * getSignature(int id) const
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
virtual Transform computeTransform(SensorData &data, const Transform &guess=Transform(), OdometryInfo *info=0)
std::map< int, cv::Point3f > localMap
std::pair< std::string, std::string > ParametersPair
GLM_FUNC_DECL genType e()
std::map< std::string, std::string > ParametersMap
OdometryMono(const rtabmap::ParametersMap ¶meters=rtabmap::ParametersMap())
const Transform & getPose() const
Basic mathematics functions.
std::vector< int > inliersIDs
Some conversion functions.
void deleteLocation(int locationId, std::list< int > *deletedWords=0)
const cv::Mat & imageRaw() const
float initMinTranslation_
const std::set< int > & getStMem() const
const std::vector< cv::KeyPoint > & getWordsKpts() const
bool init(const std::string &dbUrl, bool dbOverwritten=false, const ParametersMap ¶meters=ParametersMap(), bool postInitClosingEvents=false)
bool uIsFinite(const T &value)
#define UASSERT(condition)
Wrappers of STL for convenient functions.
bool isValidForProjection() const
const CameraModel & left() const
const std::multimap< int, int > & getWords() const
static Feature2D * create(const ParametersMap ¶meters=ParametersMap())
std::vector< int > cornerInliers
std::map< int, CameraModel > keyFrameModels_
bool update(const SensorData &data, Statistics *stats=0)
const cv::Mat & depthOrRightRaw() const
bool uContains(const std::list< V > &list, const V &value)
void RTABMAP_EXP solvePnPRansac(const std::vector< cv::Point3f > &objectPoints, const std::vector< cv::Point2f > &imagePoints, const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, cv::Mat &rvec, cv::Mat &tvec, bool useExtrinsicGuess, int iterationsCount, float reprojectionError, int minInliersCount, std::vector< int > &inliers, int flags, int refineIterations=1, float refineSigma=3.0f)
std::map< int, Transform > keyFramePoses_
int getLastSignatureId() const
const std::vector< CameraModel > & cameraModels() const
std::vector< V > uValues(const std::multimap< K, V > &mm)
float fundMatrixReprojError_
std::multimap< int, cv::KeyPoint > words
SensorData & sensorData()
T uNormSquared(const std::vector< T > &v)
const Signature * getLastWorkingSignature() const
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
std::vector< int > matchesIDs
std::map< int, float > computeLikelihood(const Signature *signature, const std::list< int > &ids)
std::vector< cv::Point2f > newCorners
virtual void reset(const Transform &initialPose)
float fundMatrixConfidence_
std::map< int, std::map< int, cv::Point3f > > keyFrameWords3D_
std::multimap< int, Link > keyFrameLinks_
std::string UTILITE_EXP uNumber2Str(unsigned int number)
std::map< int, cv::Point3f > localMap_
static Optimizer * create(const ParametersMap ¶meters)
const Transform & localTransform() const
GLM_FUNC_DECL matType< T, P > inverse(matType< T, P > const &m)