VWDictionary: changed miniflann to flann directly so version 1.8 can be used. Added parameter "Kp/IncrementalFlann"

This commit is contained in:
matlabbe
2015-09-09 00:58:45 -04:00
parent 5dcbb66a6d
commit c107436e85
12 changed files with 471 additions and 98 deletions
+4 -1
View File
@@ -132,8 +132,11 @@ option(WITH_GTSAM "Include GTSAM support" ON)
option(WITH_CVSBA "Include cvsba support" ON)
option(WITH_FLYCAPTURE2 "Include FlyCapture2/Triclops support" ON)
FIND_PACKAGE(FLANN 1.8)
SET(FLANN18_FOUND ${FLANN_FOUND})
FIND_PACKAGE(OpenCV REQUIRED)
FIND_PACKAGE(PCL 1.7 REQUIRED)
FIND_PACKAGE(PCL 1.7 REQUIRED) # Will find FLANN too
FIND_PACKAGE(ZLIB REQUIRED)
IF(WITH_QT)
+66
View File
@@ -0,0 +1,66 @@
###############################################################################
# Find FLANN
#
# This sets the following variables:
# FLANN_FOUND - True if FLANN was found.
# FLANN_INCLUDE_DIRS - Directories containing the FLANN include files.
# FLANN_LIBRARIES - Libraries needed to use FLANN.
# FLANN_DEFINITIONS - Compiler flags for FLANN.
# If FLANN_USE_STATIC is specified and then look for static libraries ONLY else
# look for shared ones
#
# Original from https://github.com/PointCloudLibrary/pcl/blob/master/cmake/Modules/FindFLANN.cmake
#
if(FLANN_USE_STATIC)
set(FLANN_RELEASE_NAME flann_cpp_s)
set(FLANN_DEBUG_NAME flann_cpp_s-gd)
else(FLANN_USE_STATIC)
set(FLANN_RELEASE_NAME flann_cpp)
set(FLANN_DEBUG_NAME flann_cpp-gd)
endif(FLANN_USE_STATIC)
find_package(PkgConfig QUIET)
if (FLANN_FIND_VERSION)
pkg_check_modules(PC_FLANN flann>=${FLANN_FIND_VERSION})
else(FLANN_FIND_VERSION)
pkg_check_modules(PC_FLANN flann)
endif(FLANN_FIND_VERSION)
set(FLANN_DEFINITIONS ${PC_FLANN_CFLAGS_OTHER})
find_path(FLANN_INCLUDE_DIR flann/flann.hpp
HINTS ${PC_FLANN_INCLUDEDIR} ${PC_FLANN_INCLUDE_DIRS} "${FLANN_ROOT}" "$ENV{FLANN_ROOT}"
PATHS "$ENV{PROGRAMFILES}/Flann" "$ENV{PROGRAMW6432}/Flann"
PATH_SUFFIXES include)
find_library(FLANN_LIBRARY
NAMES ${FLANN_RELEASE_NAME}
HINTS ${PC_FLANN_LIBDIR} ${PC_FLANN_LIBRARY_DIRS} "${FLANN_ROOT}" "$ENV{FLANN_ROOT}"
PATHS "$ENV{PROGRAMFILES}/Flann" "$ENV{PROGRAMW6432}/Flann"
PATH_SUFFIXES lib)
find_library(FLANN_LIBRARY_DEBUG
NAMES ${FLANN_DEBUG_NAME} ${FLANN_RELEASE_NAME}
HINTS ${PC_FLANN_LIBDIR} ${PC_FLANN_LIBRARY_DIRS} "${FLANN_ROOT}" "$ENV{FLANN_ROOT}"
PATHS "$ENV{PROGRAMFILES}/Flann" "$ENV{PROGRAMW6432}/Flann"
PATH_SUFFIXES lib)
if(NOT FLANN_LIBRARY_DEBUG)
set(FLANN_LIBRARY_DEBUG ${FLANN_LIBRARY})
endif(NOT FLANN_LIBRARY_DEBUG)
set(FLANN_INCLUDE_DIRS ${FLANN_INCLUDE_DIR})
set(FLANN_LIBRARIES optimized ${FLANN_LIBRARY} debug ${FLANN_LIBRARY_DEBUG})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FLANN DEFAULT_MSG FLANN_LIBRARY FLANN_INCLUDE_DIR)
mark_as_advanced(FLANN_LIBRARY FLANN_LIBRARY_DEBUG FLANN_INCLUDE_DIR)
if(FLANN_FOUND)
message(STATUS "FLANN found (include: ${FLANN_INCLUDE_DIRS}, lib: ${FLANN_LIBRARIES})")
if(FLANN_USE_STATIC)
add_definitions(-DFLANN_STATIC)
endif(FLANN_USE_STATIC)
endif(FLANN_FOUND)
@@ -205,6 +205,7 @@ class RTABMAP_EXP Parameters
// KeypointMemory (Keypoint-based)
RTABMAP_PARAM_COND(Kp, NNStrategy, int, RTABMAP_NONFREE, 1, 3, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4");
RTABMAP_PARAM(Kp, IncrementalDictionary, bool, true, "");
RTABMAP_PARAM(Kp, IncrementalFlann, bool, false, "When using FLANN based strategy, add/remove points to its index without always rebuilding the index (the index is built only when the dictionary doubles in size).");
RTABMAP_PARAM(Kp, MaxDepth, float, 0.0, "Filter extracted keypoints by depth (0=inf)");
RTABMAP_PARAM(Kp, WordsPerImage, int, 400, "");
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.2, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad).");
+4 -1
View File
@@ -41,6 +41,7 @@ namespace rtabmap
class DBDriver;
class VisualWord;
class FlannIndex;
class RTABMAP_EXP VWDictionary
{
@@ -97,14 +98,16 @@ protected:
private:
bool _incrementalDictionary;
bool _incrementalFlann;
float _nndrRatio;
std::string _dictionaryPath; // a pre-computed dictionary (.txt)
bool _newWordsComparedTogether;
int _lastWordId;
cv::flann::Index * _flannIndex;
FlannIndex * _flannIndex;
cv::Mat _dataTree;
NNStrategy _strategy;
std::map<int ,int> _mapIndexId;
std::map<int ,int> _mapIdIndex;
std::map<int, VisualWord*> _unusedWords; //<id,VisualWord*>, note that these words stay in _visualWords
std::set<int> _notIndexedWords; // Words that are not indexed in the dictionary
std::set<int> _removedIndexedWords; // Words not anymore in the dictionary but still indexed in the dictionary
+4
View File
@@ -76,6 +76,10 @@ SET(LIBRARIES
${ZLIB_LIBRARIES}
)
IF(FLANN18_FOUND)
ADD_DEFINITIONS("-DWITH_FLANN18")
ENDIF(FLANN18_FOUND)
IF(Freenect_FOUND)
ADD_DEFINITIONS("-DWITH_FREENECT")
IF(Freenect_DASH_INCLUDES)
+288 -66
View File
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/utilite/UtiLite.h"
#include <opencv2/opencv_modules.hpp>
#if CV_MAJOR_VERSION < 3
#include <opencv2/gpu/gpu.hpp>
#else
@@ -44,23 +45,160 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#endif
#include <flann/flann.hpp>
#include <fstream>
#include <string>
namespace rtabmap
{
class FlannIndex
{
public:
FlannIndex():
index_(0),
binaryType_(false)
{
}
virtual ~FlannIndex()
{
this->release();
}
void release()
{
if(index_)
{
if(binaryType_)
{
delete (flann::Index<flann::Hamming<unsigned char> >*)index_;
}
else
{
delete (flann::Index<flann::L2<float> >*)index_;
}
index_ = 0;
}
}
void build(
const cv::Mat & features,
const flann::IndexParams& params,
bool binaryType)
{
this->release();
UASSERT(index_ == 0);
binaryType_ = binaryType;
if(binaryType)
{
flann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
index_ = new flann::Index<flann::Hamming<unsigned char> >(dataset, params);
((flann::Index<flann::Hamming<unsigned char> >*)index_)->buildIndex();
}
else
{
flann::Matrix<float> dataset((float*)features.data, features.rows, features.cols);
index_ = new flann::Index<flann::L2<float> >(dataset, params);
((flann::Index<flann::L2<float> >*)index_)->buildIndex();
}
}
bool isIncremental()
{
#ifdef WITH_FLANN18
return true;
#else
return false;
#endif
}
void addPoints(const cv::Mat & features)
{
#ifdef WITH_FLANN18
if(binaryType_)
{
flann::Matrix<unsigned char> dataset(features.data, features.rows, features.cols);
((flann::Index<flann::Hamming<unsigned char> >*)index_)->addPoints(dataset);
}
else
{
flann::Matrix<float> dataset((float*)features.data, features.rows, features.cols);
((flann::Index<flann::L2<float> >*)index_)->addPoints(dataset);
}
#else
UFATAL("Not built with FLANN 1.8! Only when isIncremental() returns true that you can call this method.");
#endif
}
void removePoint(unsigned int index)
{
#ifdef WITH_FLANN18
if(binaryType_)
{
((flann::Index<flann::Hamming<unsigned char> >*)index_)->removePoint(index);
}
else
{
((flann::Index<flann::L2<float> >*)index_)->removePoint(index);
}
#else
UFATAL("Not built with FLANN 1.8! Only when isIncremental() returns true that you can call this method.");
#endif
}
void knnSearch(
const cv::Mat & query,
cv::Mat & indices,
cv::Mat & dists,
int knn,
const flann::SearchParams& params=flann::SearchParams())
{
if(!index_)
{
UERROR("Flann index not yet created!");
return;
}
indices.create(query.rows, knn, CV_32S);
dists.create(query.rows, knn, binaryType_?CV_32S:CV_32F);
cv::flann::IndexParams i;
flann::Matrix<int> indicesF((int*)indices.data, indices.rows, indices.cols);
if(binaryType_)
{
flann::Matrix<unsigned int> distsF((unsigned int*)dists.data, dists.rows, dists.cols);
flann::Matrix<unsigned char> queryF(query.data, query.rows, query.cols);
((flann::Index<flann::Hamming<unsigned char> >*)index_)->knnSearch(queryF, indicesF, distsF, knn, params);
}
else
{
flann::Matrix<float> distsF((float*)dists.data, dists.rows, dists.cols);
flann::Matrix<float> queryF((float*)query.data, query.rows, query.cols);
((flann::Index<flann::L2<float> >*)index_)->knnSearch(queryF, indicesF, distsF, knn, params);
}
}
private:
void * index_;
bool binaryType_;
};
const int VWDictionary::ID_START = 1;
const int VWDictionary::ID_INVALID = 0;
VWDictionary::VWDictionary(const ParametersMap & parameters) :
_totalActiveReferences(0),
_incrementalDictionary(Parameters::defaultKpIncrementalDictionary()),
_incrementalFlann(Parameters::defaultKpIncrementalFlann()),
_nndrRatio(Parameters::defaultKpNndrRatio()),
_dictionaryPath(Parameters::defaultKpDictionaryPath()),
_newWordsComparedTogether(Parameters::defaultKpNewWordsComparedTogether()),
_lastWordId(0),
_flannIndex(new cv::flann::Index()),
_flannIndex(new FlannIndex()),
_strategy(kNNBruteForce)
{
this->setNNStrategy((NNStrategy)Parameters::defaultKpNNStrategy());
@@ -78,6 +216,13 @@ void VWDictionary::parseParameters(const ParametersMap & parameters)
ParametersMap::const_iterator iter;
Parameters::parse(parameters, Parameters::kKpNndrRatio(), _nndrRatio);
Parameters::parse(parameters, Parameters::kKpNewWordsComparedTogether(), _newWordsComparedTogether);
Parameters::parse(parameters, Parameters::kKpIncrementalFlann(), _incrementalFlann);
if(_incrementalFlann && !_flannIndex->isIncremental())
{
UERROR("TRying to set \"KpIncrementalFlann\"=true but RTAB-Map is not built with FLANN>=1.8. Setting to false.");
_incrementalFlann = false;
}
UASSERT_MSG(_nndrRatio > 0.0f, uFormat("String=%s value=%f", uContains(parameters, Parameters::kKpNndrRatio())?parameters.at(Parameters::kKpNndrRatio()).c_str():"", _nndrRatio).c_str());
@@ -257,7 +402,15 @@ void VWDictionary::setNNStrategy(NNStrategy strategy)
}
else
{
bool update = _strategy != strategy;
_strategy = strategy;
if(update)
{
_dataTree = cv::Mat();
_notIndexedWords = uKeysSet(_visualWords);
_removedIndexedWords.clear();
this->update();
}
}
}
}
@@ -287,55 +440,106 @@ void VWDictionary::update()
if(_notIndexedWords.size() || _visualWords.size() == 0 || _removedIndexedWords.size())
{
_mapIndexId.clear();
int oldSize = _dataTree.rows;
_dataTree = cv::Mat();
_flannIndex->release();
if(_visualWords.size())
if(_incrementalFlann &&
_flannIndex->isIncremental() &&
_strategy < kNNBruteForce &&
(_notIndexedWords.size() || _removedIndexedWords.size()) &&
oldSize)
{
UTimer timer;
timer.start();
int type = _visualWords.begin()->second->getDescriptor().type();
int dim = _visualWords.begin()->second->getDescriptor().cols;
UASSERT(type == CV_32F || type == CV_8U);
UASSERT(dim > 0);
// Create the data matrix
_dataTree = cv::Mat(_visualWords.size(), dim, type); // SURF descriptors are CV_32F
std::map<int, VisualWord*>::const_iterator iter = _visualWords.begin();
for(unsigned int i=0; i < _visualWords.size(); ++i, ++iter)
for(std::set<int>::iterator iter=_notIndexedWords.begin(); iter!=_notIndexedWords.end(); ++iter)
{
UASSERT(iter->second->getDescriptor().cols == dim);
UASSERT(iter->second->getDescriptor().type() == type);
iter->second->getDescriptor().copyTo(_dataTree.row(i));
_mapIndexId.insert(_mapIndexId.end(), std::pair<int, int>(i, iter->second->id()));
VisualWord* w = uValue(_visualWords, *iter, (VisualWord*)0);
UASSERT(w);
UASSERT(w->getDescriptor().cols == _dataTree.cols);
UASSERT(w->getDescriptor().type() == _dataTree.type());
_dataTree.push_back(w->getDescriptor());
_mapIndexId.insert(_mapIndexId.end(), std::pair<int, int>(_dataTree.rows-1, w->id()));
std::pair<std::map<int, int>::iterator, bool> inserted = _mapIdIndex.insert(std::pair<int, int>(w->id(), _dataTree.rows-1));
if(!inserted.second)
{
//update to new index
inserted.first->second = _dataTree.rows-1;
}
_flannIndex->addPoints(w->getDescriptor());
}
ULOGGER_DEBUG("_mapIndexId.size() = %d, words.size()=%d, _dim=%d",_mapIndexId.size(), _visualWords.size(), dim);
ULOGGER_DEBUG("copying data = %f s", timer.ticks());
switch(_strategy)
for(std::set<int>::iterator iter=_removedIndexedWords.begin(); iter!=_removedIndexedWords.end(); ++iter)
{
case kNNFlannNaive:
_flannIndex->build(_dataTree, cv::flann::LinearIndexParams(), type == CV_32F?cvflann::FLANN_DIST_L2:cvflann::FLANN_DIST_HAMMING);
break;
case kNNFlannKdTree:
UASSERT_MSG(type == CV_32F, "To use KdTree dictionary, float descriptors are required!");
_flannIndex->build(_dataTree, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_L2);
break;
case kNNFlannLSH:
UASSERT_MSG(type == CV_8U, "To use LSH dictionary, binary descriptors are required!");
_flannIndex->build(_dataTree, cv::flann::LshIndexParams(12, 20, 2), cvflann::FLANN_DIST_HAMMING);
break;
default:
break;
UASSERT(uContains(_mapIdIndex, *iter));
_flannIndex->removePoint(_mapIdIndex.at(*iter));
}
}
else if(_strategy >= kNNBruteForce &&
_notIndexedWords.size() &&
_removedIndexedWords.size() == 0 &&
oldSize)
{
//just add not indexed words
for(std::set<int>::iterator iter=_notIndexedWords.begin(); iter!=_notIndexedWords.end(); ++iter)
{
VisualWord* w = uValue(_visualWords, *iter, (VisualWord*)0);
UASSERT(w);
UASSERT(w->getDescriptor().cols == _dataTree.cols);
UASSERT(w->getDescriptor().type() == _dataTree.type());
_dataTree.push_back(w->getDescriptor());
_mapIndexId.insert(_mapIndexId.end(), std::pair<int, int>(_dataTree.rows-1, w->id()));
std::pair<std::map<int, int>::iterator, bool> inserted = _mapIdIndex.insert(std::pair<int, int>(w->id(), _dataTree.rows-1));
UASSERT(inserted.second);
}
}
else
{
_mapIndexId.clear();
_mapIdIndex.clear();
_dataTree = cv::Mat();
_flannIndex->release();
ULOGGER_DEBUG("Time to create kd tree = %f s", timer.ticks());
if(_visualWords.size())
{
UTimer timer;
timer.start();
int type = _visualWords.begin()->second->getDescriptor().type();
int dim = _visualWords.begin()->second->getDescriptor().cols;
UASSERT(type == CV_32F || type == CV_8U);
UASSERT(dim > 0);
// Create the data matrix
_dataTree = cv::Mat(_visualWords.size(), dim, type); // SURF descriptors are CV_32F
std::map<int, VisualWord*>::const_iterator iter = _visualWords.begin();
for(unsigned int i=0; i < _visualWords.size(); ++i, ++iter)
{
UASSERT(iter->second->getDescriptor().cols == dim);
UASSERT(iter->second->getDescriptor().type() == type);
iter->second->getDescriptor().copyTo(_dataTree.row(i));
_mapIndexId.insert(_mapIndexId.end(), std::pair<int, int>(i, iter->second->id()));
_mapIdIndex.insert(_mapIdIndex.end(), std::pair<int, int>(iter->second->id(), i));
}
ULOGGER_DEBUG("_mapIndexId.size() = %d, words.size()=%d, _dim=%d",_mapIndexId.size(), _visualWords.size(), dim);
ULOGGER_DEBUG("copying data = %f s", timer.ticks());
switch(_strategy)
{
case kNNFlannNaive:
_flannIndex->build(_dataTree, flann::LinearIndexParams(), type != CV_32F);
break;
case kNNFlannKdTree:
UASSERT_MSG(type == CV_32F, "To use KdTree dictionary, float descriptors are required!");
_flannIndex->build(_dataTree, flann::KDTreeIndexParams(), false);
break;
case kNNFlannLSH:
UASSERT_MSG(type == CV_8U, "To use LSH dictionary, binary descriptors are required!");
_flannIndex->build(_dataTree, flann::LshIndexParams(12, 20, 2), true);
break;
default:
break;
}
ULOGGER_DEBUG("Time to create kd tree = %f s", timer.ticks());
}
}
UDEBUG("Dictionary updated! (size=%d->%d added=%d removed=%d)",
oldSize, _dataTree.rows, _notIndexedWords.size(), _removedIndexedWords.size());
@@ -370,6 +574,7 @@ void VWDictionary::clear()
_lastWordId = 0;
_dataTree = cv::Mat();
_mapIndexId.clear();
_mapIdIndex.clear();
_unusedWords.clear();
_flannIndex->release();
}
@@ -544,10 +749,15 @@ std::list<int> VWDictionary::addNewWords(const cv::Mat & descriptors,
{
for(int j=0; j<dists.cols; ++j)
{
if(results.at<int>(i,j) >= 0)
float d = dists.at<float>(i,j);
int id = uValue(_mapIndexId, results.at<int>(i,j));
if(d >= 0.0f && id > 0)
{
float d = dists.at<float>(i,j);
fullResults.insert(std::pair<float, int>(d, uValue(_mapIndexId, results.at<int>(i,j))));
std::multimap<float, int>::iterator iter = fullResults.insert(std::pair<float, int>(d, id));
}
else
{
break;
}
}
}
@@ -555,10 +765,15 @@ std::list<int> VWDictionary::addNewWords(const cv::Mat & descriptors,
{
for(unsigned int j=0; j<matches.at(i).size(); ++j)
{
if(matches.at(i).at(j).trainIdx >= 0)
float d = matches.at(i).at(j).distance;
int id = uValue(_mapIndexId, matches.at(i).at(j).trainIdx);
if(d >= 0.0f && id > 0)
{
float d = matches.at(i).at(j).distance;
fullResults.insert(std::pair<float, int>(d, uValue(_mapIndexId, matches.at(i).at(j).trainIdx)));
std::multimap<float, int>::iterator iter = fullResults.insert(std::pair<float, int>(d, id));
}
else
{
break;
}
}
}
@@ -566,8 +781,8 @@ std::list<int> VWDictionary::addNewWords(const cv::Mat & descriptors,
// Check if this descriptor matches with a word from the last signature (a word not already added to the tree)
if(_newWordsComparedTogether && newWords.rows)
{
cv::flann::Index linearSeach;
linearSeach.build(newWords, cv::flann::LinearIndexParams(), type == CV_32F?cvflann::FLANN_DIST_L2:cvflann::FLANN_DIST_HAMMING);
FlannIndex linearSeach;
linearSeach.build(newWords, flann::LinearIndexParams(), type != CV_32F);
cv::Mat resultsLinear;
cv::Mat distsLinear;
linearSeach.knnSearch(descriptors.row(i), resultsLinear, distsLinear, newWords.rows>1?2:1);
@@ -582,10 +797,15 @@ std::list<int> VWDictionary::addNewWords(const cv::Mat & descriptors,
{
for(int j=0; j<resultsLinear.cols; ++j)
{
if(resultsLinear.at<int>(0,j) >= 0)
float d = distsLinear.at<float>(0,j);
if(d >= 0.0f && resultsLinear.at<int>(0,j) >= 0)
{
float d = distsLinear.at<float>(0,j);
fullResults.insert(std::pair<float, int>(d, newWordsId[resultsLinear.at<int>(0,j)]));
std::multimap<float, int>::iterator iter = fullResults.insert(std::pair<float, int>(d, newWordsId[resultsLinear.at<int>(0,j)]));
UASSERT(iter->second > 0);
}
else
{
break;
}
}
}
@@ -637,7 +857,6 @@ std::list<int> VWDictionary::addNewWords(const cv::Mat & descriptors,
this->addWordRef(fullResults.begin()->second, signatureId);
wordIds.push_back(fullResults.begin()->second);
UASSERT(fullResults.begin()->second>0);
}
}
else if(fullResults.size())
@@ -786,8 +1005,8 @@ std::vector<int> VWDictionary::findNN(const std::list<VisualWord *> & vws) const
// Find nearest neighbor
ULOGGER_DEBUG("Searching in words not indexed...");
cv::flann::Index linearSeach;
linearSeach.build(dataNotIndexed, cv::flann::LinearIndexParams(), type == CV_32F?cvflann::FLANN_DIST_L2:cvflann::FLANN_DIST_HAMMING);
FlannIndex linearSeach;
linearSeach.build(dataNotIndexed, flann::LinearIndexParams(), type != CV_32F);
linearSeach.knnSearch(query, resultsNotIndexed, distsNotIndexed, _notIndexedWords.size()>1?2:1);
// In case of binary descriptors
if(distsNotIndexed.type() == CV_32S)
@@ -806,10 +1025,11 @@ std::vector<int> VWDictionary::findNN(const std::list<VisualWord *> & vws) const
{
for(int j=0; j<dists.cols; ++j)
{
if(results.at<int>(i,j) > 0)
float d = dists.at<float>(i,j);
int id = uValue(_mapIndexId, results.at<int>(i,j));
if(d >= 0.0f && id > 0)
{
float d = dists.at<float>(i,j);
fullResults.insert(std::pair<float, int>(d, uValue(_mapIndexId, results.at<int>(i,j))));
fullResults.insert(std::pair<float, int>(d, id));
}
}
}
@@ -817,10 +1037,11 @@ std::vector<int> VWDictionary::findNN(const std::list<VisualWord *> & vws) const
{
for(unsigned int j=0; j<matches.at(i).size(); ++j)
{
if(matches.at(i).at(j).trainIdx > 0)
float d = matches.at(i).at(j).distance;
int id = uValue(_mapIndexId, matches.at(i).at(j).trainIdx);
if(d >= 0.0f && id > 0)
{
float d = matches.at(i).at(j).distance;
fullResults.insert(std::pair<float, int>(d, uValue(_mapIndexId, matches.at(i).at(j).trainIdx)));
fullResults.insert(std::pair<float, int>(d, id));
}
}
}
@@ -828,10 +1049,11 @@ std::vector<int> VWDictionary::findNN(const std::list<VisualWord *> & vws) const
// not indexed..
for(int j=0; j<distsNotIndexed.cols; ++j)
{
if(resultsNotIndexed.at<int>(i,j) > 0)
float d = distsNotIndexed.at<float>(i,j);
if(d >= 0.0f && resultsNotIndexed.at<int>(i,j) > 0)
{
float d = distsNotIndexed.at<float>(i,j);
fullResults.insert(std::pair<float, int>(d, uValue(mapIndexIdNotIndexed, resultsNotIndexed.at<int>(i,j))));
std::multimap<float, int>::iterator iter = fullResults.insert(std::pair<float, int>(d, uValue(mapIndexIdNotIndexed, resultsNotIndexed.at<int>(i,j))));
UASSERT(iter->second > 0);
}
}
+3
View File
@@ -34,6 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <opencv2/core/version.hpp>
#include <pcl/pcl_config.h>
#include <flann/config.h>
namespace rtabmap {
AboutDialog::AboutDialog(QWidget * parent) :
@@ -53,6 +55,7 @@ AboutDialog::AboutDialog(QWidget * parent) :
#endif
_ui->label_version->setText(version);
_ui->label_opencv_version->setText(cv_version);
_ui->label_flann_version->setText(FLANN_VERSION_);
_ui->label_pcl_version->setText(PCL_VERSION_PRETTY);
_ui->label_freenect->setText(CameraFreenect::available()?"Yes":"No");
_ui->label_openni2->setText(CameraOpenNI2::available()?"Yes":"No");
+4
View File
@@ -121,6 +121,10 @@ INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
add_definitions(${PCL_DEFINITIONS})
IF(FLANN18_FOUND)
ADD_DEFINITIONS("-DWITH_FLANN18")
ENDIF(FLANN18_FOUND)
# create a library from the source files
ADD_LIBRARY(rtabmap_gui ${SRC_FILES})
# Linking with Qt libraries
+5
View File
@@ -490,6 +490,11 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
//Keypoint-based
_ui->comboBox_dictionary_strategy->setObjectName(Parameters::kKpNNStrategy().c_str());
_ui->checkBox_dictionary_incremental->setObjectName(Parameters::kKpIncrementalDictionary().c_str());
_ui->checkBox_kp_incrementalFlann->setObjectName(Parameters::kKpIncrementalFlann().c_str());
#ifndef WITH_FLANN18
_ui->checkBox_kp_incrementalFlann->setEnabled(false);
_ui->checkBox_kp_incrementalFlann->setChecked(false);
#endif
_ui->comboBox_detector_strategy->setObjectName(Parameters::kKpDetectorStrategy().c_str());
_ui->surf_doubleSpinBox_nndrRatio->setObjectName(Parameters::kKpNndrRatio().c_str());
_ui->surf_doubleSpinBox_maxDepth->setObjectName(Parameters::kKpMaxDepth().c_str());
+45 -28
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>824</width>
<height>581</height>
<width>831</width>
<height>615</height>
</rect>
</property>
<property name="sizePolicy">
@@ -82,21 +82,31 @@ p, li { white-space: pre-wrap; }
</item>
<item>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
<item row="10" column="0">
<item row="9" column="1">
<widget class="QLabel" name="label_pcl_version">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>With Freenect :</string>
</property>
</widget>
</item>
<item row="11" column="0">
<item row="12" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>With OpenNI2 :</string>
</property>
</widget>
</item>
<item row="13" column="0">
<item row="14" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>With stereo dc1394 :</string>
@@ -202,24 +212,14 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="label_pcl_version">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="15" column="0">
<item row="16" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>With g2o :</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QLabel" name="label_freenect">
<property name="text">
<string/>
@@ -229,7 +229,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="11" column="1">
<item row="12" column="1">
<widget class="QLabel" name="label_openni2">
<property name="text">
<string/>
@@ -239,7 +239,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="15" column="1">
<item row="16" column="1">
<widget class="QLabel" name="label_g2o">
<property name="text">
<string/>
@@ -249,21 +249,21 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="12" column="0">
<item row="13" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>With Freenect2 :</string>
</property>
</widget>
</item>
<item row="14" column="0">
<item row="15" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>With stereo FlyCapture2 :</string>
</property>
</widget>
</item>
<item row="12" column="1">
<item row="13" column="1">
<widget class="QLabel" name="label_freenect2">
<property name="text">
<string/>
@@ -273,7 +273,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="13" column="1">
<item row="14" column="1">
<widget class="QLabel" name="label_dc1394">
<property name="text">
<string/>
@@ -283,7 +283,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="14" column="1">
<item row="15" column="1">
<widget class="QLabel" name="label_flycapture2">
<property name="text">
<string/>
@@ -293,14 +293,14 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="17" column="0">
<item row="18" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>With cvsba :</string>
</property>
</widget>
</item>
<item row="17" column="1">
<item row="18" column="1">
<widget class="QLabel" name="label_cvsba">
<property name="text">
<string/>
@@ -310,14 +310,14 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="16" column="0">
<item row="17" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>With GTSAM :</string>
</property>
</widget>
</item>
<item row="16" column="1">
<item row="17" column="1">
<widget class="QLabel" name="label_gtsam">
<property name="text">
<string/>
@@ -327,6 +327,23 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>FLANN version :</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_flann_version">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
+25 -2
View File
@@ -63,7 +63,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-509</y>
<y>-349</y>
<width>760</width>
<height>1598</height>
</rect>
@@ -86,7 +86,7 @@
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>19</number>
<number>9</number>
</property>
<widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29">
@@ -4973,6 +4973,29 @@ When set to false, no new words are added to dictionary, so no more updates are
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QLabel" name="label_260">
<property name="text">
<string>When using a FLANN-based nearest neighbor strategy, add/remove points to its index without always rebuilding the index (the index is built only when the dictionary doubles in size).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="checkBox_kp_incrementalFlann">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
+22
View File
@@ -736,4 +736,26 @@ inline bool uStrContains(const std::string & string, const std::string & substri
return string.find(substring) != std::string::npos;
}
inline int uCompareVersion(const std::string & version, int major, int minor=-1, int patch=-1)
{
std::vector<std::string> v = uListToVector(uSplit(version, '.'));
if(v.size() == 3)
{
int vMajor = atoi(v[0].c_str());
int vMinor = atoi(v[1].c_str());
int vPatch = atoi(v[2].c_str());
if(vMajor > major ||
(vMajor == major && minor!=-1 && vMinor > minor) ||
(vMajor == major && minor!=-1 && vMinor == minor && patch!=-1 && vPatch > patch))
{
return 1;
}
else if(vMajor == major && (minor == -1 || (vMinor == minor && (patch == -1 || vPatch == patch))))
{
return 0;
}
}
return -1;
}
#endif /* USTL_H */