Increased version to 0.20.5

Refactored how features are stored in Signature (significative memory optimization, causing major refactoring in Memory, RegistrationVis, OdometryF2M)
FLANN: optimized memory usage when Kp/IncrementalFlann is false
Added memory usage functions
Added statistics Loop/Visual_inliers_ratio/ and Memory/RAM_estimated/MB
EpipolarGeometry: templated findPairs functions
graph::filterLinks: added inverted option
LocalBundleOnLoopClosure: Force to use only neighbor links
MainWindow: fixed max depth filtering for map's features
Rtabmap::getSignatureCopy() fixed links not returned
Added UPlot::getAllCurveDataAsText() function.
DbViewer: fixed features not rendered in right view when failing ro refine a constraint
report: added --export and --export_prefix options (to export figures data)
This commit is contained in:
matlabbe
2020-10-05 17:34:32 -04:00
parent bedc771fa4
commit bbccbd63e4
41 changed files with 1456 additions and 898 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
####################### #######################
SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 20) SET(RTABMAP_MINOR_VERSION 20)
SET(RTABMAP_PATCH_VERSION 4) SET(RTABMAP_PATCH_VERSION 5)
SET(RTABMAP_VERSION SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
@@ -61,6 +61,8 @@ public:
cv::Mat generatePrediction(const Memory * memory, const std::vector<int> & ids); cv::Mat generatePrediction(const Memory * memory, const std::vector<int> & ids);
unsigned long getMemoryUsed() const;
private: private:
cv::Mat updatePrediction(const cv::Mat & oldPrediction, cv::Mat updatePrediction(const cv::Mat & oldPrediction,
const Memory * memory, const Memory * memory,
+2 -2
View File
@@ -131,7 +131,7 @@ public:
bool openConnection(const std::string & url, bool overwritten = false); bool openConnection(const std::string & url, bool overwritten = false);
void closeConnection(bool save = true, const std::string & outputUrl = ""); void closeConnection(bool save = true, const std::string & outputUrl = "");
bool isConnected() const; bool isConnected() const;
long getMemoryUsed() const; // In bytes unsigned long getMemoryUsed() const; // In bytes
std::string getDatabaseVersion() const; std::string getDatabaseVersion() const;
long getNodesMemoryUsed() const; long getNodesMemoryUsed() const;
long getLinksMemoryUsed() const; long getLinksMemoryUsed() const;
@@ -188,7 +188,7 @@ protected:
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false) = 0; virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false) = 0;
virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = "") = 0; virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = "") = 0;
virtual bool isConnectedQuery() const = 0; virtual bool isConnectedQuery() const = 0;
virtual long getMemoryUsedQuery() const = 0; // In bytes virtual unsigned long getMemoryUsedQuery() const = 0; // In bytes
virtual bool getDatabaseVersionQuery(std::string & version) const = 0; virtual bool getDatabaseVersionQuery(std::string & version) const = 0;
virtual long getNodesMemoryUsedQuery() const = 0; virtual long getNodesMemoryUsedQuery() const = 0;
virtual long getLinksMemoryUsedQuery() const = 0; virtual long getLinksMemoryUsedQuery() const = 0;
@@ -54,7 +54,7 @@ protected:
virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false); virtual bool connectDatabaseQuery(const std::string & url, bool overwritten = false);
virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = ""); virtual void disconnectDatabaseQuery(bool save = true, const std::string & outputUrl = "");
virtual bool isConnectedQuery() const; virtual bool isConnectedQuery() const;
virtual long getMemoryUsedQuery() const; // In bytes virtual unsigned long getMemoryUsedQuery() const; // In bytes
virtual bool getDatabaseVersionQuery(std::string & version) const; virtual bool getDatabaseVersionQuery(std::string & version) const;
virtual long getNodesMemoryUsedQuery() const; virtual long getNodesMemoryUsedQuery() const;
virtual long getLinksMemoryUsedQuery() const; virtual long getLinksMemoryUsedQuery() const;
@@ -189,7 +189,7 @@ protected:
std::string _version; std::string _version;
private: private:
long _memoryUsedEstimate; unsigned long _memoryUsedEstimate;
bool _dbInMemory; bool _dbInMemory;
unsigned int _cacheSize; unsigned int _cacheSize;
int _journalMode; int _journalMode;
+109 -16
View File
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines #include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include "rtabmap/core/Parameters.h" #include "rtabmap/core/Parameters.h"
#include "rtabmap/utilite/UStl.h"
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp> #include <opencv2/features2d/features2d.hpp>
#include <pcl/point_cloud.h> #include <pcl/point_cloud.h>
@@ -91,41 +92,133 @@ public:
* if a=[1 2 3 4 6], b=[1 2 4 5 6], results= [(1,1) (2,2) (4,4) (6,6)] * if a=[1 2 3 4 6], b=[1 2 4 5 6], results= [(1,1) (2,2) (4,4) (6,6)]
* realPairsCount = 4 * realPairsCount = 4
*/ */
template<typename T>
static int findPairs( static int findPairs(
const std::map<int, cv::KeyPoint> & wordsA, const std::map<int, T> & wordsA,
const std::map<int, cv::KeyPoint> & wordsB, const std::map<int, T> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true); bool ignoreNegativeIds = true)
{
int realPairsCount = 0;
pairs.clear();
for(typename std::map<int, T>::const_iterator i=wordsA.begin(); i!=wordsA.end(); ++i)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && i->first>=0))
{
std::map<int, cv::KeyPoint>::const_iterator ptB = wordsB.find(i->first);
if(ptB != wordsB.end())
{
pairs.push_back(std::pair<int, std::pair<T, T> >(i->first, std::make_pair(i->second, ptB->second)));
++realPairsCount;
}
}
}
return realPairsCount;
}
/** /**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (2,2) (4,4) (6a,6a) (6b,6b)] * if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (2,2) (4,4) (6a,6a) (6b,6b)]
* realPairsCount = 5 * realPairsCount = 5
*/ */
template<typename T>
static int findPairs( static int findPairs(
const std::multimap<int, cv::KeyPoint> & wordsA, const std::multimap<int, T> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB, const std::multimap<int, T> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true); bool ignoreNegativeIds = true)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
typename std::multimap<int, T>::const_iterator iterA;
typename std::multimap<int, T>::const_iterator iterB;
pairs.clear();
int realPairsCount = 0;
for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && *i >= 0))
{
iterA = wordsA.find(*i);
iterB = wordsB.find(*i);
while(iterA != wordsA.end() && iterB != wordsB.end() && (*iterA).first == (*iterB).first && (*iterA).first == *i)
{
pairs.push_back(std::pair<int, std::pair<T, T> >(*i, std::make_pair((*iterA).second, (*iterB).second)));
++iterA;
++iterB;
++realPairsCount;
}
}
}
return realPairsCount;
}
/** /**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(2,2) (4,4)] * if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(2,2) (4,4)]
* realPairsCount = 5 * realPairsCount = 5
*/ */
template<typename T>
static int findPairsUnique( static int findPairsUnique(
const std::multimap<int, cv::KeyPoint> & wordsA, const std::multimap<int, T> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB, const std::multimap<int, T> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true); bool ignoreNegativeIds = true)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
int realPairsCount = 0;
pairs.clear();
for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && *i>=0))
{
std::list<T> ptsA = uValues(wordsA, *i);
std::list<T> ptsB = uValues(wordsB, *i);
if(ptsA.size() == 1 && ptsB.size() == 1)
{
pairs.push_back(std::pair<int, std::pair<T, T> >(*i, std::pair<T, T>(ptsA.front(), ptsB.front())));
++realPairsCount;
}
else if(ptsA.size()>1 && ptsB.size()>1)
{
// just update the count
realPairsCount += ptsA.size() > ptsB.size() ? ptsB.size() : ptsA.size();
}
}
}
return realPairsCount;
}
/** /**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (1,1b) (2,2) (4,4) (6a,6a) (6a,6b) (6b,6a) (6b,6b)] * if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (1,1b) (2,2) (4,4) (6a,6a) (6a,6b) (6b,6a) (6b,6b)]
* realPairsCount = 5 * realPairsCount = 5
*/ */
template<typename T>
static int findPairsAll( static int findPairsAll(
const std::multimap<int, cv::KeyPoint> & wordsA, const std::multimap<int, T> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB, const std::multimap<int, T> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs, std::list<std::pair<int, std::pair<T, T> > > & pairs,
bool ignoreNegativeIds = true); bool ignoreNegativeIds = true)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
pairs.clear();
int realPairsCount = 0;;
for(std::list<int>::const_iterator iter=ids.begin(); iter!=ids.end(); ++iter)
{
if(!ignoreNegativeIds || (ignoreNegativeIds && *iter>=0))
{
std::list<T> ptsA = uValues(wordsA, *iter);
std::list<T> ptsB = uValues(wordsB, *iter);
realPairsCount += ptsA.size() > ptsB.size() ? ptsB.size() : ptsA.size();
for(typename std::list<T>::iterator jter=ptsA.begin(); jter!=ptsA.end(); ++jter)
{
for(typename std::list<T>::iterator kter=ptsB.begin(); kter!=ptsB.end(); ++kter)
{
pairs.push_back(std::pair<int, std::pair<T, T> >(*iter, std::pair<T, T>(*jter, *kter)));
}
}
}
}
return realPairsCount;
}
static cv::Mat linearLSTriangulation( static cv::Mat linearLSTriangulation(
cv::Point3d u, //homogenous image point (u,v,1) cv::Point3d u, //homogenous image point (u,v,1)
+3 -3
View File
@@ -43,8 +43,8 @@ public:
void release(); void release();
unsigned int indexedFeatures() const; unsigned int indexedFeatures() const;
// return KB // return Bytes
unsigned int memoryUsed() const; unsigned long memoryUsed() const;
// Note that useDistanceL1 doesn't have any effect if LSH is used // Note that useDistanceL1 doesn't have any effect if LSH is used
void buildLinearIndex( void buildLinearIndex(
@@ -74,7 +74,7 @@ public:
int featuresType() const {return featuresType_;} int featuresType() const {return featuresType_;}
int featuresDim() const {return featuresDim_;} int featuresDim() const {return featuresDim_;}
unsigned int addPoints(const cv::Mat & features); std::vector<unsigned int> addPoints(const cv::Mat & features);
void removePoint(unsigned int index); void removePoint(unsigned int index);
+10 -2
View File
@@ -155,12 +155,20 @@ std::list<Link> RTABMAP_EXP findLinks(
std::multimap<int, Link> RTABMAP_EXP filterDuplicateLinks( std::multimap<int, Link> RTABMAP_EXP filterDuplicateLinks(
const std::multimap<int, Link> & links); const std::multimap<int, Link> & links);
/**
* Return links not of type "filteredType". If inverted=true, return links of of type "filteredType".
*/
std::multimap<int, Link> RTABMAP_EXP filterLinks( std::multimap<int, Link> RTABMAP_EXP filterLinks(
const std::multimap<int, Link> & links, const std::multimap<int, Link> & links,
Link::Type filteredType); Link::Type filteredType,
bool inverted = false);
/**
* Return links not of type "filteredType". If inverted=true, return links of of type "filteredType".
*/
std::map<int, Link> RTABMAP_EXP filterLinks( std::map<int, Link> RTABMAP_EXP filterLinks(
const std::map<int, Link> & links, const std::map<int, Link> & links,
Link::Type filteredType); Link::Type filteredType,
bool inverted = false);
//Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right. //Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right.
std::map<int, Transform> RTABMAP_EXP frustumPosesFiltering( std::map<int, Transform> RTABMAP_EXP frustumPosesFiltering(
+5 -3
View File
@@ -199,9 +199,10 @@ public:
cv::Mat getImageCompressed(int signatureId) const; cv::Mat getImageCompressed(int signatureId) const;
SensorData getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const; SensorData getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const;
void getNodeWordsAndGlobalDescriptors(int nodeId, void getNodeWordsAndGlobalDescriptors(int nodeId,
std::multimap<int, cv::KeyPoint> & words, std::multimap<int, int> & words,
std::multimap<int, cv::Point3f> & words3, std::vector<cv::KeyPoint> & wordsKpts,
std::multimap<int, cv::Mat> & wordsDescriptors, std::vector<cv::Point3f> & words3,
cv::Mat & wordsDescriptors,
std::vector<GlobalDescriptor> & globalDescriptors) const; std::vector<GlobalDescriptor> & globalDescriptors) const;
void getNodeCalibration(int nodeId, void getNodeCalibration(int nodeId,
std::vector<CameraModel> & models, std::vector<CameraModel> & models,
@@ -225,6 +226,7 @@ public:
virtual void dumpMemory(std::string directory) const; virtual void dumpMemory(std::string directory) const;
virtual void dumpSignatures(const char * fileNameSign, bool words3D) const; virtual void dumpSignatures(const char * fileNameSign, bool words3D) const;
void dumpDictionary(const char * fileNameRef, const char * fileNameDesc) const; void dumpDictionary(const char * fileNameRef, const char * fileNameDesc) const;
unsigned long getMemoryUsed() const; //Bytes
void generateGraph(const std::string & fileName, const std::set<int> & ids = std::set<int>()); void generateGraph(const std::string & fileName, const std::set<int> & ids = std::set<int>());
@@ -104,6 +104,8 @@ public:
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapObstacles() const {return assembledObstacles_;} const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapObstacles() const {return assembledObstacles_;}
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapEmptyCells() const {return assembledEmptyCells_;} const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & getMapEmptyCells() const {return assembledEmptyCells_;}
unsigned long getMemoryUsed() const;
private: private:
ParametersMap parameters_; ParametersMap parameters_;
int cloudDecimation_; int cloudDecimation_;
@@ -75,6 +75,7 @@ public:
// RegistrationVis // RegistrationVis
int inliers; int inliers;
float inliersRatio;
float inliersMeanDistance; float inliersMeanDistance;
float inliersDistribution; float inliersDistribution;
std::vector<int> inliersIDs; std::vector<int> inliersIDs;
-2
View File
@@ -136,11 +136,9 @@ public:
std::map<int, int> getWeights() const; std::map<int, int> getWeights() const;
int getTotalMemSize() const; int getTotalMemSize() const;
double getLastProcessTime() const {return _lastProcessTime;}; double getLastProcessTime() const {return _lastProcessTime;};
std::multimap<int, cv::KeyPoint> getWords(int locationId) const;
bool isInSTM(int locationId) const; bool isInSTM(int locationId) const;
bool isIDsGenerated() const; bool isIDsGenerated() const;
const Statistics & getStatistics() const; const Statistics & getStatistics() const;
//bool getMetricData(int locationId, cv::Mat & rgb, cv::Mat & depth, float & depthConstant, Transform & pose, Transform & localTransform) const;
const std::map<int, Transform> & getLocalOptimizedPoses() const {return _optimizedPoses;} const std::map<int, Transform> & getLocalOptimizedPoses() const {return _optimizedPoses;}
const std::multimap<int, Link> & getLocalConstraints() const {return _constraints;} const std::multimap<int, Link> & getLocalConstraints() const {return _constraints;}
Transform getPose(int locationId) const; Transform getPose(int locationId) const;
+1 -1
View File
@@ -275,7 +275,7 @@ public:
void setLandmarks(const Landmarks & landmarks) {_landmarks = landmarks;} void setLandmarks(const Landmarks & landmarks) {_landmarks = landmarks;}
const Landmarks & landmarks() const {return _landmarks;} const Landmarks & landmarks() const {return _landmarks;}
long getMemoryUsed() const; // Return memory usage in Bytes unsigned long getMemoryUsed() const; // Return memory usage in Bytes
/** /**
* Clear compressed rgb/depth (left/right) images, compressed laser scan and compressed user data. * Clear compressed rgb/depth (left/right) images, compressed laser scan and compressed user data.
* Raw data are kept is set. * Raw data are kept is set.
+11 -11
View File
@@ -104,19 +104,18 @@ public:
//visual words stuff //visual words stuff
void removeAllWords(); void removeAllWords();
void removeWord(int wordId);
void changeWordsRef(int oldWordId, int activeWordId); void changeWordsRef(int oldWordId, int activeWordId);
void setWords(const std::multimap<int, cv::KeyPoint> & words); void setWords(const std::multimap<int, int> & words, const std::vector<cv::KeyPoint> & keypoints, const std::vector<cv::Point3f> & words3, const cv::Mat & descriptors);
bool isEnabled() const {return _enabled;} bool isEnabled() const {return _enabled;}
void setEnabled(bool enabled) {_enabled = enabled;} void setEnabled(bool enabled) {_enabled = enabled;}
const std::multimap<int, cv::KeyPoint> & getWords() const {return _words;} const std::multimap<int, int> & getWords() const {return _words;}
const std::vector<cv::KeyPoint> & getWordsKpts() const {return _wordsKpts;}
int getInvalidWordsCount() const {return _invalidWordsCount;} int getInvalidWordsCount() const {return _invalidWordsCount;}
const std::map<int, int> & getWordsChanged() const {return _wordsChanged;} const std::map<int, int> & getWordsChanged() const {return _wordsChanged;}
const std::multimap<int, cv::Mat> & getWordsDescriptors() const {return _wordsDescriptors;} const cv::Mat & getWordsDescriptors() const {return _wordsDescriptors;}
void setWordsDescriptors(const std::multimap<int, cv::Mat> & descriptors) {_wordsDescriptors = descriptors;} void setWordsDescriptors(const cv::Mat & descriptors);
//metric stuff //metric stuff
void setWords3(const std::multimap<int, cv::Point3f> & words3) {_words3 = words3;}
void setPose(const Transform & pose) {_pose = pose;} void setPose(const Transform & pose) {_pose = pose;}
void setGroundTruthPose(const Transform & pose) {_groundTruthPose = pose;} void setGroundTruthPose(const Transform & pose) {_groundTruthPose = pose;}
void setVelocity(float vx, float vy, float vz, float vroll, float vpitch, float vyaw) { void setVelocity(float vx, float vy, float vz, float vroll, float vpitch, float vyaw) {
@@ -129,7 +128,7 @@ public:
_velocity[5]=vyaw; _velocity[5]=vyaw;
} }
const std::multimap<int, cv::Point3f> & getWords3() const {return _words3;} const std::vector<cv::Point3f> & getWords3() const {return _words3;}
const Transform & getPose() const {return _pose;} const Transform & getPose() const {return _pose;}
cv::Mat getPoseCovariance() const; cv::Mat getPoseCovariance() const;
const Transform & getGroundTruthPose() const {return _groundTruthPose;} const Transform & getGroundTruthPose() const {return _groundTruthPose;}
@@ -138,7 +137,7 @@ public:
SensorData & sensorData() {return _sensorData;} SensorData & sensorData() {return _sensorData;}
const SensorData & sensorData() const {return _sensorData;} const SensorData & sensorData() const {return _sensorData;}
long getMemoryUsed(bool withSensorData=true) const; // Return memory usage in Bytes unsigned long getMemoryUsed(bool withSensorData=true) const; // Return memory usage in Bytes
private: private:
int _id; int _id;
@@ -155,9 +154,10 @@ private:
// Contains all words (Some can be duplicates -> if a word appears 2 // Contains all words (Some can be duplicates -> if a word appears 2
// times in the signature, it will be 2 times in this list) // times in the signature, it will be 2 times in this list)
// Words match with the CvSeq keypoints and descriptors // Words match with the CvSeq keypoints and descriptors
std::multimap<int, cv::KeyPoint> _words; // word <id, keypoint> std::multimap<int, int> _words; // word <id, keypoint index>
std::multimap<int, cv::Point3f> _words3; // word <id, point> // in base_link frame (localTransform applied)) std::vector<cv::KeyPoint> _wordsKpts;
std::multimap<int, cv::Mat> _wordsDescriptors; std::vector<cv::Point3f> _words3; // in base_link frame (localTransform applied))
cv::Mat _wordsDescriptors;
std::map<int, int> _wordsChanged; // <oldId, newId> std::map<int, int> _wordsChanged; // <oldId, newId>
bool _enabled; bool _enabled;
int _invalidWordsCount; int _invalidWordsCount;
@@ -65,6 +65,7 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Loop, Map_id,); RTABMAP_STATS(Loop, Map_id,);
RTABMAP_STATS(Loop, Visual_words,); RTABMAP_STATS(Loop, Visual_words,);
RTABMAP_STATS(Loop, Visual_inliers,); RTABMAP_STATS(Loop, Visual_inliers,);
RTABMAP_STATS(Loop, Visual_inliers_ratio,);
RTABMAP_STATS(Loop, Visual_matches,); RTABMAP_STATS(Loop, Visual_matches,);
RTABMAP_STATS(Loop, Distance_since_last_loc,); RTABMAP_STATS(Loop, Distance_since_last_loc,);
RTABMAP_STATS(Loop, Last_id,); RTABMAP_STATS(Loop, Last_id,);
@@ -149,6 +150,7 @@ class RTABMAP_EXP Statistics
RTABMAP_STATS(Memory, Odometry_variance_lin,); RTABMAP_STATS(Memory, Odometry_variance_lin,);
RTABMAP_STATS(Memory, Distance_travelled, m); RTABMAP_STATS(Memory, Distance_travelled, m);
RTABMAP_STATS(Memory, RAM_usage, MB); RTABMAP_STATS(Memory, RAM_usage, MB);
RTABMAP_STATS(Memory, RAM_estimated, MB);
RTABMAP_STATS(Memory, Triangulated_points, ); RTABMAP_STATS(Memory, Triangulated_points, );
RTABMAP_STATS(Timing, Memory_update, ms); RTABMAP_STATS(Timing, Memory_update, ms);
+2 -1
View File
@@ -100,7 +100,8 @@ public:
int getLastIndexedWordId() const; int getLastIndexedWordId() const;
int getTotalActiveReferences() const {return _totalActiveReferences;} int getTotalActiveReferences() const {return _totalActiveReferences;}
unsigned int getIndexedWordsCount() const; unsigned int getIndexedWordsCount() const;
unsigned int getIndexMemoryUsed() const; unsigned int getIndexMemoryUsed() const; // KB
unsigned long getMemoryUsed(bool estimate = true) const; //Bytes
bool setNNStrategy(NNStrategy strategy); // Return true if the search tree has been re-initialized bool setNNStrategy(NNStrategy strategy); // Return true if the search tree has been re-initialized
bool isIncremental() const {return _incrementalDictionary;} bool isIncremental() const {return _incrementalDictionary;}
bool isIncrementalFlann() const {return _incrementalFlann;} bool isIncrementalFlann() const {return _incrementalFlann;}
@@ -43,6 +43,7 @@ public:
void addRef(int signatureId); void addRef(int signatureId);
int removeAllRef(int signatureId); int removeAllRef(int signatureId);
unsigned long getMemoryUsed() const;
int getTotalReferences() const {return _totalReferences;} int getTotalReferences() const {return _totalReferences;}
int id() const {return _id;} int id() const {return _id;}
+14
View File
@@ -417,6 +417,20 @@ cv::Mat BayesFilter::generatePrediction(const Memory * memory, const std::vector
return prediction; return prediction;
} }
unsigned long BayesFilter::getMemoryUsed() const
{
long memoryUsage = sizeof(BayesFilter);
memoryUsage += _posterior.size() * (sizeof(float)+sizeof(int)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, float>);
memoryUsage += _prediction.total() * _prediction.elemSize();
memoryUsage += _predictionLC.size() * sizeof(double);
memoryUsage += _neighborsIndex.size() * (sizeof(int)+sizeof(std::map<int, int>)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, std::map<int, int> >);
for(std::map<int, std::map<int, int> >::const_iterator iter=_neighborsIndex.begin(); iter!=_neighborsIndex.end(); ++iter)
{
memoryUsage += iter->second.size() * (sizeof(int)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, int>);
}
return memoryUsage;
}
void BayesFilter::normalize(cv::Mat & prediction, unsigned int index, float addedProbabilitiesSum, bool virtualPlaceUsed) const void BayesFilter::normalize(cv::Mat & prediction, unsigned int index, float addedProbabilitiesSum, bool virtualPlaceUsed) const
{ {
UASSERT(index < (unsigned int)prediction.rows && index < (unsigned int)prediction.cols); UASSERT(index < (unsigned int)prediction.rows && index < (unsigned int)prediction.cols);
+2 -2
View File
@@ -107,9 +107,9 @@ bool DBDriver::isConnected() const
} }
// In bytes // In bytes
long DBDriver::getMemoryUsed() const unsigned long DBDriver::getMemoryUsed() const
{ {
long bytes; unsigned long bytes;
_dbSafeAccessMutex.lock(); _dbSafeAccessMutex.lock();
bytes = getMemoryUsedQuery(); bytes = getMemoryUsedQuery();
_dbSafeAccessMutex.unlock(); _dbSafeAccessMutex.unlock();
+21 -25
View File
@@ -486,7 +486,7 @@ void DBDriverSqlite3::executeNoResultQuery(const std::string & sql) const
} }
} }
long DBDriverSqlite3::getMemoryUsedQuery() const unsigned long DBDriverSqlite3::getMemoryUsedQuery() const
{ {
if(_dbInMemory) if(_dbInMemory)
{ {
@@ -3079,9 +3079,10 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
const void * descriptor = 0; const void * descriptor = 0;
int dRealSize = 0; int dRealSize = 0;
cv::KeyPoint kpt; cv::KeyPoint kpt;
std::multimap<int, cv::KeyPoint> visualWords; std::multimap<int, int> visualWords;
std::multimap<int, cv::Point3f> visualWords3; std::vector<cv::KeyPoint> visualWordsKpts;
std::multimap<int, cv::Mat> descriptors; std::vector<cv::Point3f> visualWords3;
cv::Mat descriptors;
bool allWords3NaN = true; bool allWords3NaN = true;
cv::Point3f depth(0,0,0); cv::Point3f depth(0,0,0);
@@ -3131,8 +3132,9 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
depth.z = sqlite3_column_double(ppStmt, index++); depth.z = sqlite3_column_double(ppStmt, index++);
} }
visualWords.insert(visualWords.end(), std::make_pair(visualWordId, kpt)); visualWordsKpts.push_back(kpt);
visualWords3.insert(visualWords3.end(), std::make_pair(visualWordId, depth)); visualWords.insert(visualWords.end(), std::make_pair(visualWordId, visualWordsKpts.size()-1));
visualWords3.push_back(depth);
if(allWords3NaN && util3d::isFinite(depth)) if(allWords3NaN && util3d::isFinite(depth))
{ {
@@ -3165,7 +3167,7 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
memcpy(d.data, descriptor, dRealSize); memcpy(d.data, descriptor, dRealSize);
descriptors.insert(descriptors.end(), std::make_pair(visualWordId, d)); descriptors.push_back(d);
} }
} }
@@ -3179,13 +3181,12 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
} }
else else
{ {
(*iter)->setWords(visualWords); if(allWords3NaN)
if(!allWords3NaN)
{ {
(*iter)->setWords3(visualWords3); visualWords3.clear();
} }
(*iter)->setWordsDescriptors(descriptors); (*iter)->setWords(visualWords, visualWordsKpts, visualWords3, descriptors);
ULOGGER_DEBUG("Add %d keypoints, %d 3d points and %d descriptors to node %d", (int)visualWords.size(), allWords3NaN?0:(int)visualWords3.size(), (int)descriptors.size(), (*iter)->id()); ULOGGER_DEBUG("Add %d keypoints, %d 3d points and %d descriptors to node %d", (int)visualWords.size(), allWords3NaN?0:(int)visualWords3.size(), (int)descriptors.rows, (*iter)->id());
} }
//reset //reset
@@ -4275,30 +4276,25 @@ void DBDriverSqlite3::saveQuery(const std::list<Signature *> & signatures)
float nanFloat = std::numeric_limits<float>::quiet_NaN (); float nanFloat = std::numeric_limits<float>::quiet_NaN ();
for(std::list<Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i) for(std::list<Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
{ {
UASSERT((*i)->getWords().size() == (*i)->getWordsKpts().size());
UASSERT((*i)->getWords3().empty() || (*i)->getWords().size() == (*i)->getWords3().size()); UASSERT((*i)->getWords3().empty() || (*i)->getWords().size() == (*i)->getWords3().size());
UASSERT((*i)->getWordsDescriptors().empty() || (*i)->getWords().size() == (*i)->getWordsDescriptors().size()); UASSERT((*i)->getWordsDescriptors().empty() || (int)(*i)->getWords().size() == (*i)->getWordsDescriptors().rows);
std::multimap<int, cv::Point3f>::const_iterator p=(*i)->getWords3().begin(); for(std::multimap<int, int>::const_iterator w=(*i)->getWords().begin(); w!=(*i)->getWords().end(); ++w)
std::multimap<int, cv::Mat>::const_iterator d=(*i)->getWordsDescriptors().begin();
for(std::multimap<int, cv::KeyPoint>::const_iterator w=(*i)->getWords().begin(); w!=(*i)->getWords().end(); ++w)
{ {
cv::Point3f pt(nanFloat,nanFloat,nanFloat); cv::Point3f pt(nanFloat,nanFloat,nanFloat);
if(p!=(*i)->getWords3().end()) if(!(*i)->getWords3().empty())
{ {
UASSERT(w->first == p->first); // must be same id! pt = (*i)->getWords3()[w->second];
pt = p->second;
++p;
} }
cv::Mat descriptor; cv::Mat descriptor;
if(d!=(*i)->getWordsDescriptors().end()) if(!(*i)->getWordsDescriptors().empty())
{ {
UASSERT(w->first == d->first); // must be same id! descriptor = (*i)->getWordsDescriptors().row(w->second);
descriptor = d->second;
++d;
} }
stepKeypoint(ppStmt, (*i)->id(), w->first, w->second, pt, descriptor); stepKeypoint(ppStmt, (*i)->id(), w->first, (*i)->getWordsKpts()[w->second], pt, descriptor);
} }
} }
// Finalize (delete) the statement // Finalize (delete) the statement
+3 -17
View File
@@ -510,23 +510,9 @@ SensorData DBReader::getNextData(CameraInfo * info)
data.gps().stamp()!=0.0?1:0, data.gps().stamp()!=0.0?1:0,
gravityTransform.isNull()?0:1); gravityTransform.isNull()?0:1);
cv::Mat descriptors; cv::Mat descriptors = s->getWordsDescriptors().clone();
if(!s->getWordsDescriptors().empty()) const std::vector<cv::KeyPoint> & keypoints = s->getWordsKpts();
{ const std::vector<cv::Point3f> & keypoints3D = s->getWords3();
descriptors = cv::Mat(
s->getWordsDescriptors().size(),
s->getWordsDescriptors().begin()->second.cols,
s->getWordsDescriptors().begin()->second.type());
int i=0;
for(std::multimap<int, cv::Mat>::const_iterator iter=s->getWordsDescriptors().begin();
iter!=s->getWordsDescriptors().end();
++iter, ++i)
{
iter->second.copyTo(descriptors.row(i));
}
}
std::vector<cv::KeyPoint> keypoints = uValues(s->getWords());
std::vector<cv::Point3f> keypoints3D = uValues(s->getWords3());
if(!keypoints.empty() && if(!keypoints.empty() &&
(keypoints3D.empty() || keypoints.size() == keypoints3D.size()) && (keypoints3D.empty() || keypoints.size() == keypoints3D.size()) &&
(descriptors.empty() || (int)keypoints.size() == descriptors.rows)) (descriptors.empty() || (int)keypoints.size() == descriptors.rows))
+9 -133
View File
@@ -70,15 +70,21 @@ bool EpipolarGeometry::check(const Signature * ssA, const Signature * ssB)
} }
ULOGGER_DEBUG("id(%d,%d)", ssA->id(), ssB->id()); ULOGGER_DEBUG("id(%d,%d)", ssA->id(), ssB->id());
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > pairs; std::list<std::pair<int, std::pair<int, int> > > pairsId;
findPairsUnique(ssA->getWords(), ssB->getWords(), pairs); findPairsUnique(ssA->getWords(), ssB->getWords(), pairsId);
if((int)pairs.size()<_matchCountMinAccepted) if((int)pairsId.size()<_matchCountMinAccepted)
{ {
return false; return false;
} }
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > pairs;
for(std::list<std::pair<int, std::pair<int, int> > >::iterator iter = pairsId.begin(); iter!=pairsId.end(); ++iter)
{
pairs.push_back(std::make_pair(iter->first, std::make_pair(ssA->getWordsKpts()[iter->second.first], ssB->getWordsKpts()[iter->second.second])));
}
std::vector<uchar> status; std::vector<uchar> status;
cv::Mat f = findFFromWords(pairs, status, _ransacParam1, _ransacParam2); cv::Mat f = findFFromWords(pairs, status, _ransacParam1, _ransacParam2);
@@ -406,136 +412,6 @@ cv::Mat EpipolarGeometry::findFFromCalibratedStereoCameras(double fx, double fy,
return K.inv().t()*E*K.inv(); return K.inv().t()*E*K.inv();
} }
/**
* if a=[1 2 3 4 6], b=[1 2 4 5 6], results= [(1,1) (2,2) (4,4) (6,6)]
* realPairsCount = 4
*/
int EpipolarGeometry::findPairs(
const std::map<int, cv::KeyPoint> & wordsA,
const std::map<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreInvalidIds)
{
int realPairsCount = 0;
pairs.clear();
for(std::map<int, cv::KeyPoint>::const_iterator i=wordsA.begin(); i!=wordsA.end(); ++i)
{
if(!ignoreInvalidIds || (ignoreInvalidIds && i->first>=0))
{
std::map<int, cv::KeyPoint>::const_iterator ptB = wordsB.find(i->first);
if(ptB != wordsB.end())
{
pairs.push_back(std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> >(i->first, std::pair<cv::KeyPoint, cv::KeyPoint>(i->second, ptB->second)));
++realPairsCount;
}
}
}
return realPairsCount;
}
/**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (2,2) (4,4) (6a,6a) (6b,6b)]
* realPairsCount = 5
*/
int EpipolarGeometry::findPairs(const std::multimap<int, cv::KeyPoint> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreInvalidIds)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
std::multimap<int, cv::KeyPoint>::const_iterator iterA;
std::multimap<int, cv::KeyPoint>::const_iterator iterB;
pairs.clear();
int realPairsCount = 0;
for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
{
if(!ignoreInvalidIds || (ignoreInvalidIds && *i >= 0))
{
iterA = wordsA.find(*i);
iterB = wordsB.find(*i);
while(iterA != wordsA.end() && iterB != wordsB.end() && (*iterA).first == (*iterB).first && (*iterA).first == *i)
{
pairs.push_back(std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> >(*i, std::pair<cv::KeyPoint, cv::KeyPoint>((*iterA).second, (*iterB).second)));
++iterA;
++iterB;
++realPairsCount;
}
}
}
return realPairsCount;
}
/**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(2,2) (4,4)]
* realPairsCount = 5
*/
int EpipolarGeometry::findPairsUnique(
const std::multimap<int, cv::KeyPoint> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreInvalidIds)
{
const std::list<int> & ids = uUniqueKeys(wordsA);
int realPairsCount = 0;
pairs.clear();
for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
{
if(!ignoreInvalidIds || (ignoreInvalidIds && *i>=0))
{
std::list<cv::KeyPoint> ptsA = uValues(wordsA, *i);
std::list<cv::KeyPoint> ptsB = uValues(wordsB, *i);
if(ptsA.size() == 1 && ptsB.size() == 1)
{
pairs.push_back(std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> >(*i, std::pair<cv::KeyPoint, cv::KeyPoint>(ptsA.front(), ptsB.front())));
++realPairsCount;
}
else if(ptsA.size()>1 && ptsB.size()>1)
{
// just update the count
realPairsCount += ptsA.size() > ptsB.size() ? ptsB.size() : ptsA.size();
}
}
}
return realPairsCount;
}
/**
* if a=[1 2 3 4 6 6], b=[1 1 2 4 5 6 6], results= [(1,1a) (1,1b) (2,2) (4,4) (6a,6a) (6a,6b) (6b,6a) (6b,6b)]
* realPairsCount = 5
*/
int EpipolarGeometry::findPairsAll(const std::multimap<int, cv::KeyPoint> & wordsA,
const std::multimap<int, cv::KeyPoint> & wordsB,
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > & pairs,
bool ignoreInvalidIds)
{
UTimer timer;
timer.start();
const std::list<int> & ids = uUniqueKeys(wordsA);
pairs.clear();
int realPairsCount = 0;;
for(std::list<int>::const_iterator iter=ids.begin(); iter!=ids.end(); ++iter)
{
if(!ignoreInvalidIds || (ignoreInvalidIds && *iter>=0))
{
std::list<cv::KeyPoint> ptsA = uValues(wordsA, *iter);
std::list<cv::KeyPoint> ptsB = uValues(wordsB, *iter);
realPairsCount += ptsA.size() > ptsB.size() ? ptsB.size() : ptsA.size();
for(std::list<cv::KeyPoint>::iterator jter=ptsA.begin(); jter!=ptsA.end(); ++jter)
{
for(std::list<cv::KeyPoint>::iterator kter=ptsB.begin(); kter!=ptsB.end(); ++kter)
{
pairs.push_back(std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> >(*iter, std::pair<cv::KeyPoint, cv::KeyPoint>(*jter, *kter)));
}
}
}
}
ULOGGER_DEBUG("time = %f", timer.ticks());
return realPairsCount;
}
/** /**
source = SfM toy library: https://github.com/royshil/SfM-Toy-Library source = SfM toy library: https://github.com/royshil/SfM-Toy-Library
+77 -24
View File
@@ -107,32 +107,36 @@ unsigned int FlannIndex::indexedFeatures() const
} }
} }
// return KB // return Bytes
unsigned int FlannIndex::memoryUsed() const unsigned long FlannIndex::memoryUsed() const
{ {
if(!index_) if(!index_)
{ {
return 0; return 0;
} }
unsigned long memoryUsage = sizeof(FlannIndex);
memoryUsage += addedDescriptors_.size() * (sizeof(int) + sizeof(cv::Mat) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, cv::Mat>);
memoryUsage += sizeof(std::list<int>) + removedIndexes_.size() * sizeof(int);
if(featuresType_ == CV_8UC1) if(featuresType_ == CV_8UC1)
{ {
return ((const rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->usedMemory()/1000; memoryUsage += ((const rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->usedMemory();
} }
else else
{ {
if(useDistanceL1_) if(useDistanceL1_)
{ {
return ((const rtflann::Index<rtflann::L1<float> >*)index_)->usedMemory()/1000; memoryUsage += ((const rtflann::Index<rtflann::L1<float> >*)index_)->usedMemory();
} }
else if(featuresDim_ <= 3) else if(featuresDim_ <= 3)
{ {
return ((const rtflann::Index<rtflann::L2_Simple<float> >*)index_)->usedMemory()/1000; memoryUsage += ((const rtflann::Index<rtflann::L2_Simple<float> >*)index_)->usedMemory();
} }
else else
{ {
return ((const rtflann::Index<rtflann::L2<float> >*)index_)->usedMemory()/1000; memoryUsage += ((const rtflann::Index<rtflann::L2<float> >*)index_)->usedMemory();
} }
} }
return memoryUsage;
} }
void FlannIndex::buildLinearIndex( void FlannIndex::buildLinearIndex(
@@ -177,10 +181,21 @@ void FlannIndex::buildLinearIndex(
} }
} }
// incremental FLANN // incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated)
if(rebalancingFactor_ > 1.0f)
{
for(int i=0; i<features.rows; ++i)
{
addedDescriptors_.insert(std::make_pair(nextIndex_++, features.row(i)));
}
}
else
{
// tree won't ever be rebalanced, so just keep only one header for the data
addedDescriptors_.insert(std::make_pair(nextIndex_, features)); addedDescriptors_.insert(std::make_pair(nextIndex_, features));
nextIndex_ += features.rows;
nextIndex_ = features.rows; }
UDEBUG(""); UDEBUG("");
} }
@@ -227,10 +242,21 @@ void FlannIndex::buildKDTreeIndex(
} }
} }
// incremental FLANN // incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated)
if(rebalancingFactor_ > 1.0f)
{
for(int i=0; i<features.rows; ++i)
{
addedDescriptors_.insert(std::make_pair(nextIndex_++, features.row(i)));
}
}
else
{
// tree won't ever be rebalanced, so just keep only one header for the data
addedDescriptors_.insert(std::make_pair(nextIndex_, features)); addedDescriptors_.insert(std::make_pair(nextIndex_, features));
nextIndex_ += features.rows;
nextIndex_ = features.rows; }
UDEBUG(""); UDEBUG("");
} }
@@ -278,10 +304,21 @@ void FlannIndex::buildKDTreeSingleIndex(
} }
} }
// incremental FLANN // incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated)
if(rebalancingFactor_ > 1.0f)
{
for(int i=0; i<features.rows; ++i)
{
addedDescriptors_.insert(std::make_pair(nextIndex_++, features.row(i)));
}
}
else
{
// tree won't ever be rebalanced, so just keep only one header for the data
addedDescriptors_.insert(std::make_pair(nextIndex_, features)); addedDescriptors_.insert(std::make_pair(nextIndex_, features));
nextIndex_ += features.rows;
nextIndex_ = features.rows; }
UDEBUG(""); UDEBUG("");
} }
@@ -305,10 +342,21 @@ void FlannIndex::buildLSHIndex(
index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, rtflann::LshIndexParams(12, 20, 2)); index_ = new rtflann::Index<rtflann::Hamming<unsigned char> >(dataset, rtflann::LshIndexParams(12, 20, 2));
((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->buildIndex(); ((rtflann::Index<rtflann::Hamming<unsigned char> >*)index_)->buildIndex();
// incremental FLANN // incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated)
if(rebalancingFactor_ > 1.0f)
{
for(int i=0; i<features.rows; ++i)
{
addedDescriptors_.insert(std::make_pair(nextIndex_++, features.row(i)));
}
}
else
{
// tree won't ever be rebalanced, so just keep only one header for the data
addedDescriptors_.insert(std::make_pair(nextIndex_, features)); addedDescriptors_.insert(std::make_pair(nextIndex_, features));
nextIndex_ += features.rows;
nextIndex_ = features.rows; }
UDEBUG(""); UDEBUG("");
} }
@@ -317,12 +365,12 @@ bool FlannIndex::isBuilt()
return index_!=0; return index_!=0;
} }
unsigned int FlannIndex::addPoints(const cv::Mat & features) std::vector<unsigned int> FlannIndex::addPoints(const cv::Mat & features)
{ {
if(!index_) if(!index_)
{ {
UERROR("Flann index not yet created!"); UERROR("Flann index not yet created!");
return 0; return std::vector<unsigned int>();
} }
UASSERT(features.type() == featuresType_); UASSERT(features.type() == featuresType_);
UASSERT(features.cols == featuresDim_); UASSERT(features.cols == featuresDim_);
@@ -401,11 +449,16 @@ unsigned int FlannIndex::addPoints(const cv::Mat & features)
removedIndexes_.clear(); removedIndexes_.clear();
} }
addedDescriptors_.insert(std::make_pair(nextIndex_, features)); // incremental FLANN: we should add all headers separately in case we remove
// some indexes (to keep underlying matrix data allocated)
std::vector<unsigned int> indexes;
for(int i=0; i<features.rows; ++i)
{
indexes.push_back(nextIndex_);
addedDescriptors_.insert(std::make_pair(nextIndex_++, features.row(i)));
}
int r = nextIndex_; return indexes;
nextIndex_ += features.rows;
return r;
} }
void FlannIndex::removePoint(unsigned int index) void FlannIndex::removePoint(unsigned int index)
+12 -6
View File
@@ -1129,19 +1129,22 @@ std::multimap<int, Link> filterDuplicateLinks(
std::multimap<int, Link> filterLinks( std::multimap<int, Link> filterLinks(
const std::multimap<int, Link> & links, const std::multimap<int, Link> & links,
Link::Type filteredType) Link::Type filteredType,
bool inverted)
{ {
std::multimap<int, Link> output; std::multimap<int, Link> output;
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter) for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
{ {
if(filteredType == Link::kSelfRefLink) if(filteredType == Link::kSelfRefLink)
{ {
if(iter->second.from() != iter->second.to()) if((!inverted && iter->second.from() != iter->second.to())||
(inverted && iter->second.from() == iter->second.to()))
{ {
output.insert(*iter); output.insert(*iter);
} }
} }
else if(iter->second.type() != filteredType) else if((!inverted && iter->second.type() != filteredType)||
(inverted && iter->second.type() == filteredType))
{ {
output.insert(*iter); output.insert(*iter);
} }
@@ -1151,19 +1154,22 @@ std::multimap<int, Link> filterLinks(
std::map<int, Link> filterLinks( std::map<int, Link> filterLinks(
const std::map<int, Link> & links, const std::map<int, Link> & links,
Link::Type filteredType) Link::Type filteredType,
bool inverted)
{ {
std::map<int, Link> output; std::map<int, Link> output;
for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter) for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
{ {
if(filteredType == Link::kSelfRefLink) if(filteredType == Link::kSelfRefLink)
{ {
if(iter->second.from() != iter->second.to()) if((!inverted && iter->second.from() != iter->second.to())||
(inverted && iter->second.from() == iter->second.to()))
{ {
output.insert(*iter); output.insert(*iter);
} }
} }
else if(iter->second.type() != filteredType) else if((!inverted && iter->second.type() != filteredType)||
(inverted && iter->second.type() == filteredType))
{ {
output.insert(*iter); output.insert(*iter);
} }
+170 -88
View File
@@ -362,7 +362,7 @@ void Memory::loadDataFromDb(bool postInitClosingEvents)
const std::map<int, Signature *> & signatures = this->getSignatures(); const std::map<int, Signature *> & signatures = this->getSignatures();
for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i) for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
{ {
const std::multimap<int, cv::KeyPoint> & words = i->second->getWords(); const std::multimap<int, int> & words = i->second->getWords();
std::list<int> keys = uUniqueKeys(words); std::list<int> keys = uUniqueKeys(words);
for(std::list<int>::iterator iter=keys.begin(); iter!=keys.end(); ++iter) for(std::list<int>::iterator iter=keys.begin(); iter!=keys.end(); ++iter)
{ {
@@ -413,11 +413,11 @@ void Memory::loadDataFromDb(bool postInitClosingEvents)
Signature * s = this->_getSignature(i->first); Signature * s = this->_getSignature(i->first);
UASSERT(s != 0); UASSERT(s != 0);
const std::multimap<int, cv::KeyPoint> & words = s->getWords(); const std::multimap<int, int> & words = s->getWords();
if(words.size()) if(words.size())
{ {
UDEBUG("node=%d, word references=%d", s->id(), words.size()); UDEBUG("node=%d, word references=%d", s->id(), words.size());
for(std::multimap<int, cv::KeyPoint>::const_iterator iter = words.begin(); iter!=words.end(); ++iter) for(std::multimap<int, int>::const_iterator iter = words.begin(); iter!=words.end(); ++iter)
{ {
if(iter->first > 0) if(iter->first > 0)
{ {
@@ -2753,20 +2753,16 @@ Transform Memory::computeTransform(
if(_reextractLoopClosureFeatures && _registrationPipeline->isImageRequired()) if(_reextractLoopClosureFeatures && _registrationPipeline->isImageRequired())
{ {
UDEBUG(""); UDEBUG("");
tmpFrom.setWords(std::multimap<int, cv::KeyPoint>()); tmpFrom.removeAllWords();
tmpFrom.setWords3(std::multimap<int, cv::Point3f>());
tmpFrom.setWordsDescriptors(std::multimap<int, cv::Mat>());
tmpFrom.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); tmpFrom.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
tmpTo.setWords(std::multimap<int, cv::KeyPoint>()); tmpTo.removeAllWords();
tmpTo.setWords3(std::multimap<int, cv::Point3f>());
tmpTo.setWordsDescriptors(std::multimap<int, cv::Mat>());
tmpTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); tmpTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
} }
else if(useKnownCorrespondencesIfPossible) else if(useKnownCorrespondencesIfPossible)
{ {
// This will make RegistrationVis bypassing the correspondences computation // This will make RegistrationVis bypassing the correspondences computation
tmpFrom.setWordsDescriptors(std::multimap<int, cv::Mat>()); tmpFrom.setWordsDescriptors(cv::Mat());
tmpTo.setWordsDescriptors(std::multimap<int, cv::Mat>()); tmpTo.setWordsDescriptors(cv::Mat());
} }
bool isNeighborRefining = fromS.getLinks().find(toS.id()) != fromS.getLinks().end() && fromS.getLinks().find(toS.id())->second.type() == Link::kNeighbor; bool isNeighborRefining = fromS.getLinks().find(toS.id()) != fromS.getLinks().end() && fromS.getLinks().find(toS.id())->second.type() == Link::kNeighbor;
@@ -2795,23 +2791,28 @@ Transform Memory::computeTransform(
!tmpTo.getWords().empty() && !tmpTo.getWords().empty() &&
!tmpFrom.getWordsDescriptors().empty() && !tmpFrom.getWordsDescriptors().empty() &&
!tmpFrom.getWords().empty() && !tmpFrom.getWords().empty() &&
!tmpFrom.getWords3().empty()) !tmpFrom.getWords3().empty() &&
fromS.hasLink(0, Link::kNeighbor)) // If doesn't have neighbors, skip bundle
{ {
std::multimap<int, cv::Point3f> words3DMap; std::multimap<int, int> words;
std::multimap<int, cv::KeyPoint> wordsMap; std::vector<cv::Point3f> words3DMap;
std::multimap<int, cv::Mat> wordsDescriptorsMap; std::vector<cv::KeyPoint> wordsMap;
cv::Mat wordsDescriptorsMap;
const std::multimap<int, Link> & links = fromS.getLinks(); const std::multimap<int, Link> & links = fromS.getLinks();
if(!fromS.getWords3().empty())
{ {
const std::map<int, cv::Point3f> & words3 = uMultimapToMapUnique(fromS.getWords3()); const std::map<int, int> & wordsFrom = uMultimapToMapUnique(fromS.getWords());
UDEBUG("fromS.getWords3()=%d uniques=%d", (int)fromS.getWords3().size(), (int)words3.size()); UDEBUG("fromS.getWords()=%d uniques=%d", (int)fromS.getWords().size(), (int)wordsFrom.size());
for(std::map<int, cv::Point3f>::const_iterator jter=words3.begin(); jter!=words3.end(); ++jter) for(std::map<int, int>::const_iterator jter=wordsFrom.begin(); jter!=wordsFrom.end(); ++jter)
{ {
if(util3d::isFinite(jter->second)) const cv::Point3f & pt = fromS.getWords3()[jter->second];
if(util3d::isFinite(pt))
{ {
words3DMap.insert(*jter); words.insert(std::make_pair(jter->first, words.size()));
wordsMap.insert(*fromS.getWords().find(jter->first)); words3DMap.push_back(pt);
wordsDescriptorsMap.insert(*fromS.getWordsDescriptors().find(jter->first)); wordsMap.push_back(fromS.getWordsKpts()[jter->second]);
wordsDescriptorsMap.push_back(fromS.getWordsDescriptors().row(jter->second));
} }
} }
} }
@@ -2820,21 +2821,23 @@ Transform Memory::computeTransform(
for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter) for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
{ {
int id = iter->first; int id = iter->first;
if(id != fromS.id()) if(id != fromS.id() && iter->second.type() == Link::kNeighbor) // assemble only neighbors for the local feature map
{ {
const Signature * s = this->getSignature(id); const Signature * s = this->getSignature(id);
if(s) if(s && !s->getWords3().empty())
{ {
const std::map<int, cv::Point3f> & words3 = uMultimapToMapUnique(s->getWords3()); const std::map<int, int> & wordsTo = uMultimapToMapUnique(s->getWords());
for(std::map<int, cv::Point3f>::const_iterator jter=words3.begin(); jter!=words3.end(); ++jter) for(std::map<int, int>::const_iterator jter=wordsTo.begin(); jter!=wordsTo.end(); ++jter)
{ {
const cv::Point3f & pt = s->getWords3()[jter->second];
if( jter->first > 0 && if( jter->first > 0 &&
util3d::isFinite(jter->second) && util3d::isFinite(pt) &&
words3DMap.find(jter->first) == words3DMap.end()) words.find(jter->first) == words.end())
{ {
words3DMap.insert(std::make_pair(jter->first, util3d::transformPoint(jter->second, iter->second.transform()))); words.insert(words.end(), std::make_pair(jter->first, words.size()));
wordsMap.insert(*s->getWords().find(jter->first)); words3DMap.push_back(util3d::transformPoint(pt, iter->second.transform()));
wordsDescriptorsMap.insert(*s->getWordsDescriptors().find(jter->first)); wordsMap.push_back(s->getWordsKpts()[jter->second]);
wordsDescriptorsMap.push_back(s->getWordsDescriptors().row(jter->second));
} }
} }
} }
@@ -2842,24 +2845,29 @@ Transform Memory::computeTransform(
} }
UDEBUG("words3DMap=%d", (int)words3DMap.size()); UDEBUG("words3DMap=%d", (int)words3DMap.size());
Signature tmpFrom2(fromS.id()); Signature tmpFrom2(fromS.id());
tmpFrom2.setWords3(words3DMap); tmpFrom2.setWords(words, wordsMap, words3DMap, wordsDescriptorsMap);
tmpFrom2.setWords(wordsMap);
tmpFrom2.setWordsDescriptors(wordsDescriptorsMap);
transform = _registrationPipeline->computeTransformationMod(tmpFrom2, tmpTo, guess, info); transform = _registrationPipeline->computeTransformationMod(tmpFrom2, tmpTo, guess, info);
if(!transform.isNull() && info) if(!transform.isNull() && info && !tmpFrom2.getWords3().empty())
{ {
std::map<int, cv::Point3f> points3DMap = uMultimapToMapUnique(tmpFrom2.getWords3()); std::map<int, cv::Point3f> points3DMap;
std::map<int, int> wordsMap = uMultimapToMapUnique(tmpFrom2.getWords());
for(std::map<int, int>::iterator iter=wordsMap.begin(); iter!=wordsMap.end(); ++iter)
{
points3DMap.insert(std::make_pair(iter->first, tmpFrom2.getWords3()[iter->second]));
}
std::map<int, Transform> bundlePoses; std::map<int, Transform> bundlePoses;
std::multimap<int, Link> bundleLinks; std::multimap<int, Link> bundleLinks;
std::map<int, CameraModel> bundleModels; std::map<int, CameraModel> bundleModels;
std::map<int, std::map<int, FeatureBA> > wordReferences; std::map<int, std::map<int, FeatureBA> > wordReferences;
std::multimap<int, Link> links = fromS.getLinks(); std::multimap<int, Link> links = fromS.getLinks();
links = graph::filterLinks(links, Link::kNeighbor, true); // assemble only neighbors for the local feature map
links.insert(std::make_pair(toS.id(), Link(fromS.id(), toS.id(), Link::kGlobalClosure, transform, info->covariance.inv()))); links.insert(std::make_pair(toS.id(), Link(fromS.id(), toS.id(), Link::kGlobalClosure, transform, info->covariance.inv())));
links.insert(std::make_pair(fromS.id(), Link())); links.insert(std::make_pair(fromS.id(), Link()));
int totalWordReferences = 0;
for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter) for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
{ {
int id = iter->first; int id = iter->first;
@@ -2912,33 +2920,41 @@ Transform Memory::computeTransform(
bundlePoses.insert(std::make_pair(id, iter->second.transform())); bundlePoses.insert(std::make_pair(id, iter->second.transform()));
} }
const std::map<int,cv::KeyPoint> & words = uMultimapToMapUnique(s->getWords()); const std::map<int,int> & words = uMultimapToMapUnique(s->getWords());
for(std::map<int, cv::KeyPoint>::const_iterator jter=words.begin(); jter!=words.end(); ++jter) for(std::map<int, int>::const_iterator jter=words.begin(); jter!=words.end(); ++jter)
{ {
if(points3DMap.find(jter->first)!=points3DMap.end() && if(points3DMap.find(jter->first)!=points3DMap.end() &&
(id == tmpTo.id() || jter->first > 0)) (id == tmpTo.id() || jter->first > 0)) // Since we added negative words of "from", only accept matches with current frame
{ {
std::multimap<int, cv::Point3f>::const_iterator kter = s->getWords3().find(jter->first); //get depth
cv::Point3f pt3d = util3d::transformPoint(kter->second, invLocalTransform); float d = 0.0f;
if( !s->getWords3().empty() &&
util3d::isFinite(s->getWords3()[jter->second]))
{
//move back point in camera frame (to get depth along z)
d = util3d::transformPoint(s->getWords3()[jter->second], invLocalTransform).z;
}
wordReferences.insert(std::make_pair(jter->first, std::map<int, FeatureBA>())); wordReferences.insert(std::make_pair(jter->first, std::map<int, FeatureBA>()));
wordReferences.at(jter->first).insert(std::make_pair(id, FeatureBA(jter->second, pt3d.z))); wordReferences.at(jter->first).insert(std::make_pair(id, FeatureBA(s->getWordsKpts()[jter->second], d)));
++totalWordReferences;
} }
} }
} }
} }
} }
UDEBUG("sba...start"); UDEBUG("sba...start");
// set root negative to fix all other poses // set root negative to fix all other poses
std::set<int> sbaOutliers; std::set<int> sbaOutliers;
UTimer bundleTimer; UTimer bundleTimer;
OptimizerG2O sba; OptimizerG2O sba(parameters_);
sba.setIterations(5); sba.setIterations(5);
UTimer bundleTime; UTimer bundleTime;
bundlePoses = sba.optimizeBA(-toS.id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers); bundlePoses = sba.optimizeBA(-toS.id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers);
UDEBUG("sba...end"); UDEBUG("sba...end");
UDEBUG("bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime.ticks(), (int)bundlePoses.size(), (int)wordReferences.size(), (int)sbaOutliers.size()); UDEBUG("bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime.ticks(), (int)bundlePoses.size(), totalWordReferences, (int)sbaOutliers.size());
UDEBUG("Local Bundle Adjustment Before: %s", transform.prettyPrint().c_str()); UDEBUG("Local Bundle Adjustment Before: %s", transform.prettyPrint().c_str());
if(!bundlePoses.rbegin()->second.isNull()) if(!bundlePoses.rbegin()->second.isNull())
@@ -3406,21 +3422,25 @@ void Memory::dumpSignatures(const char * fileNameSign, bool words3D) const
{ {
if(words3D) if(words3D)
{ {
const std::multimap<int, cv::Point3f> & ref = ss->getWords3(); if(!ss->getWords3().empty())
for(std::multimap<int, cv::Point3f>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
{ {
const std::multimap<int, int> & ref = ss->getWords();
for(std::multimap<int, int>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
{
const cv::Point3f & pt = ss->getWords3()[jter->second];
//show only valid point according to current parameters //show only valid point according to current parameters
if(pcl::isFinite(jter->second) && if(pcl::isFinite(pt) &&
(jter->second.x != 0 || jter->second.y != 0 || jter->second.z != 0)) (pt.x != 0 || pt.y != 0 || pt.z != 0))
{ {
fprintf(foutSign, "%d ", (*jter).first); fprintf(foutSign, "%d ", (*jter).first);
} }
} }
} }
}
else else
{ {
const std::multimap<int, cv::KeyPoint> & ref = ss->getWords(); const std::multimap<int, int> & ref = ss->getWords();
for(std::multimap<int, cv::KeyPoint>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter) for(std::multimap<int, int>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
{ {
fprintf(foutSign, "%d ", (*jter).first); fprintf(foutSign, "%d ", (*jter).first);
} }
@@ -3490,6 +3510,47 @@ void Memory::dumpMemoryTree(const char * fileNameTree) const
} }
unsigned long Memory::getMemoryUsed() const
{
unsigned long memoryUsage = sizeof(Memory);
memoryUsage += _signatures.size() * (sizeof(int)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, Signature *>);
for(std::map<int, Signature*>::const_iterator iter=_signatures.begin(); iter!=_signatures.end(); ++iter)
{
memoryUsage += iter->second->getMemoryUsed(true);
}
if(_vwd)
{
memoryUsage += _vwd->getMemoryUsed();
}
memoryUsage += _stMem.size() * (sizeof(int)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::set<int>);
memoryUsage += _workingMem.size() * (sizeof(int)+sizeof(double)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, double>);
memoryUsage += _groundTruths.size() * (sizeof(int)+sizeof(Transform)+12*sizeof(float) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, Transform>);
memoryUsage += _labels.size() * (sizeof(int)+sizeof(std::string) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, std::string>);
for(std::map<int, std::string>::const_iterator iter=_labels.begin(); iter!=_labels.end(); ++iter)
{
memoryUsage+=iter->second.size();
}
memoryUsage += _landmarksIndex.size() * (sizeof(int)+sizeof(std::set<int>) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, std::set<int> >);
memoryUsage += _landmarksInvertedIndex.size() * (sizeof(int)+sizeof(std::set<int>) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, std::set<int> >);
for(std::map<int, std::set<int>>::const_iterator iter=_landmarksIndex.begin(); iter!=_landmarksIndex.end(); ++iter)
{
memoryUsage+=iter->second.size()*(sizeof(int)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::set<int>);
}
for(std::map<int, std::set<int>>::const_iterator iter=_landmarksInvertedIndex.begin(); iter!=_landmarksInvertedIndex.end(); ++iter)
{
memoryUsage+=iter->second.size()*(sizeof(int)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::set<int>);
}
memoryUsage += parameters_.size()*(sizeof(std::string)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(ParametersMap);
memoryUsage += sizeof(Feature2D) + _feature2D->getParameters().size()*(sizeof(std::string)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(ParametersMap);
memoryUsage += sizeof(Registration);
memoryUsage += sizeof(RegistrationIcp);
memoryUsage += _occupancy->getMemoryUsed();
memoryUsage += sizeof(MarkerDetector);
memoryUsage += sizeof(DBDriver);
return memoryUsage;
}
void Memory::rehearsal(Signature * signature, Statistics * stats) void Memory::rehearsal(Signature * signature, Statistics * stats)
{ {
UTimer timer; UTimer timer;
@@ -3881,9 +3942,10 @@ SensorData Memory::getNodeData(int locationId, bool images, bool scan, bool user
} }
void Memory::getNodeWordsAndGlobalDescriptors(int nodeId, void Memory::getNodeWordsAndGlobalDescriptors(int nodeId,
std::multimap<int, cv::KeyPoint> & words, std::multimap<int, int> & words,
std::multimap<int, cv::Point3f> & words3, std::vector<cv::KeyPoint> & wordsKpts,
std::multimap<int, cv::Mat> & wordsDescriptors, std::vector<cv::Point3f> & words3,
cv::Mat & wordsDescriptors,
std::vector<GlobalDescriptor> & globalDescriptors) const std::vector<GlobalDescriptor> & globalDescriptors) const
{ {
//UDEBUG("nodeId=%d", nodeId); //UDEBUG("nodeId=%d", nodeId);
@@ -3891,6 +3953,7 @@ void Memory::getNodeWordsAndGlobalDescriptors(int nodeId,
if(s) if(s)
{ {
words = s->getWords(); words = s->getWords();
wordsKpts = s->getWordsKpts();
words3 = s->getWords3(); words3 = s->getWords3();
wordsDescriptors = s->getWordsDescriptors(); wordsDescriptors = s->getWordsDescriptors();
globalDescriptors = s->sensorData().globalDescriptors(); globalDescriptors = s->sensorData().globalDescriptors();
@@ -3906,6 +3969,7 @@ void Memory::getNodeWordsAndGlobalDescriptors(int nodeId,
if(signatures.size()) if(signatures.size())
{ {
words = signatures.front()->getWords(); words = signatures.front()->getWords();
wordsKpts = signatures.front()->getWordsKpts();
words3 = signatures.front()->getWords3(); words3 = signatures.front()->getWords3();
wordsDescriptors = signatures.front()->getWordsDescriptors(); wordsDescriptors = signatures.front()->getWordsDescriptors();
globalDescriptors = signatures.front()->sensorData().globalDescriptors(); globalDescriptors = signatures.front()->sensorData().globalDescriptors();
@@ -3975,7 +4039,7 @@ void Memory::copyData(const Signature * from, Signature * to)
{ {
// words 2d // words 2d
this->disableWordsRef(to->id()); this->disableWordsRef(to->id());
to->setWords(from->getWords()); to->setWords(from->getWords(), from->getWordsKpts(), from->getWords3(), from->getWordsDescriptors());
std::list<int> id; std::list<int> id;
id.push_back(to->id()); id.push_back(to->id());
this->enableWordsRef(id); this->enableWordsRef(id);
@@ -3992,8 +4056,6 @@ void Memory::copyData(const Signature * from, Signature * to)
to->sensorData().setId(to->id()); to->sensorData().setId(to->id());
to->setPose(from->getPose()); to->setPose(from->getPose());
to->setWords3(from->getWords3());
to->setWordsDescriptors(from->getWordsDescriptors());
} }
else else
{ {
@@ -4649,9 +4711,10 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
UDEBUG("id %d is a bad signature", id); UDEBUG("id %d is a bad signature", id);
} }
std::multimap<int, cv::KeyPoint> words; std::multimap<int, int> words;
std::multimap<int, cv::Point3f> words3D; std::vector<cv::KeyPoint> wordsKpts;
std::multimap<int, cv::Mat> wordsDescriptors; std::vector<cv::Point3f> words3D;
cv::Mat wordsDescriptors;
int words3DValid = 0; int words3DValid = 0;
if(wordIds.size() > 0) if(wordIds.size() > 0)
{ {
@@ -4671,11 +4734,12 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
kpt.size *= decimationRatio; kpt.size *= decimationRatio;
kpt.octave += log2value; kpt.octave += log2value;
} }
words.insert(std::pair<int, cv::KeyPoint>(*iter, kpt)); words.insert(std::make_pair(*iter, words.size()));
wordsKpts.push_back(kpt);
if(keypoints3D.size()) if(keypoints3D.size())
{ {
words3D.insert(std::pair<int, cv::Point3f>(*iter, keypoints3D.at(i))); words3D.push_back(keypoints3D.at(i));
if(util3d::isFinite(keypoints3D.at(i))) if(util3d::isFinite(keypoints3D.at(i)))
{ {
++words3DValid; ++words3DValid;
@@ -4683,7 +4747,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
} }
if(_rawDescriptorsKept) if(_rawDescriptorsKept)
{ {
wordsDescriptors.insert(std::pair<int, cv::Mat>(*iter, descriptors.row(i).clone())); wordsDescriptors.push_back(descriptors.row(i));
} }
} }
} }
@@ -4803,18 +4867,32 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
Signature cpPrevious(2); Signature cpPrevious(2);
// IDs should be unique so that registration doesn't override them // IDs should be unique so that registration doesn't override them
std::map<int, cv::KeyPoint> uniqueWords = uMultimapToMapUnique(previousS->getWords()); std::map<int, int> uniqueWordsOld = uMultimapToMapUnique(previousS->getWords());
std::map<int, cv::Mat> uniqueWordsDescriptors = uMultimapToMapUnique(previousS->getWordsDescriptors()); std::vector<cv::KeyPoint> uniqueWordsKpts;
cv::Mat uniqueWordsDescriptors;
std::multimap<int, int> uniqueWords;
for(std::map<int, int>::iterator iter=uniqueWordsOld.begin(); iter!=uniqueWordsOld.end(); ++iter)
{
uniqueWords.insert(std::make_pair(iter->first, uniqueWords.size()));
uniqueWordsKpts.push_back(previousS->getWordsKpts()[iter->second]);
uniqueWordsDescriptors.push_back(previousS->getWordsDescriptors().row(iter->second));
}
cpPrevious.sensorData().setCameraModels(previousS->sensorData().cameraModels()); cpPrevious.sensorData().setCameraModels(previousS->sensorData().cameraModels());
cpPrevious.setWords(std::multimap<int, cv::KeyPoint>(uniqueWords.begin(), uniqueWords.end())); cpPrevious.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
cpPrevious.setWordsDescriptors(std::multimap<int, cv::Mat>(uniqueWordsDescriptors.begin(), uniqueWordsDescriptors.end()));
Signature cpCurrent(1); Signature cpCurrent(1);
uniqueWords = uMultimapToMapUnique(words); uniqueWordsOld = uMultimapToMapUnique(words);
uniqueWordsDescriptors = uMultimapToMapUnique(wordsDescriptors); uniqueWordsKpts.clear();
uniqueWordsDescriptors = cv::Mat();
uniqueWords.clear();
for(std::map<int, int>::iterator iter=uniqueWordsOld.begin(); iter!=uniqueWordsOld.end(); ++iter)
{
uniqueWords.insert(std::make_pair(iter->first, uniqueWords.size()));
uniqueWordsKpts.push_back(wordsKpts[iter->second]);
uniqueWordsDescriptors.push_back(wordsDescriptors.row(iter->second));
}
cpCurrent.sensorData().setCameraModels(cameraModels); cpCurrent.sensorData().setCameraModels(cameraModels);
// This will force comparing descriptors between both images directly // This will force comparing descriptors between both images directly
cpCurrent.setWords(std::multimap<int, cv::KeyPoint>(uniqueWords.begin(), uniqueWords.end())); cpCurrent.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
cpCurrent.setWordsDescriptors(std::multimap<int, cv::Mat>(uniqueWordsDescriptors.begin(), uniqueWordsDescriptors.end()));
// The following is used only to re-estimate the correspondences, the returned transform is ignored // The following is used only to re-estimate the correspondences, the returned transform is ignored
Transform tmpt; Transform tmpt;
@@ -4832,9 +4910,21 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
UDEBUG("t=%s", tmpt.prettyPrint().c_str()); UDEBUG("t=%s", tmpt.prettyPrint().c_str());
// compute 3D words by epipolar geometry with the previous signature using odometry motion // compute 3D words by epipolar geometry with the previous signature using odometry motion
std::map<int, int> currentUniqueWords = uMultimapToMapUnique(cpCurrent.getWords());
std::map<int, int> previousUniqueWords = uMultimapToMapUnique(cpPrevious.getWords());
std::map<int, cv::KeyPoint> currentWords;
std::map<int, cv::KeyPoint> previousWords;
for(std::map<int, int>::iterator iter=currentUniqueWords.begin(); iter!=currentUniqueWords.end(); ++iter)
{
currentWords.insert(std::make_pair(iter->first, cpCurrent.getWordsKpts()[iter->second]));
}
for(std::map<int, int>::iterator iter=previousUniqueWords.begin(); iter!=previousUniqueWords.end(); ++iter)
{
previousWords.insert(std::make_pair(iter->first, cpPrevious.getWordsKpts()[iter->second]));
}
std::map<int, cv::Point3f> inliers = util3d::generateWords3DMono( std::map<int, cv::Point3f> inliers = util3d::generateWords3DMono(
uMultimapToMapUnique(cpCurrent.getWords()), currentWords,
uMultimapToMapUnique(cpPrevious.getWords()), previousWords,
cameraModels[0], cameraModels[0],
cameraTransform); cameraTransform);
@@ -4845,32 +4935,26 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
UASSERT(words3D.size() == 0 || words.size() == words3D.size()); UASSERT(words3D.size() == 0 || words.size() == words3D.size());
bool words3DWasEmpty = words3D.empty(); bool words3DWasEmpty = words3D.empty();
int added3DPointsWithoutDepth = 0; int added3DPointsWithoutDepth = 0;
for(std::multimap<int, cv::KeyPoint>::const_iterator iter=words.begin(); iter!=words.end(); ++iter) for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
{ {
std::map<int, cv::Point3f>::iterator jter=inliers.find(iter->first); std::map<int, cv::Point3f>::iterator jter=inliers.find(iter->first);
std::multimap<int, cv::Point3f>::iterator iter3D = words3D.find(iter->first); if(words3DWasEmpty)
if(iter3D == words3D.end())
{ {
if(jter != inliers.end()) if(jter != inliers.end())
{ {
words3D.insert(std::make_pair(iter->first, jter->second)); words3D.push_back(jter->second);
++added3DPointsWithoutDepth; ++added3DPointsWithoutDepth;
} }
else else
{ {
words3D.insert(std::make_pair(iter->first, cv::Point3f(bad_point,bad_point,bad_point))); words3D.push_back(cv::Point3f(bad_point,bad_point,bad_point));
} }
} }
else if(!util3d::isFinite(iter3D->second) && jter != inliers.end()) else if(!util3d::isFinite(words3D[iter->second]) && jter != inliers.end())
{ {
iter3D->second = jter->second; words3D[iter->second] = jter->second;
++added3DPointsWithoutDepth; ++added3DPointsWithoutDepth;
} }
else if(words3DWasEmpty && jter == inliers.end())
{
// duplicate
words3D.insert(std::make_pair(iter->first, cv::Point3f(bad_point,bad_point,bad_point)));
}
} }
UDEBUG("added3DPointsWithoutDepth=%d", added3DPointsWithoutDepth); UDEBUG("added3DPointsWithoutDepth=%d", added3DPointsWithoutDepth);
if(stats) stats->addStatistic(Statistics::kMemoryTriangulated_points(), (float)added3DPointsWithoutDepth); if(stats) stats->addStatistic(Statistics::kMemoryTriangulated_points(), (float)added3DPointsWithoutDepth);
@@ -5123,9 +5207,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
compressedUserData)); compressedUserData));
} }
s->setWords(words); s->setWords(words, wordsKpts, words3D, wordsDescriptors);
s->setWords3(words3D);
s->setWordsDescriptors(wordsDescriptors);
// set raw data // set raw data
if(!cameraModels.empty()) if(!cameraModels.empty())
@@ -5290,7 +5372,7 @@ void Memory::disableWordsRef(int signatureId)
Signature * ss = this->_getSignature(signatureId); Signature * ss = this->_getSignature(signatureId);
if(ss && ss->isEnabled()) if(ss && ss->isEnabled())
{ {
const std::multimap<int, cv::KeyPoint> & words = ss->getWords(); const std::multimap<int, int> & words = ss->getWords();
const std::list<int> & keys = uUniqueKeys(words); const std::list<int> & keys = uUniqueKeys(words);
int count = _vwd->getTotalActiveReferences(); int count = _vwd->getTotalActiveReferences();
// First remove all references // First remove all references
+32
View File
@@ -1532,4 +1532,36 @@ bool OccupancyGrid::update(const std::map<int, Transform> & posesIn)
return updated; return updated;
} }
unsigned long OccupancyGrid::getMemoryUsed() const
{
unsigned long memoryUsage = sizeof(OccupancyGrid);
memoryUsage += parameters_.size()*(sizeof(std::string)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(ParametersMap);
memoryUsage += cache_.size()*(sizeof(int) + sizeof(std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat>) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >);
for(std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::const_iterator iter=cache_.begin(); iter!=cache_.end(); ++iter)
{
memoryUsage += iter->second.first.first.total() * iter->second.first.first.elemSize();
memoryUsage += iter->second.first.second.total() * iter->second.first.second.elemSize();
memoryUsage += iter->second.second.total() * iter->second.second.elemSize();
}
memoryUsage += map_.total() * map_.elemSize();
memoryUsage += mapInfo_.total() * mapInfo_.elemSize();
memoryUsage += cellCount_.size()*(sizeof(int)*3 + sizeof(std::pair<int, int>) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, std::pair<int, int> >);
memoryUsage += addedNodes_.size()*(sizeof(int) + sizeof(Transform)+ sizeof(float)*12 + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, Transform>);
if(assembledGround_.get())
{
memoryUsage += assembledGround_->points.size() * sizeof(pcl::PointXYZRGB);
}
if(assembledObstacles_.get())
{
memoryUsage += assembledObstacles_->points.size() * sizeof(pcl::PointXYZRGB);
}
if(assembledEmptyCells_.get())
{
memoryUsage += assembledEmptyCells_->points.size() * sizeof(pcl::PointXYZRGB);
}
return memoryUsage;
}
} }
+22 -17
View File
@@ -617,8 +617,8 @@ void Optimizer::computeBACorrespondences(
if(!rematchFeatures) if(!rematchFeatures)
{ {
sFrom.setWordsDescriptors(std::multimap<int, cv::Mat>()); sFrom.setWordsDescriptors(cv::Mat());
sTo.setWordsDescriptors(std::multimap<int, cv::Mat>()); sTo.setWordsDescriptors(cv::Mat());
} }
RegistrationInfo info; RegistrationInfo info;
@@ -633,13 +633,13 @@ void Optimizer::computeBACorrespondences(
// set descriptors for the output // set descriptors for the output
if(sFrom.getWords().size() && if(sFrom.getWords().size() &&
sFrom.getWordsDescriptors().empty() && sFrom.getWordsDescriptors().empty() &&
sFrom.getWords().size() == signatures.at(link.from()).getWordsDescriptors().size()) (int)sFrom.getWords().size() == signatures.at(link.from()).getWordsDescriptors().rows)
{ {
sFrom.setWordsDescriptors(signatures.at(link.from()).getWordsDescriptors()); sFrom.setWordsDescriptors(signatures.at(link.from()).getWordsDescriptors());
} }
if(sTo.getWords().size() && if(sTo.getWords().size() &&
sTo.getWordsDescriptors().empty() && sTo.getWordsDescriptors().empty() &&
sTo.getWords().size() == signatures.at(link.to()).getWordsDescriptors().size()) (int)sTo.getWords().size() == signatures.at(link.to()).getWordsDescriptors().rows)
{ {
sTo.setWordsDescriptors(signatures.at(link.to()).getWordsDescriptors()); sTo.setWordsDescriptors(signatures.at(link.to()).getWordsDescriptors());
} }
@@ -649,11 +649,13 @@ void Optimizer::computeBACorrespondences(
UASSERT(!pose.isNull()); UASSERT(!pose.isNull());
for(unsigned int i=0; i<info.inliersIDs.size(); ++i) for(unsigned int i=0; i<info.inliersIDs.size(); ++i)
{ {
cv::Point3f p = sFrom.getWords3().lower_bound(info.inliersIDs[i])->second; int indexFrom = sFrom.getWords().lower_bound(info.inliersIDs[i])->second;
cv::Point3f p = sFrom.getWords3()[indexFrom];
if(p.x > 0.0f) // make sure the point is valid if(p.x > 0.0f) // make sure the point is valid
{ {
cv::KeyPoint ptFrom = sFrom.getWords().lower_bound(info.inliersIDs[i])->second; cv::KeyPoint ptFrom = sFrom.getWordsKpts()[indexFrom];
cv::KeyPoint ptTo = sTo.getWords().lower_bound(info.inliersIDs[i])->second; int indexTo = sTo.getWords().lower_bound(info.inliersIDs[i])->second;
cv::KeyPoint ptTo = sTo.getWordsKpts()[indexTo];
int wordId = -1; int wordId = -1;
@@ -692,10 +694,10 @@ void Optimizer::computeBACorrespondences(
if(!fromAlreadyAdded) if(!fromAlreadyAdded)
{ {
cv::Mat descriptorFrom; cv::Mat descriptorFrom;
if(sFrom.getWordsDescriptors().size()) if(!sFrom.getWordsDescriptors().empty())
{ {
UASSERT(sFrom.getWordsDescriptors().find(info.inliersIDs[i]) != sFrom.getWordsDescriptors().end()); UASSERT(indexFrom < sFrom.getWordsDescriptors().rows);
descriptorFrom = sFrom.getWordsDescriptors().lower_bound(info.inliersIDs[i])->second; descriptorFrom = sFrom.getWordsDescriptors().row(indexFrom);
} }
wordReferences.at(wordId).insert(std::make_pair(sFrom.id(), FeatureBA(ptFrom, p.x, descriptorFrom))); wordReferences.at(wordId).insert(std::make_pair(sFrom.id(), FeatureBA(ptFrom, p.x, descriptorFrom)));
frameToWordMap.insert(std::make_pair(sFrom.id(), std::map<cv::KeyPoint, int, KeyPointCompare>())); frameToWordMap.insert(std::make_pair(sFrom.id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
@@ -705,17 +707,20 @@ void Optimizer::computeBACorrespondences(
if(!toAlreadyAdded) if(!toAlreadyAdded)
{ {
cv::Mat descriptorTo; cv::Mat descriptorTo;
if(sTo.getWordsDescriptors().size()) if(!sTo.getWordsDescriptors().empty())
{ {
UASSERT(sTo.getWordsDescriptors().find(info.inliersIDs[i]) != sTo.getWordsDescriptors().end()); UASSERT(indexTo < sTo.getWordsDescriptors().rows);
descriptorTo = sTo.getWordsDescriptors().lower_bound(info.inliersIDs[i])->second; descriptorTo = sTo.getWordsDescriptors().row(indexTo);
} }
float depth = 0.0f; float depth = 0.0f;
std::multimap<int, cv::Point3f>::const_iterator iterTo = sTo.getWords3().lower_bound(info.inliersIDs[i]); if(!sTo.getWords3().empty())
if( iterTo!=sTo.getWords3().end() &&
iterTo->second.x > 0)
{ {
depth = iterTo->second.x; UASSERT(indexTo < (int)sTo.getWords3().size());
const cv::Point3f & pt = sTo.getWords3()[indexTo];
if( pt.x > 0)
{
depth = pt.x;
}
} }
wordReferences.at(wordId).insert(std::make_pair(sTo.id(), FeatureBA(ptTo, depth, descriptorTo))); wordReferences.at(wordId).insert(std::make_pair(sTo.id(), FeatureBA(ptTo, depth, descriptorTo)));
frameToWordMap.insert(std::make_pair(sTo.id(), std::map<cv::KeyPoint, int, KeyPointCompare>())); frameToWordMap.insert(std::make_pair(sTo.id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
+205 -144
View File
@@ -303,7 +303,7 @@ Transform RegistrationVis::computeTransformationImpl(
fromSignature.id(), fromSignature.id(),
(int)fromSignature.getWords().size(), (int)fromSignature.getWords().size(),
(int)fromSignature.getWords3().size(), (int)fromSignature.getWords3().size(),
(int)fromSignature.getWordsDescriptors().size(), (int)fromSignature.getWordsDescriptors().rows,
(int)fromSignature.sensorData().keypoints().size(), (int)fromSignature.sensorData().keypoints().size(),
(int)fromSignature.sensorData().keypoints3D().size(), (int)fromSignature.sensorData().keypoints3D().size(),
fromSignature.sensorData().descriptors().rows, fromSignature.sensorData().descriptors().rows,
@@ -316,7 +316,7 @@ Transform RegistrationVis::computeTransformationImpl(
toSignature.id(), toSignature.id(),
(int)toSignature.getWords().size(), (int)toSignature.getWords().size(),
(int)toSignature.getWords3().size(), (int)toSignature.getWords3().size(),
(int)toSignature.getWordsDescriptors().size(), (int)toSignature.getWordsDescriptors().rows,
(int)toSignature.sensorData().keypoints().size(), (int)toSignature.sensorData().keypoints().size(),
(int)toSignature.sensorData().keypoints3D().size(), (int)toSignature.sensorData().keypoints3D().size(),
toSignature.sensorData().descriptors().rows, toSignature.sensorData().descriptors().rows,
@@ -349,16 +349,16 @@ Transform RegistrationVis::computeTransformationImpl(
fromSignature.getWords3().empty() || fromSignature.getWords3().empty() ||
(fromSignature.getWords().size() == fromSignature.getWords3().size())); (fromSignature.getWords().size() == fromSignature.getWords3().size()));
UASSERT((int)fromSignature.sensorData().keypoints().size() == fromSignature.sensorData().descriptors().rows || UASSERT((int)fromSignature.sensorData().keypoints().size() == fromSignature.sensorData().descriptors().rows ||
fromSignature.getWords().size() == fromSignature.getWordsDescriptors().size() || (int)fromSignature.getWords().size() == fromSignature.getWordsDescriptors().rows ||
fromSignature.sensorData().descriptors().rows == 0 || fromSignature.sensorData().descriptors().empty() ||
fromSignature.getWordsDescriptors().size() == 0); fromSignature.getWordsDescriptors().empty() == 0);
UASSERT((toSignature.getWords().empty() && toSignature.getWords3().empty())|| UASSERT((toSignature.getWords().empty() && toSignature.getWords3().empty())||
(toSignature.getWords().size() && toSignature.getWords3().empty())|| (toSignature.getWords().size() && toSignature.getWords3().empty())||
(toSignature.getWords().size() == toSignature.getWords3().size())); (toSignature.getWords().size() == toSignature.getWords3().size()));
UASSERT((int)toSignature.sensorData().keypoints().size() == toSignature.sensorData().descriptors().rows || UASSERT((int)toSignature.sensorData().keypoints().size() == toSignature.sensorData().descriptors().rows ||
toSignature.getWords().size() == toSignature.getWordsDescriptors().size() || (int)toSignature.getWords().size() == toSignature.getWordsDescriptors().rows ||
toSignature.sensorData().descriptors().rows == 0 || toSignature.sensorData().descriptors().empty() ||
toSignature.getWordsDescriptors().size() == 0); toSignature.getWordsDescriptors().empty());
UASSERT(fromSignature.sensorData().imageRaw().empty() || UASSERT(fromSignature.sensorData().imageRaw().empty() ||
fromSignature.sensorData().imageRaw().type() == CV_8UC1 || fromSignature.sensorData().imageRaw().type() == CV_8UC1 ||
fromSignature.sensorData().imageRaw().type() == CV_8UC3); fromSignature.sensorData().imageRaw().type() == CV_8UC3);
@@ -371,6 +371,7 @@ Transform RegistrationVis::computeTransformationImpl(
cv::Mat imageTo = toSignature.sensorData().imageRaw(); cv::Mat imageTo = toSignature.sensorData().imageRaw();
std::vector<int> orignalWordsFromIds; std::vector<int> orignalWordsFromIds;
int kptsFromSource = 0;
if(fromSignature.getWords().empty()) if(fromSignature.getWords().empty())
{ {
if(fromSignature.sensorData().keypoints().empty()) if(fromSignature.sensorData().keypoints().empty())
@@ -403,22 +404,26 @@ Transform RegistrationVis::computeTransformationImpl(
else else
{ {
kptsFrom = fromSignature.sensorData().keypoints(); kptsFrom = fromSignature.sensorData().keypoints();
kptsFromSource = 1;
} }
} }
else else
{ {
kptsFrom.resize(fromSignature.getWords().size()); kptsFromSource = 2;
orignalWordsFromIds.resize(fromSignature.getWords().size()); orignalWordsFromIds.resize(fromSignature.getWords().size());
int i=0; int i=0;
bool allUniques = true; bool allUniques = true;
for(std::multimap<int, cv::KeyPoint>::const_iterator iter=fromSignature.getWords().begin(); iter!=fromSignature.getWords().end(); ++iter) int previousIdAdded = 0;
kptsFrom = fromSignature.getWordsKpts();
for(std::multimap<int, int>::const_iterator iter=fromSignature.getWords().begin(); iter!=fromSignature.getWords().end(); ++iter)
{ {
kptsFrom[i] = iter->second; UASSERT(iter->second>=0 && iter->second<(int)orignalWordsFromIds.size());
orignalWordsFromIds[i] = iter->first; orignalWordsFromIds[iter->second] = iter->first;
if(i>0 && iter->first==orignalWordsFromIds[i-1]) if(i>0 && iter->first==previousIdAdded)
{ {
allUniques = false; allUniques = false;
} }
previousIdAdded = iter->first;
++i; ++i;
} }
if(!allUniques) if(!allUniques)
@@ -428,12 +433,14 @@ Transform RegistrationVis::computeTransformationImpl(
} }
} }
std::multimap<int, cv::KeyPoint> wordsFrom; std::multimap<int, int> wordsFrom;
std::multimap<int, cv::KeyPoint> wordsTo; std::multimap<int, int> wordsTo;
std::multimap<int, cv::Point3f> words3From; std::vector<cv::KeyPoint> wordsKptsFrom;
std::multimap<int, cv::Point3f> words3To; std::vector<cv::KeyPoint> wordsKptsTo;
std::multimap<int, cv::Mat> wordsDescFrom; std::vector<cv::Point3f> words3From;
std::multimap<int, cv::Mat> wordsDescTo; std::vector<cv::Point3f> words3To;
cv::Mat wordsDescFrom;
cv::Mat wordsDescTo;
if(_correspondencesApproach == 1) //Optical Flow if(_correspondencesApproach == 1) //Optical Flow
{ {
UDEBUG(""); UDEBUG("");
@@ -454,7 +461,7 @@ Transform RegistrationVis::computeTransformationImpl(
std::vector<cv::Point3f> kptsFrom3D; std::vector<cv::Point3f> kptsFrom3D;
if(kptsFrom.size() == fromSignature.getWords3().size()) if(kptsFrom.size() == fromSignature.getWords3().size())
{ {
kptsFrom3D = uValues(fromSignature.getWords3()); kptsFrom3D = fromSignature.getWords3();
} }
else if(kptsFrom.size() == fromSignature.sensorData().keypoints3D().size()) else if(kptsFrom.size() == fromSignature.sensorData().keypoints3D().size())
{ {
@@ -544,13 +551,16 @@ Transform RegistrationVis::computeTransformationImpl(
UASSERT(kptsTo3D.size() == 0 || kptsTo.size() == kptsTo3D.size()); UASSERT(kptsTo3D.size() == 0 || kptsTo.size() == kptsTo3D.size());
for(unsigned int i=0; i< kptsFrom3DKept.size(); ++i) for(unsigned int i=0; i< kptsFrom3DKept.size(); ++i)
{ {
int id = orignalWordsFromIds.size()?orignalWordsFromIds[i]:i; int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
wordsFrom.insert(std::make_pair(id, kptsFrom[i])); wordsFrom.insert(wordsFrom.end(), std::make_pair(id, wordsFrom.size()));
words3From.insert(std::make_pair(id, kptsFrom3DKept[i])); wordsKptsFrom.push_back(kptsFrom[i]);
wordsTo.insert(std::make_pair(id, kptsTo[i])); words3From.push_back(kptsFrom3DKept[i]);
if(kptsTo3D.size())
wordsTo.insert(wordsTo.end(), std::make_pair(id, wordsTo.size()));
wordsKptsTo.push_back(kptsTo[i]);
if(!kptsTo3D.empty())
{ {
words3To.insert(std::make_pair(id, kptsTo3D[i])); words3To.push_back(kptsTo3D[i]);
} }
} }
toSignature.sensorData().setFeatures(kptsTo, kptsTo3D, cv::Mat()); toSignature.sensorData().setFeatures(kptsTo, kptsTo3D, cv::Mat());
@@ -566,9 +576,10 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
if(util3d::isFinite(kptsFrom3D[i])) if(util3d::isFinite(kptsFrom3D[i]))
{ {
int id = orignalWordsFromIds.size()?orignalWordsFromIds[i]:i; int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
wordsFrom.insert(std::make_pair(id, kptsFrom[i])); wordsFrom.insert(wordsFrom.end(), std::make_pair(id, wordsFrom.size()));
words3From.insert(std::make_pair(id, kptsFrom3D[i])); wordsKptsFrom.push_back(kptsFrom[i]);
words3From.push_back(kptsFrom3D[i]);
} }
} }
toSignature.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); toSignature.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
@@ -580,6 +591,7 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
UDEBUG(""); UDEBUG("");
std::vector<cv::KeyPoint> kptsTo; std::vector<cv::KeyPoint> kptsTo;
int kptsToSource = 0;
if(toSignature.getWords().empty()) if(toSignature.getWords().empty())
{ {
if(toSignature.sensorData().keypoints().empty() && if(toSignature.sensorData().keypoints().empty() &&
@@ -610,33 +622,28 @@ Transform RegistrationVis::computeTransformationImpl(
else else
{ {
kptsTo = toSignature.sensorData().keypoints(); kptsTo = toSignature.sensorData().keypoints();
kptsToSource = 1;
} }
} }
else else
{ {
kptsTo = uValues(toSignature.getWords()); kptsTo = toSignature.getWordsKpts();
kptsToSource = 2;
} }
// extract descriptors // extract descriptors
UDEBUG("kptsFrom=%d", (int)kptsFrom.size()); UDEBUG("kptsFrom=%d kptsFromSource=%d", (int)kptsFrom.size(), kptsFromSource);
UDEBUG("kptsTo=%d", (int)kptsTo.size()); UDEBUG("kptsTo=%d kptsToSource=%d", (int)kptsTo.size(), kptsToSource);
cv::Mat descriptorsFrom; cv::Mat descriptorsFrom;
if(fromSignature.getWordsDescriptors().size() && if(kptsFromSource == 2 &&
((kptsFrom.empty() && fromSignature.getWordsDescriptors().size()) || fromSignature.getWordsDescriptors().rows &&
fromSignature.getWordsDescriptors().size() == kptsFrom.size())) ((kptsFrom.empty() && fromSignature.getWordsDescriptors().rows) ||
fromSignature.getWordsDescriptors().rows == (int)kptsFrom.size()))
{ {
descriptorsFrom = cv::Mat(fromSignature.getWordsDescriptors().size(), descriptorsFrom = fromSignature.getWordsDescriptors();
fromSignature.getWordsDescriptors().begin()->second.cols,
fromSignature.getWordsDescriptors().begin()->second.type());
int i=0;
for(std::multimap<int, cv::Mat>::const_iterator iter=fromSignature.getWordsDescriptors().begin();
iter!=fromSignature.getWordsDescriptors().end();
++iter, ++i)
{
iter->second.copyTo(descriptorsFrom.row(i));
} }
} else if(kptsFromSource == 1 &&
else if(fromSignature.sensorData().descriptors().rows == (int)kptsFrom.size()) fromSignature.sensorData().descriptors().rows == (int)kptsFrom.size())
{ {
descriptorsFrom = fromSignature.sensorData().descriptors(); descriptorsFrom = fromSignature.sensorData().descriptors();
} }
@@ -656,20 +663,13 @@ Transform RegistrationVis::computeTransformationImpl(
cv::Mat descriptorsTo; cv::Mat descriptorsTo;
if(kptsTo.size()) if(kptsTo.size())
{ {
if(toSignature.getWordsDescriptors().size() == kptsTo.size()) if(kptsToSource == 2 &&
toSignature.getWordsDescriptors().rows == (int)kptsTo.size())
{ {
descriptorsTo = cv::Mat(toSignature.getWordsDescriptors().size(), descriptorsTo = toSignature.getWordsDescriptors();
toSignature.getWordsDescriptors().begin()->second.cols,
toSignature.getWordsDescriptors().begin()->second.type());
int i=0;
for(std::multimap<int, cv::Mat>::const_iterator iter=toSignature.getWordsDescriptors().begin();
iter!=toSignature.getWordsDescriptors().end();
++iter, ++i)
{
iter->second.copyTo(descriptorsTo.row(i));
} }
} else if(kptsToSource == 1 &&
else if(toSignature.sensorData().descriptors().rows == (int)kptsTo.size()) toSignature.sensorData().descriptors().rows == (int)kptsTo.size())
{ {
descriptorsTo = toSignature.sensorData().descriptors(); descriptorsTo = toSignature.sensorData().descriptors();
} }
@@ -689,11 +689,13 @@ Transform RegistrationVis::computeTransformationImpl(
// create 3D keypoints // create 3D keypoints
std::vector<cv::Point3f> kptsFrom3D; std::vector<cv::Point3f> kptsFrom3D;
std::vector<cv::Point3f> kptsTo3D; std::vector<cv::Point3f> kptsTo3D;
if(kptsFrom.size() == fromSignature.getWords3().size()) if(kptsFromSource == 2 &&
kptsFrom.size() == fromSignature.getWords3().size())
{ {
kptsFrom3D = uValues(fromSignature.getWords3()); kptsFrom3D = fromSignature.getWords3();
} }
else if(kptsFrom.size() == fromSignature.sensorData().keypoints3D().size()) else if(kptsFromSource == 1 &&
kptsFrom.size() == fromSignature.sensorData().keypoints3D().size())
{ {
kptsFrom3D = fromSignature.sensorData().keypoints3D(); kptsFrom3D = fromSignature.sensorData().keypoints3D();
} }
@@ -724,11 +726,12 @@ Transform RegistrationVis::computeTransformationImpl(
_detectorFrom->filterKeypointsByDepth(kptsFrom, descriptorsFrom, kptsFrom3D, _detectorFrom->getMinDepth(), _detectorFrom->getMaxDepth()); _detectorFrom->filterKeypointsByDepth(kptsFrom, descriptorsFrom, kptsFrom3D, _detectorFrom->getMinDepth(), _detectorFrom->getMaxDepth());
} }
if(kptsTo.size() == toSignature.getWords3().size()) if(kptsToSource == 2 && kptsTo.size() == toSignature.getWords3().size())
{ {
kptsTo3D = uValues(toSignature.getWords3()); kptsTo3D = toSignature.getWords3();
} }
else if(kptsTo.size() == toSignature.sensorData().keypoints3D().size()) else if(kptsToSource == 1 &&
kptsTo.size() == toSignature.sensorData().keypoints3D().size())
{ {
kptsTo3D = toSignature.sensorData().keypoints3D(); kptsTo3D = toSignature.sensorData().keypoints3D();
} }
@@ -858,7 +861,7 @@ Transform RegistrationVis::computeTransformationImpl(
UDEBUG("radius search done for guess"); UDEBUG("radius search done for guess");
// Process results (Nearest Neighbor Distance Ratio) // Process results (Nearest Neighbor Distance Ratio)
int newToId = orignalWordsFromIds.size()?orignalWordsFromIds.back():descriptorsFrom.rows; int newToId = !orignalWordsFromIds.empty()?fromSignature.getWords().rbegin()->first+1:descriptorsFrom.rows;
std::map<int,int> addedWordsFrom; //<id, index> std::map<int,int> addedWordsFrom; //<id, index>
std::map<int, int> duplicates; //<fromId, toId> std::map<int, int> duplicates; //<fromId, toId>
int newWords = 0; int newWords = 0;
@@ -912,7 +915,7 @@ Transform RegistrationVis::computeTransformationImpl(
if(matchedIndex >= 0) if(matchedIndex >= 0)
{ {
matchedIndex = projectedIndexToDescIndex[matchedIndex]; matchedIndex = projectedIndexToDescIndex[matchedIndex];
int id = orignalWordsFromIds.size()?orignalWordsFromIds[matchedIndex]:matchedIndex; int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndex]:matchedIndex;
if(addedWordsFrom.find(matchedIndex) != addedWordsFrom.end()) if(addedWordsFrom.find(matchedIndex) != addedWordsFrom.end())
{ {
@@ -923,29 +926,32 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
addedWordsFrom.insert(std::make_pair(matchedIndex, id)); addedWordsFrom.insert(std::make_pair(matchedIndex, id));
if(kptsFrom.size()) wordsFrom.insert(wordsFrom.end(), std::make_pair(id, wordsFrom.size()));
if(!kptsFrom.empty())
{ {
wordsFrom.insert(std::make_pair(id, kptsFrom[matchedIndex])); wordsKptsFrom.push_back(kptsFrom[matchedIndex]);
} }
words3From.insert(std::make_pair(id, kptsFrom3D[matchedIndex])); words3From.push_back(kptsFrom3D[matchedIndex]);
wordsDescFrom.insert(std::make_pair(id, descriptorsFrom.row(matchedIndex))); wordsDescFrom.push_back(descriptorsFrom.row(matchedIndex));
} }
wordsTo.insert(std::make_pair(id, kptsTo[i])); wordsTo.insert(wordsTo.end(), std::make_pair(id, wordsTo.size()));
wordsDescTo.insert(std::make_pair(id, descriptorsTo.row(i))); wordsKptsTo.push_back(kptsTo[i]);
if(kptsTo3D.size()) wordsDescTo.push_back(descriptorsTo.row(i));
if(!kptsTo3D.empty())
{ {
words3To.insert(std::make_pair(id, kptsTo3D[i])); words3To.push_back(kptsTo3D[i]);
} }
} }
else else
{ {
// gen fake ids // gen fake ids
wordsTo.insert(wordsTo.end(), std::make_pair(newToId, kptsTo[i])); wordsTo.insert(wordsTo.end(), std::make_pair(newToId, wordsTo.size()));
wordsDescTo.insert(wordsDescTo.end(), std::make_pair(newToId, descriptorsTo.row(i))); wordsKptsTo.push_back(kptsTo[i]);
if(kptsTo3D.size()) wordsDescTo.push_back(descriptorsTo.row(i));
if(!kptsTo3D.empty())
{ {
words3To.insert(words3To.end(), std::make_pair(newToId, kptsTo3D[i])); words3To.push_back(kptsTo3D[i]);
} }
++newToId; ++newToId;
@@ -962,10 +968,11 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
if(util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end()) if(util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end())
{ {
int id = orignalWordsFromIds.size()?orignalWordsFromIds[i]:i; int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
wordsFrom.insert(wordsFrom.end(), std::make_pair(id, kptsFrom[i])); wordsFrom.insert(wordsFrom.end(), std::make_pair(id, wordsFrom.size()));
wordsDescFrom.insert(wordsDescFrom.end(), std::make_pair(id, descriptorsFrom.row(i))); wordsKptsFrom.push_back(kptsFrom[i]);
words3From.insert(words3From.end(), std::make_pair(id, kptsFrom3D[i])); wordsDescFrom.push_back(descriptorsFrom.row(i));
words3From.push_back(kptsFrom3D[i]);
++addWordsFromNotMatched; ++addWordsFromNotMatched;
} }
@@ -1007,7 +1014,7 @@ Transform RegistrationVis::computeTransformationImpl(
if(indices[i].size()) if(indices[i].size())
{ {
info.projectedIDs.push_back(orignalWordsFromIds.size()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom); info.projectedIDs.push_back(!orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom);
} }
if(util3d::isFinite(kptsFrom3D[matchedIndexFrom])) if(util3d::isFinite(kptsFrom3D[matchedIndexFrom]))
@@ -1058,26 +1065,28 @@ Transform RegistrationVis::computeTransformationImpl(
matchedIndexTo = indices[i].at(0); matchedIndexTo = indices[i].at(0);
} }
int id = orignalWordsFromIds.size()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom; int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[matchedIndexFrom]:matchedIndexFrom;
addedWordsFrom.insert(addedWordsFrom.end(), matchedIndexFrom); addedWordsFrom.insert(addedWordsFrom.end(), matchedIndexFrom);
if(kptsFrom.size()) wordsFrom.insert(wordsFrom.end(), std::make_pair(id, wordsFrom.size()));
if(!kptsFrom.empty())
{ {
wordsFrom.insert(wordsFrom.end(), std::make_pair(id, kptsFrom[matchedIndexFrom])); wordsKptsFrom.push_back(kptsFrom[matchedIndexFrom]);
} }
words3From.insert(words3From.end(), std::make_pair(id, kptsFrom3D[matchedIndexFrom])); words3From.push_back(kptsFrom3D[matchedIndexFrom]);
wordsDescFrom.insert(wordsDescFrom.end(), std::make_pair(id, descriptorsFrom.row(matchedIndexFrom))); wordsDescFrom.push_back(descriptorsFrom.row(matchedIndexFrom));
if( matchedIndexTo >= 0 && if( matchedIndexTo >= 0 &&
addedWordsTo.find(matchedIndexTo) == addedWordsTo.end()) addedWordsTo.find(matchedIndexTo) == addedWordsTo.end())
{ {
addedWordsTo.insert(matchedIndexTo); addedWordsTo.insert(matchedIndexTo);
wordsTo.insert(wordsTo.end(), std::make_pair(id, kptsTo[matchedIndexTo])); wordsTo.insert(wordsTo.end(), std::make_pair(id, wordsTo.size()));
wordsDescTo.insert(wordsDescTo.end(), std::make_pair(id, descriptorsTo.row(matchedIndexTo))); wordsKptsTo.push_back(kptsTo[matchedIndexTo]);
if(kptsTo3D.size()) wordsDescTo.push_back(descriptorsTo.row(matchedIndexTo));
if(!kptsTo3D.empty())
{ {
words3To.insert(words3To.end(), std::make_pair(id, kptsTo3D[matchedIndexTo])); words3To.push_back(kptsTo3D[matchedIndexTo]);
} }
} }
} }
@@ -1089,23 +1098,25 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
if(util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end()) if(util3d::isFinite(kptsFrom3D[i]) && addedWordsFrom.find(i) == addedWordsFrom.end())
{ {
int id = orignalWordsFromIds.size()?orignalWordsFromIds[i]:i; int id = !orignalWordsFromIds.empty()?orignalWordsFromIds[i]:i;
wordsFrom.insert(wordsFrom.end(), std::make_pair(id, kptsFrom[i])); wordsFrom.insert(wordsFrom.end(), std::make_pair(id, wordsFrom.size()));
wordsDescFrom.insert(wordsDescFrom.end(), std::make_pair(id, descriptorsFrom.row(i))); wordsKptsFrom.push_back(kptsFrom[i]);
words3From.insert(words3From.end(), std::make_pair(id, kptsFrom3D[i])); wordsDescFrom.push_back(descriptorsFrom.row(i));
words3From.push_back(kptsFrom3D[i]);
} }
} }
int newToId = orignalWordsFromIds.size()?orignalWordsFromIds.back():descriptorsFrom.rows; int newToId = !orignalWordsFromIds.empty()?fromSignature.getWords().rbegin()->first+1:descriptorsFrom.rows;
for(unsigned int i = 0; i < kptsTo.size(); ++i) for(unsigned int i = 0; i < kptsTo.size(); ++i)
{ {
if(addedWordsTo.find(i) == addedWordsTo.end()) if(addedWordsTo.find(i) == addedWordsTo.end())
{ {
wordsTo.insert(wordsTo.end(), std::make_pair(newToId, kptsTo[i])); wordsTo.insert(wordsTo.end(), std::make_pair(newToId, wordsTo.size()));
wordsDescTo.insert(wordsDescTo.end(), std::make_pair(newToId, descriptorsTo.row(i))); wordsKptsTo.push_back(kptsTo[i]);
if(kptsTo3D.size()) wordsDescTo.push_back(descriptorsTo.row(i));
if(!kptsTo3D.empty())
{ {
words3To.insert(words3To.end(), std::make_pair(newToId, kptsTo3D[i])); words3To.push_back(kptsTo3D[i]);
} }
++newToId; ++newToId;
} }
@@ -1271,15 +1282,16 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
if(fromWordIdsSet.count(*iter) == 1) if(fromWordIdsSet.count(*iter) == 1)
{ {
if (kptsFrom.size()) wordsFrom.insert(wordsFrom.end(), std::make_pair(*iter, wordsFrom.size()));
if (!kptsFrom.empty())
{ {
wordsFrom.insert(std::make_pair(*iter, kptsFrom[i])); wordsKptsFrom.push_back(kptsFrom[i]);
} }
if(kptsFrom3D.size()) if(!kptsFrom3D.empty())
{ {
words3From.insert(std::make_pair(*iter, kptsFrom3D[i])); words3From.push_back(kptsFrom3D[i]);
} }
wordsDescFrom.insert(std::make_pair(*iter, descriptorsFrom.row(i))); wordsDescFrom.push_back(descriptorsFrom.row(i));
} }
++i; ++i;
} }
@@ -1291,11 +1303,12 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
if(toWordIdsSet.count(*iter) == 1) if(toWordIdsSet.count(*iter) == 1)
{ {
wordsTo.insert(std::make_pair(*iter, kptsTo[i])); wordsTo.insert(wordsTo.end(), std::make_pair(*iter, wordsTo.size()));
wordsDescTo.insert(std::make_pair(*iter, descriptorsTo.row(i))); wordsKptsTo.push_back(kptsTo[i]);
if(kptsTo3D.size()) wordsDescTo.push_back(descriptorsTo.row(i));
if(!kptsTo3D.empty())
{ {
words3To.insert(std::make_pair(*iter, kptsTo3D[i])); words3To.push_back(kptsTo3D[i]);
} }
} }
++i; ++i;
@@ -1308,21 +1321,19 @@ Transform RegistrationVis::computeTransformationImpl(
UASSERT(kptsFrom3D.empty() || int(kptsFrom3D.size()) == descriptorsFrom.rows); UASSERT(kptsFrom3D.empty() || int(kptsFrom3D.size()) == descriptorsFrom.rows);
for(int i=0; i<descriptorsFrom.rows; ++i) for(int i=0; i<descriptorsFrom.rows; ++i)
{ {
wordsFrom.insert(std::make_pair(i, kptsFrom[i])); wordsFrom.insert(wordsFrom.end(), std::make_pair(i, wordsFrom.size()));
wordsDescFrom.insert(std::make_pair(i, descriptorsFrom.row(i))); wordsKptsFrom.push_back(kptsFrom[i]);
if(kptsFrom3D.size()) wordsDescFrom.push_back(descriptorsFrom.row(i));
if(!kptsFrom3D.empty())
{ {
words3From.insert(std::make_pair(i, kptsFrom3D[i])); words3From.push_back(kptsFrom3D[i]);
} }
} }
} }
} }
fromSignature.setWords(wordsFrom);
fromSignature.setWords3(words3From); fromSignature.setWords(wordsFrom, wordsKptsFrom, words3From, wordsDescFrom);
fromSignature.setWordsDescriptors(wordsDescFrom); toSignature.setWords(wordsTo, wordsKptsTo, words3To, wordsDescTo);
toSignature.setWords(wordsTo);
toSignature.setWords3(words3To);
toSignature.setWordsDescriptors(wordsDescTo);
} }
///////////////////// /////////////////////
@@ -1376,14 +1387,31 @@ Transform RegistrationVis::computeTransformationImpl(
Transform cameraTransform; Transform cameraTransform;
double variance = 1.0f; double variance = 1.0f;
std::vector<int> matchesV; std::vector<int> matchesV;
std::map<int, int> uniqueWordsA = uMultimapToMapUnique(signatureA->getWords());
std::map<int, int> uniqueWordsB = uMultimapToMapUnique(signatureB->getWords());
std::map<int, cv::KeyPoint> wordsA;
std::map<int, cv::Point3f> words3A;
std::map<int, cv::KeyPoint> wordsB;
for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
{
wordsA.insert(std::make_pair(iter->first, signatureA->getWordsKpts()[iter->second]));
if(!signatureA->getWords3().empty())
{
words3A.insert(std::make_pair(iter->first, signatureA->getWords3()[iter->second]));
}
}
for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
{
wordsB.insert(std::make_pair(iter->first, signatureB->getWordsKpts()[iter->second]));
}
std::map<int, cv::Point3f> inliers3D = util3d::generateWords3DMono( std::map<int, cv::Point3f> inliers3D = util3d::generateWords3DMono(
uMultimapToMapUnique(signatureA->getWords()), wordsA,
uMultimapToMapUnique(signatureB->getWords()), wordsB,
cameraModel, cameraModel,
cameraTransform, cameraTransform,
_PnPReprojError, _PnPReprojError,
0.99f, 0.99f,
uMultimapToMapUnique(signatureA->getWords3()), // for scale estimation words3A, // for scale estimation
&variance, &variance,
&matchesV); &matchesV);
covariances[dir] *= variance; covariances[dir] *= variance;
@@ -1459,9 +1487,26 @@ Transform RegistrationVis::computeTransformationImpl(
std::vector<int> inliersV; std::vector<int> inliersV;
std::vector<int> matchesV; std::vector<int> matchesV;
std::map<int, int> uniqueWordsA = uMultimapToMapUnique(signatureA->getWords());
std::map<int, int> uniqueWordsB = uMultimapToMapUnique(signatureB->getWords());
std::map<int, cv::Point3f> words3A;
std::map<int, cv::Point3f> words3B;
std::map<int, cv::KeyPoint> wordsB;
for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
{
words3A.insert(std::make_pair(iter->first, signatureA->getWords3()[iter->second]));
}
for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
{
wordsB.insert(std::make_pair(iter->first, signatureB->getWordsKpts()[iter->second]));
if(!signatureB->getWords3().empty())
{
words3B.insert(std::make_pair(iter->first, signatureB->getWords3()[iter->second]));
}
}
transforms[dir] = util3d::estimateMotion3DTo2D( transforms[dir] = util3d::estimateMotion3DTo2D(
uMultimapToMapUnique(signatureA->getWords3()), words3A,
uMultimapToMapUnique(signatureB->getWords()), wordsB,
cameraModel, cameraModel,
_minInliers, _minInliers,
_iterations, _iterations,
@@ -1469,7 +1514,7 @@ Transform RegistrationVis::computeTransformationImpl(
_PnPFlags, _PnPFlags,
_PnPRefineIterations, _PnPRefineIterations,
dir==0?(!guess.isNull()?guess:Transform::getIdentity()):!transforms[0].isNull()?transforms[0].inverse():(!guess.isNull()?guess.inverse():Transform::getIdentity()), dir==0?(!guess.isNull()?guess:Transform::getIdentity()):!transforms[0].isNull()?transforms[0].inverse():(!guess.isNull()?guess.inverse():Transform::getIdentity()),
uMultimapToMapUnique(signatureB->getWords3()), words3B,
&covariances[dir], &covariances[dir],
&matchesV, &matchesV,
&inliersV); &inliersV);
@@ -1505,9 +1550,21 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
std::vector<int> inliersV; std::vector<int> inliersV;
std::vector<int> matchesV; std::vector<int> matchesV;
std::map<int, int> uniqueWordsA = uMultimapToMapUnique(signatureA->getWords());
std::map<int, int> uniqueWordsB = uMultimapToMapUnique(signatureB->getWords());
std::map<int, cv::Point3f> words3A;
std::map<int, cv::Point3f> words3B;
for(std::map<int, int>::iterator iter=uniqueWordsA.begin(); iter!=uniqueWordsA.end(); ++iter)
{
words3A.insert(std::make_pair(iter->first, signatureA->getWords3()[iter->second]));
}
for(std::map<int, int>::iterator iter=uniqueWordsB.begin(); iter!=uniqueWordsB.end(); ++iter)
{
words3B.insert(std::make_pair(iter->first, signatureB->getWords3()[iter->second]));
}
transforms[dir] = util3d::estimateMotion3DTo3D( transforms[dir] = util3d::estimateMotion3DTo3D(
uMultimapToMapUnique(signatureA->getWords3()), words3A,
uMultimapToMapUnique(signatureB->getWords3()), words3B,
_minInliers, _minInliers,
_inlierDistance, _inlierDistance,
_iterations, _iterations,
@@ -1679,7 +1736,8 @@ Transform RegistrationVis::computeTransformationImpl(
for(unsigned int i=0; i<allInliers.size(); ++i) for(unsigned int i=0; i<allInliers.size(); ++i)
{ {
int wordId = allInliers[i]; int wordId = allInliers[i];
const cv::Point3f & pt3D = fromSignature.getWords3().find(wordId)->second; int indexFrom = fromSignature.getWords().find(wordId)->second;
const cv::Point3f & pt3D = fromSignature.getWords3()[indexFrom];
if(!util3d::isFinite(pt3D)) if(!util3d::isFinite(pt3D))
{ {
UASSERT_MSG(!_forwardEstimateOnly, uFormat("3D point %d is not finite!?", wordId).c_str()); UASSERT_MSG(!_forwardEstimateOnly, uFormat("3D point %d is not finite!?", wordId).c_str());
@@ -1690,20 +1748,21 @@ Transform RegistrationVis::computeTransformationImpl(
points3DMap.insert(std::make_pair(wordId, pt3D)); points3DMap.insert(std::make_pair(wordId, pt3D));
std::map<int, FeatureBA> ptMap; std::map<int, FeatureBA> ptMap;
if(fromSignature.getWords().size() && cameraModelFrom.isValidForProjection()) if(!fromSignature.getWordsKpts().empty() && cameraModelFrom.isValidForProjection())
{ {
float depthFrom = util3d::transformPoint(pt3D, invLocalTransformFrom).z; float depthFrom = util3d::transformPoint(pt3D, invLocalTransformFrom).z;
const cv::KeyPoint & kpt = fromSignature.getWords().find(wordId)->second; const cv::KeyPoint & kpt = fromSignature.getWordsKpts()[indexFrom];
ptMap.insert(std::make_pair(1,FeatureBA(kpt, depthFrom))); ptMap.insert(std::make_pair(1,FeatureBA(kpt, depthFrom)));
} }
if(toSignature.getWords().size() && cameraModelTo.isValidForProjection()) if(!toSignature.getWordsKpts().empty() && cameraModelTo.isValidForProjection())
{ {
int indexTo = toSignature.getWords().find(wordId)->second;
float depthTo = 0.0f; float depthTo = 0.0f;
if(toSignature.getWords3().find(wordId) != toSignature.getWords3().end()) if(!toSignature.getWords3().empty())
{ {
depthTo = util3d::transformPoint(toSignature.getWords3().find(wordId)->second, invLocalTransformTo).z; depthTo = util3d::transformPoint(toSignature.getWords3()[indexTo], invLocalTransformTo).z;
} }
const cv::KeyPoint & kpt = toSignature.getWords().find(wordId)->second; const cv::KeyPoint & kpt = toSignature.getWordsKpts()[indexTo];
ptMap.insert(std::make_pair(2,FeatureBA(kpt, depthTo))); ptMap.insert(std::make_pair(2,FeatureBA(kpt, depthTo)));
} }
@@ -1841,24 +1900,25 @@ Transform RegistrationVis::computeTransformationImpl(
{ {
if(_maxInliersMeanDistance>0.0f) if(_maxInliersMeanDistance>0.0f)
{ {
std::multimap<int, cv::Point3f>::const_iterator words3Iter = fromSignature.getWords3().find(allInliers[i]); std::multimap<int, int>::const_iterator wordsIter = fromSignature.getWords().find(allInliers[i]);
if(words3Iter != fromSignature.getWords3().end()) if(wordsIter != fromSignature.getWords().end() && !fromSignature.getWords3().empty())
{ {
if(uIsFinite(words3Iter->second.x)) const cv::Point3f & pt = fromSignature.getWords3()[wordsIter->second];
if(uIsFinite(pt.x))
{ {
cv::Point3f pt = util3d::transformPoint(words3Iter->second, transformInv); distances.push_back(util3d::transformPoint(pt, transformInv).x);
distances.push_back(pt.x);
} }
} }
} }
if(!pcaData.empty()) if(!pcaData.empty())
{ {
std::multimap<int, cv::KeyPoint>::const_iterator wordsIter = fromSignature.getWords().find(allInliers[i]); std::multimap<int, int>::const_iterator wordsIter = fromSignature.getWords().find(allInliers[i]);
UASSERT(wordsIter != fromSignature.getWords().end()); UASSERT(wordsIter != fromSignature.getWords().end() && !fromSignature.getWordsKpts().empty());
float * ptr = pcaData.ptr<float>(i, 0); float * ptr = pcaData.ptr<float>(i, 0);
ptr[0] = (wordsIter->second.pt.x-cx) / w; const cv::KeyPoint & kpt = fromSignature.getWordsKpts()[wordsIter->second];
ptr[1] = (wordsIter->second.pt.y-cy) / h; ptr[0] = (kpt.pt.x-cx) / w;
ptr[1] = (kpt.pt.y-cy) / h;
} }
} }
@@ -1899,6 +1959,7 @@ Transform RegistrationVis::computeTransformationImpl(
} }
info.inliers = inliersCount; info.inliers = inliersCount;
info.inliersRatio = !toSignature.getWords().empty()?float(inliersCount)/float(toSignature.getWords().size()):0;
info.matches = matchesCount; info.matches = matchesCount;
info.rejectedMsg = msg; info.rejectedMsg = msg;
info.covariance = covariance; info.covariance = covariance;
+33 -40
View File
@@ -678,19 +678,6 @@ int Rtabmap::getTotalMemSize() const
return 0; return 0;
} }
std::multimap<int, cv::KeyPoint> Rtabmap::getWords(int locationId) const
{
if(_memory)
{
const Signature * s = _memory->getSignature(locationId);
if(s)
{
return s->getWords();
}
}
return std::multimap<int, cv::KeyPoint>();
}
bool Rtabmap::isInSTM(int locationId) const bool Rtabmap::isInSTM(int locationId) const
{ {
if(_memory) if(_memory)
@@ -713,25 +700,7 @@ const Statistics & Rtabmap::getStatistics() const
{ {
return statistics_; return statistics_;
} }
/*
bool Rtabmap::getMetricData(int locationId, cv::Mat & rgb, cv::Mat & depth, float & depthConstant, Transform & pose, Transform & localTransform) const
{
if(_memory)
{
const Signature * s = _memory->getSignature(locationId);
if(s && _optimizedPoses.find(s->id()) != _optimizedPoses.end())
{
rgb = s->getImage();
depth = s->getDepth();
depthConstant = s->getDepthConstant();
pose = _optimizedPoses.at(s->id());
localTransform = s->getLocalTransform();
return true;
}
}
return false;
}
*/
Transform Rtabmap::getPose(int locationId) const Transform Rtabmap::getPose(int locationId) const
{ {
return uValue(_optimizedPoses, locationId, Transform()); return uValue(_optimizedPoses, locationId, Transform());
@@ -2235,6 +2204,7 @@ bool Rtabmap::process(
//============================================================ //============================================================
std::list<std::pair<int, int> > loopClosureLinksAdded; std::list<std::pair<int, int> > loopClosureLinksAdded;
int loopClosureVisualInliers = 0; // for statistics int loopClosureVisualInliers = 0; // for statistics
float loopClosureVisualInliersRatio = 0.0f;
int loopClosureVisualMatches = 0; int loopClosureVisualMatches = 0;
float loopClosureLinearVariance = 0.0f; float loopClosureLinearVariance = 0.0f;
float loopClosureAngularVariance = 0.0f; float loopClosureAngularVariance = 0.0f;
@@ -2386,6 +2356,7 @@ bool Rtabmap::process(
lastProximitySpaceClosureId = nearestId; lastProximitySpaceClosureId = nearestId;
loopClosureVisualInliers = info.inliers; loopClosureVisualInliers = info.inliers;
loopClosureVisualInliersRatio = info.inliersRatio;
loopClosureVisualMatches = info.matches; loopClosureVisualMatches = info.matches;
loopClosureLinearVariance = 1.0/information.at<double>(0,0); loopClosureLinearVariance = 1.0/information.at<double>(0,0);
@@ -2589,6 +2560,7 @@ bool Rtabmap::process(
loopClosureVisualInliersDistribution = info.inliersDistribution; loopClosureVisualInliersDistribution = info.inliersDistribution;
loopClosureVisualInliers = info.inliers; loopClosureVisualInliers = info.inliers;
loopClosureVisualInliersRatio = info.inliersRatio;
loopClosureVisualMatches = info.matches; loopClosureVisualMatches = info.matches;
rejectedGlobalLoopClosure = transform.isNull(); rejectedGlobalLoopClosure = transform.isNull();
if(rejectedGlobalLoopClosure) if(rejectedGlobalLoopClosure)
@@ -3167,6 +3139,7 @@ bool Rtabmap::process(
statistics_.addStatistic(Statistics::kLoopReactivate_id(), retrievalId); statistics_.addStatistic(Statistics::kLoopReactivate_id(), retrievalId);
statistics_.addStatistic(Statistics::kLoopHypothesis_ratio(), hypothesisRatio); statistics_.addStatistic(Statistics::kLoopHypothesis_ratio(), hypothesisRatio);
statistics_.addStatistic(Statistics::kLoopVisual_inliers(), loopClosureVisualInliers); statistics_.addStatistic(Statistics::kLoopVisual_inliers(), loopClosureVisualInliers);
statistics_.addStatistic(Statistics::kLoopVisual_inliers_ratio(), loopClosureVisualInliersRatio);
statistics_.addStatistic(Statistics::kLoopVisual_matches(), loopClosureVisualMatches); statistics_.addStatistic(Statistics::kLoopVisual_matches(), loopClosureVisualMatches);
statistics_.addStatistic(Statistics::kLoopLinear_variance(), loopClosureLinearVariance); statistics_.addStatistic(Statistics::kLoopLinear_variance(), loopClosureLinearVariance);
statistics_.addStatistic(Statistics::kLoopAngular_variance(), loopClosureAngularVariance); statistics_.addStatistic(Statistics::kLoopAngular_variance(), loopClosureAngularVariance);
@@ -3315,6 +3288,13 @@ bool Rtabmap::process(
if(_publishRAMUsage) if(_publishRAMUsage)
{ {
statistics_.addStatistic(Statistics::kMemoryRAM_usage(), UProcessInfo::getMemoryUsage()/(1024*1024)); statistics_.addStatistic(Statistics::kMemoryRAM_usage(), UProcessInfo::getMemoryUsage()/(1024*1024));
long estimatedMemoryUsage = sizeof(Rtabmap);
estimatedMemoryUsage += _optimizedPoses.size() * (sizeof(int) + sizeof(Transform) + 12 * sizeof(float) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, Transform>);
estimatedMemoryUsage += _constraints.size() * (sizeof(int) + sizeof(Transform) + 12 * sizeof(float) + sizeof(cv::Mat) + 36 * sizeof(double) + sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, Link>);
estimatedMemoryUsage += _memory->getMemoryUsed();
estimatedMemoryUsage += _bayesFilter->getMemoryUsed();
estimatedMemoryUsage += _parameters.size()*(sizeof(std::string)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(ParametersMap);
statistics_.addStatistic(Statistics::kMemoryRAM_estimated(), (float)(estimatedMemoryUsage/(1024*1024)));//MB
} }
if(_publishLikelihood || _publishPdf) if(_publishLikelihood || _publishPdf)
@@ -4463,18 +4443,30 @@ Signature Rtabmap::getSignatureCopy(int id, bool images, bool scan, bool userDat
groundTruth, groundTruth,
data); data);
std::multimap<int, Link> links = _memory->getLinks(id, true, true);
for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
{
if(iter->second.type() == Link::kLandmark)
{
s.addLandmark(iter->second);
}
else
{
s.addLink(iter->second);
}
}
if(withWords || withGlobalDescriptors) if(withWords || withGlobalDescriptors)
{ {
std::multimap<int, cv::KeyPoint> words; std::multimap<int, int> words;
std::multimap<int, cv::Point3f> words3; std::vector<cv::KeyPoint> wordsKpts;
std::multimap<int, cv::Mat> wordsDescriptors; std::vector<cv::Point3f> words3;
cv::Mat wordsDescriptors;
std::vector<rtabmap::GlobalDescriptor> globalDescriptors; std::vector<rtabmap::GlobalDescriptor> globalDescriptors;
_memory->getNodeWordsAndGlobalDescriptors(id, words, words3, wordsDescriptors, globalDescriptors); _memory->getNodeWordsAndGlobalDescriptors(id, words, wordsKpts, words3, wordsDescriptors, globalDescriptors);
if(withWords) if(withWords)
{ {
s.setWords(words); s.setWords(words, wordsKpts, words3, wordsDescriptors);
s.setWords3(words3);
s.setWordsDescriptors(wordsDescriptors);
} }
if(withGlobalDescriptors) if(withGlobalDescriptors)
{ {
@@ -4620,7 +4612,7 @@ int Rtabmap::detectMoreLoopClosures(
std::map<int, Transform> posesToCheckLoopClosures; std::map<int, Transform> posesToCheckLoopClosures;
std::map<int, Transform> poses; std::map<int, Transform> poses;
std::multimap<int, Link> links; std::multimap<int, Link> links;
std::map<int, Signature> signatures; std::map<int, Signature> signatures; // some signatures may be in LTM, get them all
this->getGraph(poses, links, true, true, &signatures); this->getGraph(poses, links, true, true, &signatures);
std::map<int, int> mapIds; std::map<int, int> mapIds;
@@ -4706,6 +4698,7 @@ int Rtabmap::detectMoreLoopClosures(
if(!t.isNull()) if(!t.isNull())
{ {
UWARN(t.prettyPrint().c_str());
bool updateConstraints = true; bool updateConstraints = true;
if(_optimizationMaxError > 0.0f) if(_optimizationMaxError > 0.0f)
{ {
+5 -4
View File
@@ -763,9 +763,10 @@ void SensorData::setFeatures(const std::vector<cv::KeyPoint> & keypoints, const
_descriptors = descriptors; _descriptors = descriptors;
} }
long SensorData::getMemoryUsed() const // Return memory usage in Bytes unsigned long SensorData::getMemoryUsed() const // Return memory usage in Bytes
{ {
return _imageCompressed.total()*_imageCompressed.elemSize() + return sizeof(SensorData) +
_imageCompressed.total()*_imageCompressed.elemSize() +
_imageRaw.total()*_imageRaw.elemSize() + _imageRaw.total()*_imageRaw.elemSize() +
_depthOrRightCompressed.total()*_depthOrRightCompressed.elemSize() + _depthOrRightCompressed.total()*_depthOrRightCompressed.elemSize() +
_depthOrRightRaw.total()*_depthOrRightRaw.elemSize() + _depthOrRightRaw.total()*_depthOrRightRaw.elemSize() +
@@ -779,8 +780,8 @@ long SensorData::getMemoryUsed() const // Return memory usage in Bytes
_obstacleCellsRaw.total()*_obstacleCellsRaw.elemSize()+ _obstacleCellsRaw.total()*_obstacleCellsRaw.elemSize()+
_emptyCellsCompressed.total()*_emptyCellsCompressed.elemSize() + _emptyCellsCompressed.total()*_emptyCellsCompressed.elemSize() +
_emptyCellsRaw.total()*_emptyCellsRaw.elemSize()+ _emptyCellsRaw.total()*_emptyCellsRaw.elemSize()+
_keypoints.size() * sizeof(float) * 7 + _keypoints.size() * sizeof(cv::KeyPoint) +
_keypoints3D.size() * sizeof(float)*3 + _keypoints3D.size() * sizeof(cv::Point3f) +
_descriptors.total()*_descriptors.elemSize(); _descriptors.total()*_descriptors.elemSize();
} }
+66 -41
View File
@@ -132,6 +132,18 @@ bool Signature::hasLink(int idTo, Link::Type type) const
{ {
return _links.find(idTo) != _links.end(); return _links.find(idTo) != _links.end();
} }
if(idTo==0)
{
for(std::multimap<int, Link>::const_iterator iter=_links.begin(); iter!=_links.end(); ++iter)
{
if(type == iter->second.type())
{
return true;
}
}
}
else
{
for(std::multimap<int, Link>::const_iterator iter=_links.find(idTo); iter!=_links.end() && iter->first == idTo; ++iter) for(std::multimap<int, Link>::const_iterator iter=_links.find(idTo); iter!=_links.end() && iter->first == idTo; ++iter)
{ {
if(type == iter->second.type()) if(type == iter->second.type())
@@ -139,6 +151,7 @@ bool Signature::hasLink(int idTo, Link::Type type) const
return true; return true;
} }
} }
}
return false; return false;
} }
@@ -209,11 +222,11 @@ void Signature::removeVirtualLinks()
float Signature::compareTo(const Signature & s) const float Signature::compareTo(const Signature & s) const
{ {
float similarity = 0.0f; float similarity = 0.0f;
const std::multimap<int, cv::KeyPoint> & words = s.getWords(); const std::multimap<int, int> & words = s.getWords();
if(!s.isBadSignature() && !this->isBadSignature()) if(!s.isBadSignature() && !this->isBadSignature())
{ {
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > pairs; std::list<std::pair<int, std::pair<int, int> > > pairs;
int totalWords = ((int)_words.size()-_invalidWordsCount)>((int)words.size()-s.getInvalidWordsCount())?((int)_words.size()-_invalidWordsCount):((int)words.size()-s.getInvalidWordsCount()); int totalWords = ((int)_words.size()-_invalidWordsCount)>((int)words.size()-s.getInvalidWordsCount())?((int)_words.size()-_invalidWordsCount):((int)words.size()-s.getInvalidWordsCount());
UASSERT(totalWords > 0); UASSERT(totalWords > 0);
EpipolarGeometry::findPairs(words, _words, pairs); EpipolarGeometry::findPairs(words, _words, pairs);
@@ -225,11 +238,9 @@ float Signature::compareTo(const Signature & s) const
void Signature::changeWordsRef(int oldWordId, int activeWordId) void Signature::changeWordsRef(int oldWordId, int activeWordId)
{ {
std::list<cv::KeyPoint> kps = uValues(_words, oldWordId); std::list<int> words = uValues(_words, oldWordId);
if(kps.size()) if(words.size())
{ {
std::list<cv::Point3f> pts = uValues(_words3, oldWordId);
std::list<cv::Mat> descriptors = uValues(_wordsDescriptors, oldWordId);
if(oldWordId<=0) if(oldWordId<=0)
{ {
_invalidWordsCount-=(int)_words.erase(oldWordId); _invalidWordsCount-=(int)_words.erase(oldWordId);
@@ -239,37 +250,41 @@ void Signature::changeWordsRef(int oldWordId, int activeWordId)
{ {
_words.erase(oldWordId); _words.erase(oldWordId);
} }
_words3.erase(oldWordId);
_wordsDescriptors.erase(oldWordId);
_wordsChanged.insert(std::make_pair(oldWordId, activeWordId)); _wordsChanged.insert(std::make_pair(oldWordId, activeWordId));
for(std::list<cv::KeyPoint>::const_iterator iter=kps.begin(); iter!=kps.end(); ++iter) for(std::list<int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
{ {
_words.insert(std::pair<int, cv::KeyPoint>(activeWordId, (*iter))); _words.insert(std::pair<int, int>(activeWordId, (*iter)));
}
for(std::list<cv::Point3f>::const_iterator iter=pts.begin(); iter!=pts.end(); ++iter)
{
_words3.insert(std::pair<int, cv::Point3f>(activeWordId, (*iter)));
}
for(std::list<cv::Mat>::const_iterator iter=descriptors.begin(); iter!=descriptors.end(); ++iter)
{
_wordsDescriptors.insert(std::pair<int, cv::Mat>(activeWordId, (*iter)));
} }
} }
} }
void Signature::setWords(const std::multimap<int, cv::KeyPoint> & words) void Signature::setWords(const std::multimap<int, int> & words,
const std::vector<cv::KeyPoint> & keypoints,
const std::vector<cv::Point3f> & points,
const cv::Mat & descriptors)
{ {
_enabled = false; UASSERT_MSG(descriptors.empty() || descriptors.rows == (int)words.size(), uFormat("words=%d, descriptors=%d", (int)words.size(), descriptors.rows).c_str());
_words = words; UASSERT_MSG(points.empty() || points.size() == words.size(), uFormat("words=%d, points=%d", (int)words.size(), (int)points.size()).c_str());
UASSERT_MSG(keypoints.empty() || keypoints.size() == words.size(), uFormat("words=%d, descriptors=%d", (int)words.size(), (int)keypoints.size()).c_str());
UASSERT(words.empty() || !keypoints.empty() || !points.empty() || !descriptors.empty());
_invalidWordsCount = 0; _invalidWordsCount = 0;
for(std::multimap<int, cv::KeyPoint>::iterator iter=_words.begin(); iter!=_words.end(); ++iter) for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
{ {
if(iter->first>0) if(iter->first<=0)
{ {
break;
}
++_invalidWordsCount; ++_invalidWordsCount;
} }
// make sure indexes are all valid!
UASSERT_MSG(iter->second >=0 && iter->second < (int)words.size(), uFormat("iter->second=%d words.size()=%d", iter->second, (int)words.size()).c_str());
}
_enabled = false;
_words = words;
_wordsKpts = keypoints;
_words3 = points;
_wordsDescriptors = descriptors.clone();
} }
bool Signature::isBadSignature() const bool Signature::isBadSignature() const
@@ -280,24 +295,30 @@ bool Signature::isBadSignature() const
void Signature::removeAllWords() void Signature::removeAllWords()
{ {
_words.clear(); _words.clear();
_wordsKpts.clear();
_words3.clear(); _words3.clear();
_wordsDescriptors.clear(); _wordsDescriptors = cv::Mat();
_invalidWordsCount = 0; _invalidWordsCount = 0;
} }
void Signature::removeWord(int wordId) void Signature::setWordsDescriptors(const cv::Mat & descriptors)
{ {
if(wordId<=0) if(descriptors.empty())
{ {
_invalidWordsCount-=(int)_words.erase(wordId); if(_wordsKpts.empty() && _words3.empty())
UASSERT(_invalidWordsCount>=0); {
removeAllWords();
} }
else else
{ {
_words.erase(wordId); _wordsDescriptors = cv::Mat();
}
}
else
{
UASSERT(descriptors.rows == (int)_words.size());
_wordsDescriptors = descriptors.clone();
} }
_words3.erase(wordId);
_wordsDescriptors.clear();
} }
cv::Mat Signature::getPoseCovariance() const cv::Mat Signature::getPoseCovariance() const
@@ -321,19 +342,23 @@ cv::Mat Signature::getPoseCovariance() const
return covariance; return covariance;
} }
long Signature::getMemoryUsed(bool withSensorData) const // Return memory usage in Bytes unsigned long Signature::getMemoryUsed(bool withSensorData) const // Return memory usage in Bytes
{ {
long total = _words.size() * sizeof(float) * 8 + unsigned long total = sizeof(Signature);
_words3.size() * sizeof(float) * 4; total += _words.size() * (sizeof(int)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(std::multimap<int, cv::KeyPoint>);
if(!_wordsDescriptors.empty()) total += _wordsKpts.size() * sizeof(cv::KeyPoint) + sizeof(std::vector<cv::KeyPoint>);
{ total += _words3.size() * sizeof(cv::Point3f) + sizeof(std::vector<cv::Point3f>);
total += _wordsDescriptors.size() * sizeof(int); total += _wordsDescriptors.total() * _wordsDescriptors.elemSize() + sizeof(cv::Mat);
total += _wordsDescriptors.size() * _wordsDescriptors.begin()->second.total() * _wordsDescriptors.begin()->second.elemSize(); total += _wordsChanged.size() * (sizeof(int)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, int>);
}
if(withSensorData) if(withSensorData)
{ {
total+=_sensorData.getMemoryUsed(); total+=_sensorData.getMemoryUsed();
} }
total += _pose.size() * (sizeof(Transform) + sizeof(float)*12);
total += _groundTruthPose.size() * (sizeof(Transform) + sizeof(float)*12);
total += _velocity.size() * sizeof(float);
total += _links.size() * (sizeof(int) + sizeof(Transform) + 12 * sizeof(float) + sizeof(cv::Mat) + 36 * sizeof(double)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::multimap<int, Link>);
total += _landmarks.size() * (sizeof(int) + sizeof(Transform) + 12 * sizeof(float) + sizeof(cv::Mat) + 36 * sizeof(double)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, Link>);
return total; return total;
} }
+40 -4
View File
@@ -330,8 +330,11 @@ bool VWDictionary::setNNStrategy(NNStrategy strategy)
bool update = _strategy != strategy; bool update = _strategy != strategy;
_strategy = strategy; _strategy = strategy;
if(update) if(update)
{
if(_notIndexedWords.size() != _visualWords.size() || !_dataTree.empty())
{ {
UINFO("Nearest neighbor strategy has changed, re-initialize search tree."); UINFO("Nearest neighbor strategy has changed, re-initialize search tree.");
}
_dataTree = cv::Mat(); _dataTree = cv::Mat();
_notIndexedWords = uKeysSet(_visualWords); _notIndexedWords = uKeysSet(_visualWords);
_removedIndexedWords.clear(); _removedIndexedWords.clear();
@@ -363,6 +366,38 @@ unsigned int VWDictionary::getIndexMemoryUsed() const
return _flannIndex->memoryUsed(); return _flannIndex->memoryUsed();
} }
unsigned long VWDictionary::getMemoryUsed(bool estimate) const
{
long memoryUsage = sizeof(VWDictionary);
memoryUsage += getIndexMemoryUsed();
memoryUsage += _dataTree.total()*_dataTree.elemSize();
if(estimate)
{
if(!_visualWords.empty())
{
memoryUsage += _visualWords.size()*(sizeof(int) + _visualWords.begin()->second->getMemoryUsed()+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, VisualWord *>);
}
}
else
{
for(std::map<int, VisualWord *>::const_iterator iter=_visualWords.begin(); iter!=_visualWords.end(); ++iter)
{
memoryUsage += sizeof(int) + iter->second->getMemoryUsed();
}
memoryUsage += _visualWords.size()*(sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, VisualWord *>);
}
if(!_unusedWords.empty())
{
// they are the same words than in _visualWords, so just add the pointer size
memoryUsage += _unusedWords.size()*(sizeof(int) + sizeof(VisualWord *)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int, VisualWord *>);
}
memoryUsage += _mapIndexId.size() * (sizeof(int)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int ,int>);
memoryUsage += _mapIdIndex.size() * (sizeof(int)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int ,int>);
memoryUsage += _notIndexedWords.size() * (sizeof(int)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::set<int>);
memoryUsage += _removedIndexedWords.size() * (sizeof(int)+sizeof(std::_Rb_tree_node_base)) + sizeof(std::set<int>);
return memoryUsage;
}
cv::Mat VWDictionary::convertBinTo32F(const cv::Mat & descriptorsIn, bool byteToFloat) cv::Mat VWDictionary::convertBinTo32F(const cv::Mat & descriptorsIn, bool byteToFloat)
{ {
if(byteToFloat) if(byteToFloat)
@@ -521,7 +556,8 @@ void VWDictionary::update()
{ {
UASSERT(descriptor.cols == _flannIndex->featuresDim()); UASSERT(descriptor.cols == _flannIndex->featuresDim());
UASSERT(descriptor.type() == _flannIndex->featuresType()); UASSERT(descriptor.type() == _flannIndex->featuresType());
index = _flannIndex->addPoints(descriptor); UASSERT(descriptor.rows == 1);
index = _flannIndex->addPoints(descriptor).front();
} }
std::pair<std::map<int, int>::iterator, bool> inserted; std::pair<std::map<int, int>::iterator, bool> inserted;
inserted = _mapIndexId.insert(std::pair<int, int>(index, w->id())); inserted = _mapIndexId.insert(std::pair<int, int>(index, w->id()));
@@ -628,15 +664,15 @@ void VWDictionary::update()
switch(_strategy) switch(_strategy)
{ {
case kNNFlannNaive: case kNNFlannNaive:
_flannIndex->buildLinearIndex(_dataTree, useDistanceL1_, _rebalancingFactor); _flannIndex->buildLinearIndex(_dataTree, useDistanceL1_, _incrementalDictionary&&_incrementalFlann?_rebalancingFactor:1);
break; break;
case kNNFlannKdTree: case kNNFlannKdTree:
UASSERT_MSG(type == CV_32F, "To use KdTree dictionary, float descriptors are required!"); UASSERT_MSG(type == CV_32F, "To use KdTree dictionary, float descriptors are required!");
_flannIndex->buildKDTreeIndex(_dataTree, KDTREE_SIZE, useDistanceL1_, _rebalancingFactor); _flannIndex->buildKDTreeIndex(_dataTree, KDTREE_SIZE, useDistanceL1_, _incrementalDictionary&&_incrementalFlann?_rebalancingFactor:1);
break; break;
case kNNFlannLSH: case kNNFlannLSH:
UASSERT_MSG(type == CV_8U, "To use LSH dictionary, binary descriptors are required!"); UASSERT_MSG(type == CV_8U, "To use LSH dictionary, binary descriptors are required!");
_flannIndex->buildLSHIndex(_dataTree, 12, 20, 2, _rebalancingFactor); _flannIndex->buildLSHIndex(_dataTree, 12, 20, 2, _incrementalDictionary&&_incrementalFlann?_rebalancingFactor:1);
break; break;
default: default:
break; break;
+9
View File
@@ -69,4 +69,13 @@ int VisualWord::removeAllRef(int signatureId)
return removed; return removed;
} }
unsigned long VisualWord::getMemoryUsed() const
{
unsigned long memoryUsage = sizeof(VisualWord);
memoryUsage += _references.size() * (sizeof(int)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int ,int>);
memoryUsage += _oldReferences.size() * (sizeof(int)*2+sizeof(std::_Rb_tree_node_base)) + sizeof(std::map<int ,int>);
memoryUsage += _descriptor.total() * _descriptor.elemSize();
return memoryUsage;
}
} // namespace rtabmap } // namespace rtabmap
+19 -14
View File
@@ -137,9 +137,7 @@ Transform OdometryF2F::computeTransform(
{ {
tmpRefFrame = refFrame_; tmpRefFrame = refFrame_;
// reset matches, but keep already extracted features in newFrame.sensorData() // reset matches, but keep already extracted features in newFrame.sensorData()
newFrame.setWords(std::multimap<int, cv::KeyPoint>()); newFrame.removeAllWords();
newFrame.setWords3(std::multimap<int, cv::Point3f>());
newFrame.setWordsDescriptors(std::multimap<int, cv::Mat>());
UWARN("Failed to find a transformation with the provided guess (%s), trying again without a guess.", guess.prettyPrint().c_str()); UWARN("Failed to find a transformation with the provided guess (%s), trying again without a guess.", guess.prettyPrint().c_str());
// If optical flow is used, switch temporary to feature matching // If optical flow is used, switch temporary to feature matching
int visCorTypeBackup = Parameters::defaultVisCorType(); int visCorTypeBackup = Parameters::defaultVisCorType();
@@ -176,18 +174,18 @@ Transform OdometryF2F::computeTransform(
if(info && this->isInfoDataFilled()) if(info && this->isInfoDataFilled())
{ {
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > pairs; std::list<std::pair<int, std::pair<int, int> > > pairs;
EpipolarGeometry::findPairsUnique(tmpRefFrame.getWords(), newFrame.getWords(), pairs); EpipolarGeometry::findPairsUnique(tmpRefFrame.getWords(), newFrame.getWords(), pairs);
info->refCorners.resize(pairs.size()); info->refCorners.resize(pairs.size());
info->newCorners.resize(pairs.size()); info->newCorners.resize(pairs.size());
std::map<int, int> idToIndex; std::map<int, int> idToIndex;
int i=0; int i=0;
for(std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > >::iterator iter=pairs.begin(); for(std::list<std::pair<int, std::pair<int, int> > >::iterator iter=pairs.begin();
iter!=pairs.end(); iter!=pairs.end();
++iter) ++iter)
{ {
info->refCorners[i] = iter->second.first.pt; info->refCorners[i] = tmpRefFrame.getWordsKpts()[iter->second.first].pt;
info->newCorners[i] = iter->second.second.pt; info->newCorners[i] = newFrame.getWordsKpts()[iter->second.second].pt;
idToIndex.insert(std::make_pair(iter->first, i)); idToIndex.insert(std::make_pair(iter->first, i));
++i; ++i;
} }
@@ -199,12 +197,21 @@ Transform OdometryF2F::computeTransform(
} }
Transform t = this->getPose()*motionSinceLastKeyFrame.inverse(); Transform t = this->getPose()*motionSinceLastKeyFrame.inverse();
for(std::multimap<int, cv::Point3f>::const_iterator iter=tmpRefFrame.getWords3().begin(); iter!=tmpRefFrame.getWords3().end(); ++iter) if(!tmpRefFrame.getWords3().empty())
{ {
info->localMap.insert(std::make_pair(iter->first, util3d::transformPoint(iter->second, t))); for(std::multimap<int, int>::const_iterator iter=tmpRefFrame.getWords().begin(); iter!=tmpRefFrame.getWords().end(); ++iter)
{
info->localMap.insert(std::make_pair(iter->first, util3d::transformPoint(tmpRefFrame.getWords3()[iter->second], t)));
}
} }
info->localMapSize = tmpRefFrame.getWords3().size(); info->localMapSize = tmpRefFrame.getWords3().size();
info->words = newFrame.getWords(); if(!newFrame.getWordsKpts().empty())
{
for(std::multimap<int, int>::const_iterator iter=newFrame.getWords().begin(); iter!=newFrame.getWords().end(); ++iter)
{
info->words.insert(std::make_pair(iter->first, newFrame.getWordsKpts()[iter->second]));
}
}
info->localScanMapSize = tmpRefFrame.sensorData().laserScanRaw().size(); info->localScanMapSize = tmpRefFrame.sensorData().laserScanRaw().size();
@@ -232,7 +239,7 @@ Transform OdometryF2F::computeTransform(
(registrationPipeline_->isScanRequired() && (scanKeyFrameThr_ == 0.0f || regInfo.icpInliersRatio <= scanKeyFrameThr_))) (registrationPipeline_->isScanRequired() && (scanKeyFrameThr_ == 0.0f || regInfo.icpInliersRatio <= scanKeyFrameThr_)))
{ {
UDEBUG("Update key frame"); UDEBUG("Update key frame");
int features = newFrame.getWordsDescriptors().size(); int features = newFrame.getWordsDescriptors().rows;
if(registrationPipeline_->isImageRequired() && features == 0) if(registrationPipeline_->isImageRequired() && features == 0)
{ {
newFrame = Signature(data); newFrame = Signature(data);
@@ -251,9 +258,7 @@ Transform OdometryF2F::computeTransform(
{ {
refFrame_ = newFrame; refFrame_ = newFrame;
refFrame_.setWords(std::multimap<int, cv::KeyPoint>()); refFrame_.removeAllWords();
refFrame_.setWords3(std::multimap<int, cv::Point3f>());
refFrame_.setWordsDescriptors(std::multimap<int, cv::Mat>());
//reset motion //reset motion
lastKeyFramePose_.setNull(); lastKeyFramePose_.setNull();
+148 -83
View File
@@ -133,6 +133,27 @@ OdometryF2M::OdometryF2M(const ParametersMap & parameters) :
} }
uInsert(bundleParameters, ParametersPair(Parameters::kVisCorType(), uNumber2Str(corType))); uInsert(bundleParameters, ParametersPair(Parameters::kVisCorType(), uNumber2Str(corType)));
int estType = Parameters::defaultVisEstimationType();
Parameters::parse(parameters, Parameters::kVisEstimationType(), estType);
if(estType > 1)
{
UWARN("%s=%d is not supported by OdometryF2M, using 2D->3D approach instead (type=1).",
Parameters::kVisEstimationType().c_str(),
estType);
estType = 1;
}
uInsert(bundleParameters, ParametersPair(Parameters::kVisEstimationType(), uNumber2Str(estType)));
bool forwardEst = Parameters::defaultVisForwardEstOnly();
Parameters::parse(parameters, Parameters::kVisForwardEstOnly(), forwardEst);
if(!forwardEst)
{
UWARN("%s=false is not supported by OdometryF2M, setting to true.",
Parameters::kVisForwardEstOnly().c_str());
forwardEst = true;
}
uInsert(bundleParameters, ParametersPair(Parameters::kVisForwardEstOnly(), uBool2Str(forwardEst)));
regPipeline_ = Registration::create(bundleParameters); regPipeline_ = Registration::create(bundleParameters);
if(bundleAdjustment_>0 && regPipeline_->isScanRequired()) if(bundleAdjustment_>0 && regPipeline_->isScanRequired())
{ {
@@ -272,9 +293,7 @@ Transform OdometryF2M::computeTransform(
{ {
tmpMap = *map_; tmpMap = *map_;
// reset matches, but keep already extracted features in lastFrame_->sensorData() // reset matches, but keep already extracted features in lastFrame_->sensorData()
lastFrame_->setWords(std::multimap<int, cv::KeyPoint>()); lastFrame_->removeAllWords();
lastFrame_->setWords3(std::multimap<int, cv::Point3f>());
lastFrame_->setWordsDescriptors(std::multimap<int, cv::Mat>());
points3DMap.clear(); points3DMap.clear();
bundlePoses.clear(); bundlePoses.clear();
@@ -393,11 +412,9 @@ Transform OdometryF2M::computeTransform(
int wordId =regInfo.inliersIDs[i]; int wordId =regInfo.inliersIDs[i];
// 3D point // 3D point
std::multimap<int, cv::Point3f>::const_iterator iter3D = tmpMap.getWords3().find(wordId); std::multimap<int, int>::const_iterator iter3D = tmpMap.getWords().find(wordId);
UASSERT(iter3D!=tmpMap.getWords3().end()); UASSERT(iter3D!=tmpMap.getWords().end() && !tmpMap.getWords3().empty());
points3DMap.insert(*iter3D); points3DMap.insert(std::make_pair(wordId, tmpMap.getWords3()[iter3D->second]));
std::multimap<int, cv::KeyPoint>::const_iterator iter2D = lastFrame_->getWords().find(wordId);
// all other references // all other references
std::map<int, std::map<int, FeatureBA> >::iterator refIter = bundleWordReferences_.find(wordId); std::map<int, std::map<int, FeatureBA> >::iterator refIter = bundleWordReferences_.find(wordId);
@@ -427,12 +444,19 @@ Transform OdometryF2M::computeTransform(
} }
} }
std::multimap<int, int>::const_iterator iter2D = lastFrame_->getWords().find(wordId);
if(iter2D!=lastFrame_->getWords().end()) if(iter2D!=lastFrame_->getWords().end())
{ {
UASSERT(lastFrame_->getWords3().find(wordId) != lastFrame_->getWords3().end()); UASSERT(!lastFrame_->getWordsKpts().empty());
//get depth
float d = 0.0f;
if( !lastFrame_->getWords3().empty() &&
util3d::isFinite(lastFrame_->getWords3()[iter2D->second]))
{
//move back point in camera frame (to get depth along z) //move back point in camera frame (to get depth along z)
cv::Point3f pt3d = util3d::transformPoint(lastFrame_->getWords3().find(wordId)->second, invLocalTransform); d = util3d::transformPoint(lastFrame_->getWords3()[iter2D->second], invLocalTransform).z;
references.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter2D->second, pt3d.z))); }
references.insert(std::make_pair(lastFrame_->id(), FeatureBA(lastFrame_->getWordsKpts()[iter2D->second], d)));
} }
wordReferences.insert(std::make_pair(wordId, references)); wordReferences.insert(std::make_pair(wordId, references));
@@ -557,9 +581,10 @@ Transform OdometryF2M::computeTransform(
// fields to update // fields to update
LaserScan mapScan = tmpMap.sensorData().laserScanRaw(); LaserScan mapScan = tmpMap.sensorData().laserScanRaw();
std::multimap<int, cv::KeyPoint> mapWords = tmpMap.getWords(); std::multimap<int, int> mapWords = tmpMap.getWords();
std::multimap<int, cv::Point3f> mapPoints = tmpMap.getWords3(); std::vector<cv::KeyPoint> mapWordsKpts = tmpMap.getWordsKpts();
std::multimap<int, cv::Mat> mapDescriptors = tmpMap.getWordsDescriptors(); std::vector<cv::Point3f> mapPoints = tmpMap.getWords3();
cv::Mat mapDescriptors = tmpMap.getWordsDescriptors();
bool addVisualKeyFrame = regPipeline_->isImageRequired() && bool addVisualKeyFrame = regPipeline_->isImageRequired() &&
(keyFrameThr_ == 0.0f || (keyFrameThr_ == 0.0f ||
@@ -590,8 +615,9 @@ Transform OdometryF2M::computeTransform(
// update local map // update local map
UASSERT(mapWords.size() == mapPoints.size()); UASSERT(mapWords.size() == mapPoints.size());
UASSERT(mapPoints.size() == mapDescriptors.size()); UASSERT(mapWords.size() == mapWordsKpts.size());
UASSERT_MSG(lastFrame_->getWordsDescriptors().size() == lastFrame_->getWords3().size(), uFormat("%d vs %d", lastFrame_->getWordsDescriptors().size(), lastFrame_->getWords3().size()).c_str()); UASSERT((int)mapPoints.size() == mapDescriptors.rows);
UASSERT_MSG(lastFrame_->getWordsDescriptors().rows == (int)lastFrame_->getWords3().size(), uFormat("%d vs %d", lastFrame_->getWordsDescriptors().rows, (int)lastFrame_->getWords3().size()).c_str());
std::map<int, int>::iterator iterBundlePosesRef = bundlePoseReferences_.end(); std::map<int, int>::iterator iterBundlePosesRef = bundlePoseReferences_.end();
if(bundleAdjustment_>0) if(bundleAdjustment_>0)
@@ -613,17 +639,15 @@ Transform OdometryF2M::computeTransform(
// update local map 3D points (if bundle adjustment was done) // update local map 3D points (if bundle adjustment was done)
for(std::map<int, cv::Point3f>::iterator iter=points3DMap.begin(); iter!=points3DMap.end(); ++iter) for(std::map<int, cv::Point3f>::iterator iter=points3DMap.begin(); iter!=points3DMap.end(); ++iter)
{ {
UASSERT(mapPoints.count(iter->first) == 1); UASSERT(mapWords.count(iter->first) == 1);
//UDEBUG("Updated %d (%f,%f,%f) -> (%f,%f,%f)", iter->first, mapPoints.find(origin)->second.x, mapPoints.find(origin)->second.y, mapPoints.find(origin)->second.z, iter->second.x, iter->second.y, iter->second.z); //UDEBUG("Updated %d (%f,%f,%f) -> (%f,%f,%f)", iter->first, mapPoints[mapWords.find(iter->first)->second].x, mapPoints[mapWords.find(iter->first)->second].y, mapPoints[mapWords.find(iter->first)->second].z, iter->second.x, iter->second.y, iter->second.z);
mapPoints.find(iter->first)->second = iter->second; mapPoints[mapWords.find(iter->first)->second] = iter->second;
} }
} }
// sort by feature response // sort by feature response
std::multimap<float, std::pair<int, std::pair<cv::KeyPoint, std::pair<cv::Point3f, cv::Mat> > > > newIds; std::multimap<float, std::pair<int, std::pair<cv::KeyPoint, std::pair<cv::Point3f, cv::Mat> > > > newIds;
UASSERT(lastFrame_->getWords3().size() == lastFrame_->getWords().size()); UASSERT(lastFrame_->getWords3().size() == lastFrame_->getWords().size());
std::multimap<int, cv::KeyPoint>::const_iterator iter2D = lastFrame_->getWords().begin();
std::multimap<int, cv::Mat>::const_iterator iterDesc = lastFrame_->getWordsDescriptors().begin();
UDEBUG("new frame words3=%d", (int)lastFrame_->getWords3().size()); UDEBUG("new frame words3=%d", (int)lastFrame_->getWords3().size());
std::set<int> seenStatusUpdated; std::set<int> seenStatusUpdated;
Transform invLocalTransform; Transform invLocalTransform;
@@ -648,11 +672,11 @@ Transform OdometryF2M::computeTransform(
if(!visDepthAsMask && validDepthRatio_ < 1.0f) if(!visDepthAsMask && validDepthRatio_ < 1.0f)
{ {
int ptsWithDepth = 0; int ptsWithDepth = 0;
for (std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin(); for (std::vector<cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin();
iter != lastFrame_->getWords3().end(); iter != lastFrame_->getWords3().end();
++iter) ++iter)
{ {
if(util3d::isFinite(iter->second)) if(util3d::isFinite(*iter))
{ {
++ptsWithDepth; ++ptsWithDepth;
} }
@@ -666,27 +690,29 @@ Transform OdometryF2M::computeTransform(
} }
} }
for(std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin(); iter!=lastFrame_->getWords3().end(); ++iter, ++iter2D, ++iterDesc) for(std::multimap<int, int>::const_iterator iter = lastFrame_->getWords().begin(); iter!=lastFrame_->getWords().end(); ++iter)
{ {
if(mapPoints.find(iter->first) == mapPoints.end()) // Point not in map const cv::Point3f & pt = lastFrame_->getWords3()[iter->second];
const cv::KeyPoint & kpt = lastFrame_->getWordsKpts()[iter->second];
if(mapWords.find(iter->first) == mapWords.end()) // Point not in map
{ {
if(util3d::isFinite(iter->second) || addPointsWithoutDepth) if(util3d::isFinite(pt) || addPointsWithoutDepth)
{ {
newIds.insert( newIds.insert(
std::make_pair(iter2D->second.response>0?1.0f/iter2D->second.response:0.0f, std::make_pair(kpt.response>0?1.0f/kpt.response:0.0f,
std::make_pair(iter->first, std::make_pair(iter->first,
std::make_pair(iter2D->second, std::make_pair(kpt,
std::make_pair(iter->second, iterDesc->second))))); std::make_pair(pt, lastFrame_->getWordsDescriptors().row(iter->second))))));
} }
} }
else if(bundleAdjustment_>0) else if(bundleAdjustment_>0)
{ {
if(lastFrame_->getWords().count(iter->first) == 1) if(lastFrame_->getWords().count(iter->first) == 1)
{ {
std::multimap<int, cv::KeyPoint>::iterator iterKpts = mapWords.find(iter->first); std::multimap<int, int>::iterator iterKpts = mapWords.find(iter->first);
if(iterKpts!=mapWords.end()) if(iterKpts!=mapWords.end() && !mapWordsKpts.empty())
{ {
iterKpts->second.octave = iter2D->second.octave; mapWordsKpts[iterKpts->second].octave = kpt.octave;
} }
UASSERT(iterBundlePosesRef!=bundlePoseReferences_.end()); UASSERT(iterBundlePosesRef!=bundlePoseReferences_.end());
@@ -694,19 +720,19 @@ Transform OdometryF2M::computeTransform(
//move back point in camera frame (to get depth along z) //move back point in camera frame (to get depth along z)
float depth = 0.0f; float depth = 0.0f;
if(util3d::isFinite(iter->second)) if(util3d::isFinite(pt))
{ {
depth = util3d::transformPoint(iter->second, invLocalTransform).z; depth = util3d::transformPoint(pt, invLocalTransform).z;
} }
if(bundleWordReferences_.find(iter->first) == bundleWordReferences_.end()) if(bundleWordReferences_.find(iter->first) == bundleWordReferences_.end())
{ {
std::map<int, FeatureBA> framePt; std::map<int, FeatureBA> framePt;
framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter2D->second, depth))); framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(kpt, depth)));
bundleWordReferences_.insert(std::make_pair(iter->first, framePt)); bundleWordReferences_.insert(std::make_pair(iter->first, framePt));
} }
else else
{ {
bundleWordReferences_.find(iter->first)->second.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter2D->second, depth))); bundleWordReferences_.find(iter->first)->second.insert(std::make_pair(lastFrame_->id(), FeatureBA(kpt, depth)));
} }
} }
} }
@@ -747,7 +773,8 @@ Transform OdometryF2M::computeTransform(
} }
} }
mapWords.insert(std::make_pair(iter->second.first, iter->second.second.first)); mapWords.insert(mapWords.end(), std::make_pair(iter->second.first, mapWords.size()));
mapWordsKpts.push_back(iter->second.second.first);
cv::Point3f pt = iter->second.second.second.first; cv::Point3f pt = iter->second.second.second.first;
if(!util3d::isFinite(pt)) if(!util3d::isFinite(pt))
{ {
@@ -783,8 +810,8 @@ Transform OdometryF2M::computeTransform(
float scaleInf = (0.05 * model.fx()) / 0.01; float scaleInf = (0.05 * model.fx()) / 0.01;
pt = util3d::transformPoint(cv::Point3f(ray[0]*scaleInf, ray[1]*scaleInf, ray[2]*scaleInf), model.localTransform()); // in base_link frame pt = util3d::transformPoint(cv::Point3f(ray[0]*scaleInf, ray[1]*scaleInf, ray[2]*scaleInf), model.localTransform()); // in base_link frame
} }
mapPoints.insert(std::make_pair(iter->second.first, util3d::transformPoint(pt, newFramePose))); mapPoints.push_back(util3d::transformPoint(pt, newFramePose));
mapDescriptors.insert(std::make_pair(iter->second.first, iter->second.second.second.second)); mapDescriptors.push_back(iter->second.second.second.second);
if(lastFrameOldestNewId_ > iter->second.first) if(lastFrameOldestNewId_ > iter->second.first)
{ {
lastFrameOldestNewId_ = iter->second.first; lastFrameOldestNewId_ = iter->second.first;
@@ -794,7 +821,7 @@ Transform OdometryF2M::computeTransform(
} }
// remove words in map if max size is reached // remove words in map if max size is reached
if((int)mapPoints.size() > maximumMapSize_) if((int)mapWords.size() > maximumMapSize_)
{ {
// remove oldest outliers first // remove oldest outliers first
std::set<int> inliers(regInfo.inliersIDs.begin(), regInfo.inliersIDs.end()); std::set<int> inliers(regInfo.inliersIDs.begin(), regInfo.inliersIDs.end());
@@ -813,7 +840,7 @@ Transform OdometryF2M::computeTransform(
ids.resize(regInfo.matchesIDs.size()+oi); ids.resize(regInfo.matchesIDs.size()+oi);
UDEBUG("projected added=%d/%d minLastFrameId=%d", oi, (int)regInfo.projectedIDs.size(), lastFrameOldestNewId); UDEBUG("projected added=%d/%d minLastFrameId=%d", oi, (int)regInfo.projectedIDs.size(), lastFrameOldestNewId);
} }
for(unsigned int i=0; i<ids.size() && (int)mapPoints.size() > maximumMapSize_ && mapPoints.size() >= newIds.size(); ++i) for(unsigned int i=0; i<ids.size() && (int)mapWords.size() > maximumMapSize_ && mapWords.size() >= newIds.size(); ++i)
{ {
int id = ids.at(i); int id = ids.at(i);
if(inliers.find(id) == inliers.end()) if(inliers.find(id) == inliers.end())
@@ -831,18 +858,14 @@ Transform OdometryF2M::computeTransform(
bundleWordReferences_.erase(iterRef); bundleWordReferences_.erase(iterRef);
} }
mapPoints.erase(id);
mapDescriptors.erase(id);
mapWords.erase(id); mapWords.erase(id);
++removed; ++removed;
} }
} }
// remove oldest first // remove oldest first
std::multimap<int, cv::Mat>::iterator iterMapDescriptors = mapDescriptors.begin(); for(std::multimap<int, int>::iterator iter = mapWords.begin();
std::multimap<int, cv::KeyPoint>::iterator iterMapWords = mapWords.begin(); iter!=mapWords.end() && (int)mapWords.size() > maximumMapSize_ && mapWords.size() >= newIds.size();)
for(std::multimap<int, cv::Point3f>::iterator iter = mapPoints.begin();
iter!=mapPoints.end() && (int)mapPoints.size() > maximumMapSize_ && mapPoints.size() >= newIds.size();)
{ {
if(inliers.find(iter->first) == inliers.end()) if(inliers.find(iter->first) == inliers.end())
{ {
@@ -859,19 +882,36 @@ Transform OdometryF2M::computeTransform(
bundleWordReferences_.erase(iterRef); bundleWordReferences_.erase(iterRef);
} }
mapPoints.erase(iter++); mapWords.erase(iter++);
mapDescriptors.erase(iterMapDescriptors++);
mapWords.erase(iterMapWords++);
++removed; ++removed;
} }
else else
{ {
++iter; ++iter;
++iterMapDescriptors;
++iterMapWords;
} }
} }
if(mapWords.size() != mapPoints.size())
{
UDEBUG("Remove points");
std::vector<cv::KeyPoint> mapWordsKptsClean(mapWords.size());
std::vector<cv::Point3f> mapPointsClean(mapWords.size());
cv::Mat mapDescriptorsClean(mapWords.size(), mapDescriptors.cols, mapDescriptors.type());
int index = 0;
for(std::multimap<int, int>::iterator iter = mapWords.begin(); iter!=mapWords.end(); ++iter, ++index)
{
mapWordsKptsClean[index] = mapWordsKpts[iter->second];
mapPointsClean[index] = mapPoints[iter->second];
mapDescriptors.row(iter->second).copyTo(mapDescriptorsClean.row(index));
iter->second = index;
}
mapWordsKpts = mapWordsKptsClean;
mapWordsKptsClean.clear();
mapPoints = mapPointsClean;
mapPointsClean.clear();
mapDescriptors = mapDescriptorsClean;
}
Link * previousLink = 0; Link * previousLink = 0;
for(std::map<int, int>::iterator iter=bundlePoseReferences_.begin(); iter!=bundlePoseReferences_.end();) for(std::map<int, int>::iterator iter=bundlePoseReferences_.begin(); iter!=bundlePoseReferences_.end();)
{ {
@@ -1099,9 +1139,7 @@ Transform OdometryF2M::computeTransform(
newFramePose.translation())); newFramePose.translation()));
} }
map_->setWords(mapWords); map_->setWords(mapWords, mapWordsKpts, mapPoints, mapDescriptors);
map_->setWords3(mapPoints);
map_->setWordsDescriptors(mapDescriptors);
} }
} }
@@ -1112,7 +1150,14 @@ Transform OdometryF2M::computeTransform(
info->localScanMapSize = tmpMap.sensorData().laserScanRaw().size(); info->localScanMapSize = tmpMap.sensorData().laserScanRaw().size();
if(this->isInfoDataFilled()) if(this->isInfoDataFilled())
{ {
info->localMap = uMultimapToMap(tmpMap.getWords3()); info->localMap.clear();
if(!tmpMap.getWords3().empty())
{
for(std::multimap<int, int>::const_iterator iter=tmpMap.getWords().begin(); iter!=tmpMap.getWords().end(); ++iter)
{
info->localMap.insert(std::make_pair(iter->first, tmpMap.getWords3()[iter->second]));
}
}
info->localScanMap = tmpMap.sensorData().laserScanRaw(); info->localScanMap = tmpMap.sensorData().laserScanRaw();
} }
} }
@@ -1139,11 +1184,12 @@ Transform OdometryF2M::computeTransform(
if(regPipeline_->isImageRequired()) if(regPipeline_->isImageRequired())
{ {
int ptsWithDepth = 0; int ptsWithDepth = 0;
for (std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin(); for (std::multimap<int, int>::const_iterator iter = lastFrame_->getWords().begin();
iter != lastFrame_->getWords3().end(); iter != lastFrame_->getWords().end();
++iter) ++iter)
{ {
if(util3d::isFinite(iter->second)) if(!lastFrame_->getWords3().empty() &&
util3d::isFinite(lastFrame_->getWords3()[iter->second]))
{ {
++ptsWithDepth; ++ptsWithDepth;
} }
@@ -1153,26 +1199,29 @@ Transform OdometryF2M::computeTransform(
{ {
frameValid = true; frameValid = true;
// update local map // update local map
UASSERT_MSG(lastFrame_->getWordsDescriptors().size() == lastFrame_->getWords3().size(), uFormat("%d vs %d", lastFrame_->getWordsDescriptors().size(), lastFrame_->getWords3().size()).c_str()); UASSERT_MSG(lastFrame_->getWordsDescriptors().rows == (int)lastFrame_->getWords3().size(), uFormat("%d vs %d", lastFrame_->getWordsDescriptors().size(), lastFrame_->getWords3().size()).c_str());
UASSERT(lastFrame_->getWords3().size() == lastFrame_->getWords().size()); UASSERT(lastFrame_->getWords3().size() == lastFrame_->getWords().size());
std::multimap<int, cv::KeyPoint> words; std::multimap<int, int> words;
std::multimap<int, cv::Point3f> transformedPoints; std::vector<cv::KeyPoint> wordsKpts;
std::vector<cv::Point3f> transformedPoints;
std::multimap<int, int> mapPointWeights; std::multimap<int, int> mapPointWeights;
std::multimap<int, cv::Mat> descriptors; cv::Mat descriptors;
UASSERT(lastFrame_->getWords3().size() == lastFrame_->getWordsDescriptors().size()); if(!lastFrame_->getWords3().empty())
std::multimap<int, cv::KeyPoint>::const_iterator wordsIter = lastFrame_->getWords().begin();
std::multimap<int, cv::Mat>::const_iterator descIter = lastFrame_->getWordsDescriptors().begin();
for (std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin();
iter != lastFrame_->getWords3().end();
++iter, ++descIter, ++wordsIter)
{ {
if (util3d::isFinite(iter->second)) for (std::multimap<int, int>::const_iterator iter = lastFrame_->getWords().begin();
iter != lastFrame_->getWords().end();
++iter)
{ {
words.insert(*wordsIter); const cv::Point3f & pt = lastFrame_->getWords3()[iter->second];
transformedPoints.insert(std::make_pair(iter->first, util3d::transformPoint(iter->second, newFramePose))); if (util3d::isFinite(pt))
{
words.insert(words.end(), std::make_pair(iter->first, words.size()));
wordsKpts.push_back(lastFrame_->getWordsKpts()[iter->second]);
transformedPoints.push_back(util3d::transformPoint(pt, newFramePose));
mapPointWeights.insert(std::make_pair(iter->first, 0)); mapPointWeights.insert(std::make_pair(iter->first, 0));
descriptors.insert(*descIter); descriptors.push_back(lastFrame_->getWordsDescriptors().row(iter->second));
}
} }
} }
@@ -1193,7 +1242,9 @@ Transform OdometryF2M::computeTransform(
} }
// update bundleWordReferences_: used for bundle adjustment // update bundleWordReferences_: used for bundle adjustment
for(std::multimap<int, cv::KeyPoint>::const_iterator iter=words.begin(); iter!=words.end(); ++iter) if(!wordsKpts.empty())
{
for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
{ {
if(words.count(iter->first) == 1) if(words.count(iter->first) == 1)
{ {
@@ -1202,18 +1253,20 @@ Transform OdometryF2M::computeTransform(
//get depth //get depth
float d = 0.0f; float d = 0.0f;
if(lastFrame_->getWords3().count(iter->first) == 1 && if(lastFrame_->getWords().count(iter->first) == 1 &&
util3d::isFinite(lastFrame_->getWords3().find(iter->first)->second)) !lastFrame_->getWords3().empty() &&
util3d::isFinite(lastFrame_->getWords3()[lastFrame_->getWords().find(iter->first)->second]))
{ {
//move back point in camera frame (to get depth along z) //move back point in camera frame (to get depth along z)
d = util3d::transformPoint(lastFrame_->getWords3().find(iter->first)->second, invLocalTransform).z; d = util3d::transformPoint(lastFrame_->getWords3()[lastFrame_->getWords().find(iter->first)->second], invLocalTransform).z;
} }
framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter->second, d))); framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(wordsKpts[iter->second], d)));
bundleWordReferences_.insert(std::make_pair(iter->first, framePt)); bundleWordReferences_.insert(std::make_pair(iter->first, framePt));
} }
} }
}
bundlePoseReferences_.insert(std::make_pair(lastFrame_->id(), (int)bundleWordReferences_.size())); bundlePoseReferences_.insert(std::make_pair(lastFrame_->id(), (int)bundleWordReferences_.size()));
@@ -1246,9 +1299,7 @@ Transform OdometryF2M::computeTransform(
} }
} }
map_->setWords(words); map_->setWords(words, wordsKpts, transformedPoints, descriptors);
map_->setWords3(transformedPoints);
map_->setWordsDescriptors(descriptors);
addKeyFrame = true; addKeyFrame = true;
} }
else else
@@ -1347,7 +1398,14 @@ Transform OdometryF2M::computeTransform(
if(this->isInfoDataFilled()) if(this->isInfoDataFilled())
{ {
info->localMap = uMultimapToMap(map_->getWords3()); info->localMap.clear();
if(!map_->getWords3().empty())
{
for(std::multimap<int, int>::const_iterator iter=map_->getWords().begin(); iter!=map_->getWords().end(); ++iter)
{
info->localMap.insert(std::make_pair(iter->first, map_->getWords3()[iter->second]));
}
}
info->localScanMap = map_->sensorData().laserScanRaw(); info->localScanMap = map_->sensorData().laserScanRaw();
} }
} }
@@ -1360,7 +1418,14 @@ Transform OdometryF2M::computeTransform(
{ {
if(regPipeline_->isImageRequired()) if(regPipeline_->isImageRequired())
{ {
info->words = lastFrame_->getWords(); info->words.clear();
if(!lastFrame_->getWordsKpts().empty())
{
for(std::multimap<int, int>::const_iterator iter=lastFrame_->getWords().begin(); iter!=lastFrame_->getWords().end(); ++iter)
{
info->words.insert(std::make_pair(iter->first, lastFrame_->getWordsKpts()[iter->second]));
}
}
} }
} }
} }
+32 -18
View File
@@ -283,15 +283,15 @@ Transform OdometryMono::computeTransform(SensorData & data, const Transform & gu
newCorners[oi] = imagePoints[i]; newCorners[oi] = imagePoints[i];
if(localMap_.count(ids[i]) == 1) if(localMap_.count(ids[i]) == 1)
{ {
if(prevS->getWords().count(ids[i]) == 1) if(prevS->getWords().count(ids[i]) == 1 && !prevS->getWordsKpts().empty())
{ {
// set guess if unique // set guess if unique
refCorners[oi] = prevS->getWords().find(ids[i])->second.pt; refCorners[oi] = prevS->getWordsKpts()[prevS->getWords().find(ids[i])->second].pt;
} }
if(newS->getWords().count(ids[i]) == 1) if(newS->getWords().count(ids[i]) == 1 && !newS->getWordsKpts().empty())
{ {
// set guess if unique // set guess if unique
newCorners[oi] = newS->getWords().find(ids[i])->second.pt; newCorners[oi] = newS->getWordsKpts()[newS->getWords().find(ids[i])->second].pt;
} }
} }
objectPointsTmp[oi] = objectPoints[i]; objectPointsTmp[oi] = objectPoints[i];
@@ -338,9 +338,9 @@ Transform OdometryMono::computeTransform(SensorData & data, const Transform & gu
if(this->isInfoDataFilled() && info) if(this->isInfoDataFilled() && info)
{ {
cv::KeyPoint kpt; cv::KeyPoint kpt;
if(newS->getWords().count(matches[i]) == 1) if(newS->getWords().count(matches[i]) == 1 && !newS->getWordsKpts().empty())
{ {
kpt = newS->getWords().find(matches[i])->second; kpt = newS->getWordsKpts()[newS->getWords().find(matches[i])->second];
} }
kpt.pt = newCorners[i]; kpt.pt = newCorners[i];
info->words.insert(std::make_pair(matches[i], kpt)); info->words.insert(std::make_pair(matches[i], kpt));
@@ -437,9 +437,9 @@ Transform OdometryMono::computeTransform(SensorData & data, const Transform & gu
for(std::set<int>::iterator iter = memory_->getStMem().begin(); iter!=memory_->getStMem().end(); ++iter) for(std::set<int>::iterator iter = memory_->getStMem().begin(); iter!=memory_->getStMem().end(); ++iter)
{ {
const Signature * s = memory_->getSignature(*iter); const Signature * s = memory_->getSignature(*iter);
for(std::multimap<int, cv::KeyPoint>::const_iterator jter=s->getWords().begin(); jter!=s->getWords().end(); ++jter) for(std::multimap<int, int>::const_iterator jter=s->getWords().begin(); jter!=s->getWords().end(); ++jter)
{ {
if(s->getWords().count(jter->first) == 1 && localMap_.find(jter->first)!=localMap_.end()) if(s->getWords().count(jter->first) == 1 && localMap_.find(jter->first)!=localMap_.end() && !s->getWordsKpts().empty())
{ {
if(wordReferences.find(jter->first)==wordReferences.end()) if(wordReferences.find(jter->first)==wordReferences.end())
{ {
@@ -451,7 +451,8 @@ Transform OdometryMono::computeTransform(SensorData & data, const Transform & gu
{ {
depth = keyFrameWords3D_.at(s->id()).at(jter->first).x; depth = keyFrameWords3D_.at(s->id()).at(jter->first).x;
} }
wordReferences.at(jter->first).insert(std::make_pair(s->id(), FeatureBA(jter->second, depth, cv::Mat()))); const cv::KeyPoint & kpts = s->getWordsKpts()[jter->second];
wordReferences.at(jter->first).insert(std::make_pair(s->id(), FeatureBA(kpts, depth, cv::Mat())));
} }
} }
} }
@@ -502,9 +503,21 @@ Transform OdometryMono::computeTransform(SensorData & data, const Transform & gu
} }
else if(float(inliers)/float(imagePoints.size()) < keyFrameThr_) else if(float(inliers)/float(imagePoints.size()) < keyFrameThr_)
{ {
std::map<int, int> uniqueWordsPrevious = uMultimapToMapUnique(previousS->getWords());
std::map<int, int> uniqueWordsNew = uMultimapToMapUnique(newS->getWords());
std::map<int, cv::KeyPoint> wordsPrevious;
std::map<int, cv::KeyPoint> wordsNew;
for(std::map<int, int>::iterator iter=uniqueWordsPrevious.begin(); iter!=uniqueWordsPrevious.end(); ++iter)
{
wordsPrevious.insert(std::make_pair(iter->first, previousS->getWordsKpts()[iter->second]));
}
for(std::map<int, int>::iterator iter=uniqueWordsNew.begin(); iter!=uniqueWordsNew.end(); ++iter)
{
wordsNew.insert(std::make_pair(iter->first, newS->getWordsKpts()[iter->second]));
}
std::map<int, cv::Point3f> inliers3D = util3d::generateWords3DMono( std::map<int, cv::Point3f> inliers3D = util3d::generateWords3DMono(
uMultimapToMapUnique(previousS->getWords()), wordsPrevious,
uMultimapToMapUnique(newS->getWords()), wordsNew,
cameraModel, cameraModel,
cameraTransform, cameraTransform,
fundMatrixReprojError_, fundMatrixReprojError_,
@@ -626,9 +639,9 @@ Transform OdometryMono::computeTransform(SensorData & data, const Transform & gu
int ii=0; int ii=0;
for(std::map<int, cv::Point2f>::iterator iter=firstFrameGuessCorners_.begin(); iter!=firstFrameGuessCorners_.end(); ++iter) for(std::map<int, cv::Point2f>::iterator iter=firstFrameGuessCorners_.begin(); iter!=firstFrameGuessCorners_.end(); ++iter)
{ {
std::multimap<int, cv::KeyPoint>::const_iterator jter=refS->getWords().find(iter->first); std::multimap<int, int>::const_iterator jter=refS->getWords().find(iter->first);
UASSERT(jter != refS->getWords().end()); UASSERT(jter != refS->getWords().end() && !refS->getWordsKpts().empty());
refCorners[ii] = jter->second.pt; refCorners[ii] = refS->getWordsKpts()[jter->second].pt;
refCornersGuess[ii] = iter->second; refCornersGuess[ii] = iter->second;
cornerIds[ii] = iter->first; cornerIds[ii] = iter->first;
++ii; ++ii;
@@ -800,14 +813,15 @@ Transform OdometryMono::computeTransform(SensorData & data, const Transform & gu
// generate kpts // generate kpts
if(memory_->update(SensorData(data))) if(memory_->update(SensorData(data)))
{ {
const std::multimap<int, cv::KeyPoint> & words = memory_->getLastWorkingSignature()->getWords(); const Signature * s = memory_->getLastWorkingSignature();
if((int)words.size() > minInliers_) const std::multimap<int, int> & words = s->getWords();
if((int)words.size() > minInliers_ && !s->getWordsKpts().empty())
{ {
for(std::multimap<int, cv::KeyPoint>::const_iterator iter=words.begin(); iter!=words.end(); ++iter) for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
{ {
if(words.count(iter->first) == 1) if(words.count(iter->first) == 1)
{ {
firstFrameGuessCorners_.insert(std::make_pair(iter->first, iter->second.pt)); firstFrameGuessCorners_.insert(std::make_pair(iter->first, s->getWordsKpts()[iter->second].pt));
} }
} }
} }
+2
View File
@@ -398,6 +398,7 @@ public:
bool isFlat() const {return _flat;} bool isFlat() const {return _flat;}
void addItem(UPlotCurve * curve); void addItem(UPlotCurve * curve);
bool remove(const UPlotCurve * curve); bool remove(const UPlotCurve * curve);
QString getAllCurveDataAsText() const;
private Q_SLOTS: private Q_SLOTS:
void removeLegendItem(const UPlotCurve * curve); void removeLegendItem(const UPlotCurve * curve);
@@ -510,6 +511,7 @@ public:
QStringList curveNames(); QStringList curveNames();
bool contains(const QString & curveName); bool contains(const QString & curveName);
void removeCurves(); void removeCurves();
QString getAllCurveDataAsText() const;
/** /**
* Add a threshold to the plot. * Add a threshold to the plot.
*/ */
+94 -33
View File
@@ -4163,9 +4163,14 @@ void DatabaseViewer::update(int value,
std::list<Signature*> signatures; std::list<Signature*> signatures;
dbDriver_->loadSignatures(ids, signatures); dbDriver_->loadSignatures(ids, signatures);
if(signatures.size() && signatures.front()!=0 && signatures.front()->getWords().size()) if(signatures.size() && signatures.front()!=0 && !signatures.front()->getWordsKpts().empty())
{ {
view->setFeatures(signatures.front()->getWords(), data.depthOrRightRaw().type() == CV_8UC1?cv::Mat():data.depthOrRightRaw(), Qt::yellow); std::multimap<int, cv::KeyPoint> keypoints;
for(std::map<int, int>::const_iterator iter=signatures.front()->getWords().begin(); iter!=signatures.front()->getWords().end(); ++iter)
{
keypoints.insert(std::make_pair(iter->first, signatures.front()->getWordsKpts()[iter->second]));
}
view->setFeatures(keypoints, data.depthOrRightRaw().type() == CV_8UC1?cv::Mat():data.depthOrRightRaw(), Qt::yellow);
} }
Transform odomPose, g; Transform odomPose, g;
@@ -4522,16 +4527,19 @@ void DatabaseViewer::update(int value,
} }
//words //words
if(ui_->checkBox_showWords->isChecked() && signatures.size()) if(ui_->checkBox_showWords->isChecked() &&
!signatures.empty() &&
!(*signatures.begin())->getWords3().empty())
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
cloud->resize((*signatures.begin())->getWords3().size()); cloud->resize((*signatures.begin())->getWords3().size());
int i=0; int i=0;
for(std::multimap<int, cv::Point3f>::const_iterator iter=(*signatures.begin())->getWords3().begin(); for(std::multimap<int, int>::const_iterator iter=(*signatures.begin())->getWords().begin();
iter!=(*signatures.begin())->getWords3().end(); iter!=(*signatures.begin())->getWords().end();
++iter) ++iter)
{ {
cloud->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z); const cv::Point3f & pt = (*signatures.begin())->getWords3()[iter->second];
cloud->at(i++) = pcl::PointXYZ(pt.x, pt.y, pt.z);
} }
if(cloud->size()) if(cloud->size())
@@ -5593,20 +5601,25 @@ void DatabaseViewer::updateConstraintView(
cloudTo->resize(sTo->getWords3().size()); cloudTo->resize(sTo->getWords3().size());
} }
int i=0; int i=0;
for(std::multimap<int, cv::Point3f>::const_iterator iter=sFrom->getWords3().begin(); if(!sFrom->getWords3().empty())
iter!=sFrom->getWords3().end(); {
for(std::multimap<int, int>::const_iterator iter=sFrom->getWords().begin();
iter!=sFrom->getWords().end();
++iter) ++iter)
{ {
cloudFrom->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z); const cv::Point3f & pt = sFrom->getWords3()[iter->second];
cloudFrom->at(i++) = pcl::PointXYZ(pt.x, pt.y, pt.z);
}
} }
i=0; i=0;
if(sTo) if(sTo && !sTo->getWords3().empty())
{ {
for(std::multimap<int, cv::Point3f>::const_iterator iter=sTo->getWords3().begin(); for(std::multimap<int, int>::const_iterator iter=sTo->getWords().begin();
iter!=sTo->getWords3().end(); iter!=sTo->getWords().end();
++iter) ++iter)
{ {
cloudTo->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z); const cv::Point3f & pt = sTo->getWords3()[iter->second];
cloudTo->at(i++) = pcl::PointXYZ(pt.x, pt.y, pt.z);
} }
} }
@@ -7074,13 +7087,9 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent)
if(reextractVisualFeatures) if(reextractVisualFeatures)
{ {
fromS->setWords(std::multimap<int, cv::KeyPoint>()); fromS->removeAllWords();
fromS->setWords3(std::multimap<int, cv::Point3f>());
fromS->setWordsDescriptors(std::multimap<int, cv::Mat>());
fromS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); fromS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
toS->setWords(std::multimap<int, cv::KeyPoint>()); toS->removeAllWords();
toS->setWords3(std::multimap<int, cv::Point3f>());
toS->setWordsDescriptors(std::multimap<int, cv::Mat>());
toS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); toS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
} }
@@ -7192,17 +7201,33 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent)
if(toS && fromS->id() > 0 && toS->id() > 0) if(toS && fromS->id() > 0 && toS->id() > 0)
{ {
updateLoopClosuresSlider(fromS->id(), toS->id()); updateLoopClosuresSlider(fromS->id(), toS->id());
std::multimap<int, cv::KeyPoint> keypointsFrom;
std::multimap<int, cv::KeyPoint> keypointsTo;
if(!fromS->getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=fromS->getWords().begin(); iter!=fromS->getWords().end(); ++iter)
{
keypointsFrom.insert(keypointsFrom.end(), std::make_pair(iter->first, fromS->getWordsKpts()[iter->second]));
}
}
if(!toS->getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=toS->getWords().begin(); iter!=toS->getWords().end(); ++iter)
{
keypointsTo.insert(keypointsTo.end(), std::make_pair(iter->first, toS->getWordsKpts()[iter->second]));
}
}
if(newLink.type() != Link::kNeighbor && fromS->id() < toS->id()) if(newLink.type() != Link::kNeighbor && fromS->id() < toS->id())
{ {
this->updateConstraintView(newLink.inverse(), true, *toS, *fromS); this->updateConstraintView(newLink.inverse(), true, *toS, *fromS);
ui_->graphicsView_A->setFeatures(toS->getWords(), toS->sensorData().depthRaw()); ui_->graphicsView_A->setFeatures(keypointsTo, toS->sensorData().depthRaw());
ui_->graphicsView_B->setFeatures(fromS->getWords(), fromS->sensorData().depthRaw()); ui_->graphicsView_B->setFeatures(keypointsFrom, fromS->sensorData().depthRaw());
} }
else else
{ {
this->updateConstraintView(newLink, true, *fromS, *toS); this->updateConstraintView(newLink, true, *fromS, *toS);
ui_->graphicsView_A->setFeatures(fromS->getWords(), fromS->sensorData().depthRaw()); ui_->graphicsView_A->setFeatures(keypointsFrom, fromS->sensorData().depthRaw());
ui_->graphicsView_B->setFeatures(toS->getWords(), toS->sensorData().depthRaw()); ui_->graphicsView_B->setFeatures(keypointsTo, toS->sensorData().depthRaw());
} }
updateWordsMatching(info.inliersIDs); updateWordsMatching(info.inliersIDs);
@@ -7218,8 +7243,32 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent)
if(toS && fromS->id() > 0 && toS->id() > 0) if(toS && fromS->id() > 0 && toS->id() > 0)
{ {
// just update matches in the views // just update matches in the views
ui_->graphicsView_A->setFeatures(fromS->getWords(), fromS->sensorData().depthRaw()); std::multimap<int, cv::KeyPoint> keypointsFrom;
ui_->graphicsView_B->setFeatures(toS->getWords(), toS->sensorData().depthRaw()); std::multimap<int, cv::KeyPoint> keypointsTo;
if(!fromS->getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=fromS->getWords().begin(); iter!=fromS->getWords().end(); ++iter)
{
keypointsFrom.insert(keypointsFrom.end(), std::make_pair(iter->first, fromS->getWordsKpts()[iter->second]));
}
}
if(!toS->getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=toS->getWords().begin(); iter!=toS->getWords().end(); ++iter)
{
keypointsTo.insert(keypointsTo.end(), std::make_pair(iter->first, toS->getWordsKpts()[iter->second]));
}
}
if(currentLink.type() != Link::kNeighbor && fromS->id() < toS->id())
{
ui_->graphicsView_A->setFeatures(keypointsTo, toS->sensorData().depthRaw());
ui_->graphicsView_B->setFeatures(keypointsFrom, fromS->sensorData().depthRaw());
}
else
{
ui_->graphicsView_A->setFeatures(keypointsFrom, fromS->sensorData().depthRaw());
ui_->graphicsView_B->setFeatures(keypointsTo, toS->sensorData().depthRaw());
}
updateWordsMatching(info.inliersIDs); updateWordsMatching(info.inliersIDs);
} }
@@ -7306,13 +7355,9 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent)
toS->sensorData().uncompressData(); toS->sensorData().uncompressData();
if(reextractVisualFeatures) if(reextractVisualFeatures)
{ {
fromS->setWords(std::multimap<int, cv::KeyPoint>()); fromS->removeAllWords();
fromS->setWords3(std::multimap<int, cv::Point3f>());
fromS->setWordsDescriptors(std::multimap<int, cv::Mat>());
fromS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); fromS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
toS->setWords(std::multimap<int, cv::KeyPoint>()); toS->removeAllWords();
toS->setWords3(std::multimap<int, cv::Point3f>());
toS->setWordsDescriptors(std::multimap<int, cv::Mat>());
toS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); toS->sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
} }
} }
@@ -7565,8 +7610,24 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent)
this->updateConstraintView(newLink, false, *fromS, *toS); this->updateConstraintView(newLink, false, *fromS, *toS);
} }
ui_->graphicsView_A->setFeatures(fromS->getWords(), fromS->sensorData().depthRaw()); std::multimap<int, cv::KeyPoint> keypointsFrom;
ui_->graphicsView_B->setFeatures(toS->getWords(), toS->sensorData().depthRaw()); std::multimap<int, cv::KeyPoint> keypointsTo;
if(!fromS->getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=fromS->getWords().begin(); iter!=fromS->getWords().end(); ++iter)
{
keypointsFrom.insert(keypointsFrom.end(), std::make_pair(iter->first, fromS->getWordsKpts()[iter->second]));
}
}
if(!toS->getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=toS->getWords().begin(); iter!=toS->getWords().end(); ++iter)
{
keypointsTo.insert(keypointsTo.end(), std::make_pair(iter->first, toS->getWordsKpts()[iter->second]));
}
}
ui_->graphicsView_A->setFeatures(keypointsFrom, fromS->sensorData().depthRaw());
ui_->graphicsView_B->setFeatures(keypointsTo, toS->sensorData().depthRaw());
updateWordsMatching(info.inliersIDs); updateWordsMatching(info.inliersIDs);
} }
else if(updateConstraints) else if(updateConstraints)
+49 -20
View File
@@ -1715,13 +1715,16 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
_cachedSignatures.insert(signature.id(), signature); _cachedSignatures.insert(signature.id(), signature);
_cachedMemoryUsage += signature.sensorData().getMemoryUsed(); _cachedMemoryUsage += signature.sensorData().getMemoryUsed();
unsigned int count = 0; unsigned int count = 0;
for(std::multimap<int, cv::Point3f>::const_iterator jter=signature.getWords3().upper_bound(-1); jter!=signature.getWords3().end(); ++jter) if(!signature.getWords3().empty())
{ {
if(util3d::isFinite(jter->second)) for(std::multimap<int, int>::const_iterator jter=signature.getWords().upper_bound(-1); jter!=signature.getWords().end(); ++jter)
{
if(util3d::isFinite(signature.getWords3()[jter->second]))
{ {
++count; ++count;
} }
} }
}
_cachedWordsCount.insert(std::make_pair(signature.id(), (float)count)); _cachedWordsCount.insert(std::make_pair(signature.id(), (float)count));
} }
} }
@@ -1952,7 +1955,17 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
UDEBUG("time= %d ms", time.restart()); UDEBUG("time= %d ms", time.restart());
// do it after scaling // do it after scaling
this->drawKeypoints(signature.getWords(), loopSignature.getWords()); std::multimap<int, cv::KeyPoint> wordsA;
std::multimap<int, cv::KeyPoint> wordsB;
for(std::map<int, int>::const_iterator iter=signature.getWords().begin(); iter!=signature.getWords().end(); ++iter)
{
wordsA.insert(wordsA.end(), std::make_pair(iter->first, signature.getWordsKpts()[iter->second]));
}
for(std::map<int, int>::const_iterator iter=loopSignature.getWords().begin(); iter!=loopSignature.getWords().end(); ++iter)
{
wordsB.insert(wordsB.end(), std::make_pair(iter->first, loopSignature.getWordsKpts()[iter->second]));
}
this->drawKeypoints(wordsA, wordsB);
UDEBUG("time= %d ms", time.restart()); UDEBUG("time= %d ms", time.restart());
@@ -3706,19 +3719,35 @@ void MainWindow::createAndAddFeaturesToMap(int nodeId, const Transform & pose, i
cloud->resize(iter->getWords3().size()); cloud->resize(iter->getWords3().size());
int oi=0; int oi=0;
UASSERT(iter->getWords().size() == iter->getWords3().size()); UASSERT(iter->getWords().size() == iter->getWords3().size());
std::multimap<int, cv::KeyPoint>::const_iterator kter=iter->getWords().begin();
float maxDepth = _preferencesDialog->getCloudMaxDepth(0); float maxDepth = _preferencesDialog->getCloudMaxDepth(0);
UDEBUG("rgb.channels()=%d"); UDEBUG("rgb.channels()=%d");
for(std::multimap<int, cv::Point3f>::const_iterator jter=iter->getWords3().begin(); if(!iter->getWords3().empty() && !iter->getWordsKpts().empty())
jter!=iter->getWords3().end(); ++jter, ++kter)
{ {
if(util3d::isFinite(jter->second) && (maxDepth == 0.0f || jter->second.z < maxDepth)) Transform invLocalTransform = Transform::getIdentity();
if(iter.value().sensorData().cameraModels().size() == 1 && iter.value().sensorData().cameraModels().at(0).isValidForProjection())
{ {
(*cloud)[oi].x = jter->second.x; invLocalTransform = iter.value().sensorData().cameraModels()[0].localTransform().inverse();
(*cloud)[oi].y = jter->second.y; }
(*cloud)[oi].z = jter->second.z; else if(iter.value().sensorData().stereoCameraModel().isValidForProjection())
int u = kter->second.pt.x+0.5; {
int v = kter->second.pt.y+0.5; invLocalTransform = iter.value().sensorData().stereoCameraModel().left().localTransform().inverse();
}
for(std::multimap<int, int>::const_iterator jter=iter->getWords().begin(); jter!=iter->getWords().end(); ++jter)
{
const cv::Point3f & pt = iter->getWords3()[jter->second];
if(util3d::isFinite(pt) &&
(maxDepth == 0.0f ||
//move back point in camera frame (to get depth along z), ignore for multi-camera
(iter.value().sensorData().cameraModels().size()<=1 &&
util3d::transformPoint(pt, invLocalTransform).z < maxDepth)))
{
(*cloud)[oi].x = pt.x;
(*cloud)[oi].y = pt.y;
(*cloud)[oi].z = pt.z;
const cv::KeyPoint & kpt = iter->getWordsKpts()[jter->second];
int u = kpt.pt.x+0.5;
int v = kpt.pt.y+0.5;
if(!rgb.empty() && if(!rgb.empty() &&
uIsInBounds(u, 0, rgb.cols-1) && uIsInBounds(u, 0, rgb.cols-1) &&
uIsInBounds(v, 0, rgb.rows-1)) uIsInBounds(v, 0, rgb.rows-1))
@@ -3742,6 +3771,7 @@ void MainWindow::createAndAddFeaturesToMap(int nodeId, const Transform & pose, i
++oi; ++oi;
} }
} }
}
cloud->resize(oi); cloud->resize(oi);
if(!_cloudViewer->addCloud(cloudName, cloud, pose, color)) if(!_cloudViewer->addCloud(cloudName, cloud, pose, color))
{ {
@@ -4062,13 +4092,16 @@ void MainWindow::processRtabmapEvent3DMap(const rtabmap::RtabmapEvent3DMap & eve
_cachedSignatures.insert(iter->first, iter->second); _cachedSignatures.insert(iter->first, iter->second);
_cachedMemoryUsage += iter->second.sensorData().getMemoryUsed(); _cachedMemoryUsage += iter->second.sensorData().getMemoryUsed();
unsigned int count = 0; unsigned int count = 0;
for(std::multimap<int, cv::Point3f>::const_iterator jter=iter->second.getWords3().upper_bound(-1); jter!=iter->second.getWords3().end(); ++jter) if(!iter->second.getWords3().empty())
{ {
if(util3d::isFinite(jter->second)) for(std::multimap<int, int>::const_iterator jter=iter->second.getWords().upper_bound(-1); jter!=iter->second.getWords().end(); ++jter)
{
if(util3d::isFinite(iter->second.getWords3()[jter->second]))
{ {
++count; ++count;
} }
} }
}
_cachedWordsCount.insert(std::make_pair(iter->first, (float)count)); _cachedWordsCount.insert(std::make_pair(iter->first, (float)count));
++addedSignatures; ++addedSignatures;
} }
@@ -5874,13 +5907,9 @@ void MainWindow::postProcessing()
} }
else else
{ {
signatureFrom.setWords(std::multimap<int, cv::KeyPoint>()); signatureFrom.removeAllWords();
signatureFrom.setWords3(std::multimap<int, cv::Point3f>());
signatureFrom.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureFrom.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); signatureFrom.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
signatureTo.setWords(std::multimap<int, cv::KeyPoint>()); signatureTo.removeAllWords();
signatureTo.setWords3(std::multimap<int, cv::Point3f>());
signatureTo.setWordsDescriptors(std::multimap<int, cv::Mat>());
signatureTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat()); signatureTo.sensorData().setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
} }
} }
+29 -10
View File
@@ -1678,15 +1678,8 @@ void UPlotLegend::moveDown(UPlotLegendItem * item)
} }
} }
void UPlotLegend::contextMenuEvent(QContextMenuEvent * event) QString UPlotLegend::getAllCurveDataAsText() const
{ {
QAction * action = _menu->exec(event->globalPos());
if(action == _aUseFlatButtons)
{
this->setFlat(_aUseFlatButtons->isChecked());
}
else if(action == _aCopyAllCurvesToClipboard)
{
QList<UPlotLegendItem *> items = this->findChildren<UPlotLegendItem*>(); QList<UPlotLegendItem *> items = this->findChildren<UPlotLegendItem*>();
if(items.size()) if(items.size())
{ {
@@ -1759,10 +1752,27 @@ void UPlotLegend::contextMenuEvent(QContextMenuEvent * event)
text.append("\n"); text.append("\n");
} }
} }
QClipboard * clipboard = QApplication::clipboard(); return text;
clipboard->setText(text);
} }
} }
return "";
}
void UPlotLegend::contextMenuEvent(QContextMenuEvent * event)
{
QAction * action = _menu->exec(event->globalPos());
if(action == _aUseFlatButtons)
{
this->setFlat(_aUseFlatButtons->isChecked());
}
else if(action == _aCopyAllCurvesToClipboard)
{
QString data = getAllCurveDataAsText();
if(!data.isEmpty())
{
QClipboard * clipboard = QApplication::clipboard();
clipboard->setText(data);
}
} }
else if(action == _aShowAllStdDevMeanMax) else if(action == _aShowAllStdDevMeanMax)
{ {
@@ -3262,3 +3272,12 @@ void UPlot::moveCurve(const UPlotCurve * curve, int index)
this->update(); this->update();
} }
} }
QString UPlot::getAllCurveDataAsText() const
{
if(_legend)
{
return _legend->getAllCurveDataAsText();
}
return "";
}
+48 -18
View File
@@ -275,7 +275,7 @@ int main(int argc, char * argv[])
if(reg.getNNType()==6 && if(reg.getNNType()==6 &&
!dataFrom.getWordsDescriptors().empty() && !dataFrom.getWordsDescriptors().empty() &&
dataFrom.getWordsDescriptors().begin()->second.type()!=CV_32F) dataFrom.getWordsDescriptors().type()!=CV_32F)
{ {
UWARN("PyMatcher is selected for matching but binary features " UWARN("PyMatcher is selected for matching but binary features "
"are not compatible. BruteForce with CrossCheck (%s=5) " "are not compatible. BruteForce with CrossCheck (%s=5) "
@@ -298,7 +298,7 @@ int main(int argc, char * argv[])
.arg(Parameters::kVisCorNNType().c_str()) .arg(Parameters::kVisCorNNType().c_str())
.arg(reg.getNNType()) .arg(reg.getNNType())
.arg(reg.getNNType()<VWDictionary::kNNUndef?VWDictionary::nnStrategyName((VWDictionary::NNStrategy)reg.getNNType()).c_str(): .arg(reg.getNNType()<VWDictionary::kNNUndef?VWDictionary::nnStrategyName((VWDictionary::NNStrategy)reg.getNNType()).c_str():
reg.getNNType()==5||(reg.getNNType()==6&&!dataFrom.getWordsDescriptors().empty()&& dataFrom.getWordsDescriptors().begin()->second.type()!=CV_32F)?"BFCrossCheck": reg.getNNType()==5||(reg.getNNType()==6&&!dataFrom.getWordsDescriptors().empty()&& dataFrom.getWordsDescriptors().type()!=CV_32F)?"BFCrossCheck":
reg.getNNType()==6?QString(uSplit(UFile::getName(pyMatcherPath), '.').front().c_str()).replace("rtabmap_", ""): reg.getNNType()==6?QString(uSplit(UFile::getName(pyMatcherPath), '.').front().c_str()).replace("rtabmap_", ""):
reg.getNNType()==7?"GMS":"?") reg.getNNType()==7?"GMS":"?")
.arg(reg.getNNType()<5?QString(" %1=%2").arg(Parameters::kVisCorNNDR().c_str()).arg(reg.getNNDR()):"") .arg(reg.getNNType()<5?QString(" %1=%2").arg(Parameters::kVisCorNNDR().c_str()).arg(reg.getNNDR()):"")
@@ -322,9 +322,21 @@ int main(int argc, char * argv[])
if(reg.getEstimationType() == 2) if(reg.getEstimationType() == 2)
{ {
// triangulate 3D words based on the transform computed // triangulate 3D words based on the transform computed
std::map<int, int> wordsFrom = uMultimapToMapUnique(dataFrom.getWords());
std::map<int, int> wordsTo = uMultimapToMapUnique(dataTo.getWords());
std::map<int, cv::KeyPoint> kptsFrom;
std::map<int, cv::KeyPoint> kptsTo;
for(std::map<int, int>::iterator iter=wordsFrom.begin(); iter!=wordsFrom.end(); ++iter)
{
kptsFrom.insert(std::make_pair(iter->first, dataFrom.getWordsKpts()[iter->second]));
}
for(std::map<int, int>::iterator iter=wordsTo.begin(); iter!=wordsTo.end(); ++iter)
{
kptsTo.insert(std::make_pair(iter->first, dataTo.getWordsKpts()[iter->second]));
}
std::map<int, cv::Point3f> points3d = util3d::generateWords3DMono( std::map<int, cv::Point3f> points3d = util3d::generateWords3DMono(
uMultimapToMapUnique(dataFrom.getWords()), kptsFrom,
uMultimapToMapUnique(dataTo.getWords()), kptsTo,
model.isValidForProjection()?model:stereoModel.left(), model.isValidForProjection()?model:stereoModel.left(),
t); t);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>);
@@ -353,11 +365,12 @@ int main(int argc, char * argv[])
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>);
cloudWordsFrom->resize(dataFrom.getWords3().size()); cloudWordsFrom->resize(dataFrom.getWords3().size());
int i=0; int i=0;
for(std::multimap<int, cv::Point3f>::const_iterator iter=dataFrom.getWords3().begin(); for(std::multimap<int, int>::const_iterator iter=dataFrom.getWords().begin();
iter!=dataFrom.getWords3().end(); iter!=dataFrom.getWords().end();
++iter) ++iter)
{ {
cloudWordsFrom->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z); const cv::Point3f & pt = dataFrom.getWords3()[iter->second];
cloudWordsFrom->at(i++) = pcl::PointXYZ(pt.x, pt.y, pt.z);
} }
if(cloudWordsFrom->size()) if(cloudWordsFrom->size())
{ {
@@ -371,22 +384,23 @@ int main(int argc, char * argv[])
} }
if(!dataTo.getWords3().empty()) if(!dataTo.getWords3().empty())
{ {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsFrom(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWordsTo(new pcl::PointCloud<pcl::PointXYZ>);
cloudWordsFrom->resize(dataTo.getWords3().size()); cloudWordsTo->resize(dataTo.getWords3().size());
int i=0; int i=0;
for(std::multimap<int, cv::Point3f>::const_iterator iter=dataTo.getWords3().begin(); for(std::multimap<int, int>::const_iterator iter=dataTo.getWords().begin();
iter!=dataTo.getWords3().end(); iter!=dataTo.getWords().end();
++iter) ++iter)
{ {
cloudWordsFrom->at(i++) = pcl::PointXYZ(iter->second.x, iter->second.y, iter->second.z); const cv::Point3f & pt = dataTo.getWords3()[iter->second];
cloudWordsTo->at(i++) = pcl::PointXYZ(pt.x, pt.y, pt.z);
} }
if(cloudWordsFrom->size()) if(cloudWordsTo->size())
{ {
cloudWordsFrom = rtabmap::util3d::removeNaNFromPointCloud(cloudWordsFrom); cloudWordsTo = rtabmap::util3d::removeNaNFromPointCloud(cloudWordsTo);
} }
if(cloudWordsFrom->size()) if(cloudWordsTo->size())
{ {
viewer->addCloud("wordsTo", cloudWordsFrom, t, Qt::cyan); viewer->addCloud("wordsTo", cloudWordsTo, t, Qt::cyan);
viewer->setCloudPointSize("wordsTo", 5); viewer->setCloudPointSize("wordsTo", 5);
} }
} }
@@ -443,8 +457,24 @@ int main(int argc, char * argv[])
viewB->setImageDepth(uCvMat2QImage(toDepth, false, uCvQtDepthRedToBlue)); viewB->setImageDepth(uCvMat2QImage(toDepth, false, uCvQtDepthRedToBlue));
viewB->setImageDepthShown(true); viewB->setImageDepthShown(true);
} }
viewA->setFeatures(dataFrom.getWords()); std::multimap<int, cv::KeyPoint> keypointsFrom;
viewB->setFeatures(dataTo.getWords()); std::multimap<int, cv::KeyPoint> keypointsTo;
if(!dataFrom.getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=dataFrom.getWords().begin(); iter!=dataFrom.getWords().end(); ++iter)
{
keypointsFrom.insert(keypointsFrom.end(), std::make_pair(iter->first, dataFrom.getWordsKpts()[iter->second]));
}
}
if(!dataTo.getWordsKpts().empty())
{
for(std::map<int, int>::const_iterator iter=dataTo.getWords().begin(); iter!=dataTo.getWords().end(); ++iter)
{
keypointsTo.insert(keypointsTo.end(), std::make_pair(iter->first, dataTo.getWordsKpts()[iter->second]));
}
}
viewA->setFeatures(keypointsFrom);
viewB->setFeatures(keypointsTo);
std::set<int> inliersSet(info.inliersIDs.begin(), info.inliersIDs.end()); std::set<int> inliersSet(info.inliersIDs.begin(), info.inliersIDs.end());
const QMultiMap<int, KeypointItem*> & wordsA = viewA->getFeatures(); const QMultiMap<int, KeypointItem*> & wordsA = viewA->getFeatures();
+50 -2
View File
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef WITH_QT #ifdef WITH_QT
#include <rtabmap/utilite/UPlot.h> #include <rtabmap/utilite/UPlot.h>
#include <QApplication> #include <QApplication>
#include <QFile>
#endif #endif
using namespace rtabmap; using namespace rtabmap;
@@ -69,6 +70,8 @@ void showUsage()
" database, the inverse will be done. \n" " database, the inverse will be done. \n"
" --ids Use IDs for x axis instead of time in the figures. \n" " --ids Use IDs for x axis instead of time in the figures. \n"
" --start # Start from this node ID for the figures.\n" " --start # Start from this node ID for the figures.\n"
" --export Export figures' data to txt files.\n"
" --export_prefix Prefix to filenames of exported figures' data (default is \"Stat\").\n"
#endif #endif
" --report Export all evaluation statistics values in report.txt \n" " --report Export all evaluation statistics values in report.txt \n"
" --loc # Show localization statistics for each \"Statistic/Id\" per\n" " --loc # Show localization statistics for each \"Statistic/Id\" per\n"
@@ -134,6 +137,8 @@ int main(int argc, char * argv[])
bool invertFigures = false; bool invertFigures = false;
bool useIds = false; bool useIds = false;
int startId = 0; int startId = 0;
bool exportFigures = false;
std::string exportPrefix = "Stat";
int showLoc = 0; int showLoc = 0;
float locDelay = 60; float locDelay = 60;
std::vector<std::string> statsToShow; std::vector<std::string> statsToShow;
@@ -186,6 +191,24 @@ int main(int argc, char * argv[])
{ {
useIds = true; useIds = true;
} }
else if(strcmp(argv[i],"--export") == 0)
{
exportFigures = true;
}
else if(strcmp(argv[i],"--export_prefix") == 0)
{
++i;
if(i<argc-1)
{
exportPrefix = argv[i];
printf("Export prefix=%s (--export_prefix)\n", exportPrefix.c_str());
}
else
{
printf("Missing value for \"--export_prefix\" option.\n");
showUsage();
}
}
else if(strcmp(argv[i],"--loc") == 0) else if(strcmp(argv[i],"--loc") == 0)
{ {
++i; ++i;
@@ -518,14 +541,14 @@ int main(int argc, char * argv[])
if(uContains(stat, std::string("RtabmapROS/TotalTime/ms"))) if(uContains(stat, std::string("RtabmapROS/TotalTime/ms")))
{ {
if(w>=0) if(w!=-1)
{ {
slamTime.push_back(stat.at("RtabmapROS/TotalTime/ms")); slamTime.push_back(stat.at("RtabmapROS/TotalTime/ms"));
} }
} }
else if(uContains(stat, Statistics::kTimingTotal())) else if(uContains(stat, Statistics::kTimingTotal()))
{ {
if(w>=0) if(w!=-1)
{ {
slamTime.push_back(stat.at(Statistics::kTimingTotal())); slamTime.push_back(stat.at(Statistics::kTimingTotal()));
} }
@@ -1171,10 +1194,35 @@ int main(int argc, char * argv[])
{ {
iter->second->frameData(); iter->second->frameData();
} }
if(exportFigures)
{
QString data = iter->second->getAllCurveDataAsText();
if(!data.isEmpty())
{
QString filePath = QString(exportPrefix.c_str()) + (exportPrefix.empty()?"":"-") + iter->second->windowTitle().replace('/', "-") + ".txt";
QFile file(filePath);
if(file.open(QIODevice::Text | QIODevice::WriteOnly))
{
file.write(data.toUtf8());
file.close();
printf("Exported \"%s\".\n", filePath.toStdString().c_str());
}
else
{
printf("ERROR: could not open file \"%s\" for writing!\n", filePath.toStdString().c_str());
}
}
}
else
{
iter->second->show(); iter->second->show();
} }
}
if(!exportFigures)
{
return app.exec(); return app.exec();
} }
}
#endif #endif
return 0; return 0;
} }