mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Binary descriptors (ORB, BRIEF, FREAK) can now be used for the visual dictionnary: maybe not as discriminative as SIFT/SURF on large environments, the advantage is that RTAB-Map will work without Patent/noncommercial licenses of SIFT and SURF.
A new option is added to re-extract features when a loop closure hypothesis is found. Another new option is to force 2D (3DoF) transform on visual odometry and loop closures. git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@1679 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
@@ -115,14 +115,24 @@ public:
|
|||||||
int getMapId(int signatureId) const;
|
int getMapId(int signatureId) const;
|
||||||
std::vector<unsigned char> getImage(int signatureId) const;
|
std::vector<unsigned char> getImage(int signatureId) const;
|
||||||
void getImageDepth(
|
void getImageDepth(
|
||||||
int locationId, std::vector<unsigned char> & rgb,
|
int locationId,
|
||||||
|
std::vector<unsigned char> & rgb,
|
||||||
std::vector<unsigned char> & depth,
|
std::vector<unsigned char> & depth,
|
||||||
std::vector<unsigned char> & depth2d,
|
std::vector<unsigned char> & depth2d,
|
||||||
float & fx,
|
float & fx,
|
||||||
float & fy,
|
float & fy,
|
||||||
float & cx,
|
float & cx,
|
||||||
float & cy,
|
float & cy,
|
||||||
Transform & localTransform) const;
|
Transform & localTransform);
|
||||||
|
void getImageDepthRaw(
|
||||||
|
int locationId,
|
||||||
|
cv::Mat & rgb,
|
||||||
|
cv::Mat & depth,
|
||||||
|
float & fx,
|
||||||
|
float & fy,
|
||||||
|
float & cx,
|
||||||
|
float & cy,
|
||||||
|
Transform & localTransform);
|
||||||
std::set<int> getAllSignatureIds() const;
|
std::set<int> getAllSignatureIds() const;
|
||||||
bool memoryChanged() const {return _memoryChanged;}
|
bool memoryChanged() const {return _memoryChanged;}
|
||||||
bool isIncremental() const {return _incrementalMemory;}
|
bool isIncremental() const {return _incrementalMemory;}
|
||||||
@@ -171,8 +181,13 @@ public:
|
|||||||
std::map<int, Transform> & poses,
|
std::map<int, Transform> & poses,
|
||||||
std::multimap<int, Link> & links,
|
std::multimap<int, Link> & links,
|
||||||
bool lookInDatabase = false);
|
bool lookInDatabase = false);
|
||||||
Transform computeVisualTransform(int oldId, int newId, std::string * rejectedMsg = 0) const;
|
float getBowInlierDistance() const {return _bowInlierDistance;}
|
||||||
Transform computeVisualTransform(const Signature & oldS, const Signature & newS, std::string * rejectedMsg = 0) const;
|
int getBowIterations() const {return _bowIterations;}
|
||||||
|
int getBowMinInliers() const {return _bowMinInliers;}
|
||||||
|
float getBowMaxDepth() const {return _bowMaxDepth;}
|
||||||
|
bool getBowForce2D() const {return _bowForce2D;}
|
||||||
|
Transform computeVisualTransform(int oldId, int newId, std::string * rejectedMsg = 0, int * inliers = 0) const;
|
||||||
|
Transform computeVisualTransform(const Signature & oldS, const Signature & newS, std::string * rejectedMsg = 0, int * inliers = 0) const;
|
||||||
Transform computeIcpTransform(int oldId, int newId, Transform guess, bool icp3D, std::string * rejectedMsg = 0);
|
Transform computeIcpTransform(int oldId, int newId, Transform guess, bool icp3D, std::string * rejectedMsg = 0);
|
||||||
Transform computeIcpTransform(const Signature & oldS, const Signature & newS, Transform guess, bool icp3D, std::string * rejectedMsg = 0) const;
|
Transform computeIcpTransform(const Signature & oldS, const Signature & newS, Transform guess, bool icp3D, std::string * rejectedMsg = 0) const;
|
||||||
Transform computeScanMatchingTransform(
|
Transform computeScanMatchingTransform(
|
||||||
@@ -252,6 +267,7 @@ private:
|
|||||||
float _bowInlierDistance;
|
float _bowInlierDistance;
|
||||||
int _bowIterations;
|
int _bowIterations;
|
||||||
float _bowMaxDepth;
|
float _bowMaxDepth;
|
||||||
|
bool _bowForce2D;
|
||||||
int _icpDecimation;
|
int _icpDecimation;
|
||||||
float _icpMaxDepth;
|
float _icpMaxDepth;
|
||||||
float _icpVoxelSize;
|
float _icpVoxelSize;
|
||||||
|
|||||||
@@ -273,6 +273,12 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(LccBow, InlierDistance, float, 0.01, "Maximum distance for visual word correspondences.");
|
RTABMAP_PARAM(LccBow, InlierDistance, float, 0.01, "Maximum distance for visual word correspondences.");
|
||||||
RTABMAP_PARAM(LccBow, Iterations, int, 100, "Maximum iterations to compute the transform from visual words.");
|
RTABMAP_PARAM(LccBow, Iterations, int, 100, "Maximum iterations to compute the transform from visual words.");
|
||||||
RTABMAP_PARAM(LccBow, MaxDepth, float, 5.0, "Max depth of the words (0 means no limit).");
|
RTABMAP_PARAM(LccBow, MaxDepth, float, 5.0, "Max depth of the words (0 means no limit).");
|
||||||
|
RTABMAP_PARAM(LccBow, Force2D, bool, false, "Force 2D transform (3Dof: x,y and yaw).")
|
||||||
|
RTABMAP_PARAM(LccReextract, LoopClosureFeatures, bool, false, "Re-extract features on global loop closure.");
|
||||||
|
RTABMAP_PARAM(LccReextract, NNType, int, 3, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4.");
|
||||||
|
RTABMAP_PARAM(LccReextract, NNDR, float, 0.7, "NNDR: nearest neighbor distance ratio.");
|
||||||
|
RTABMAP_PARAM(LccReextract, FeatureType, int, 4, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF.");
|
||||||
|
RTABMAP_PARAM(LccReextract, MaxWords, int, 0, "0 no limits.");
|
||||||
|
|
||||||
RTABMAP_PARAM(LccIcp3, Decimation, int, 8, "Depth image decimation.");
|
RTABMAP_PARAM(LccIcp3, Decimation, int, 8, "Depth image decimation.");
|
||||||
RTABMAP_PARAM(LccIcp3, MaxDepth, float, 4.0, "Max cloud depth.");
|
RTABMAP_PARAM(LccIcp3, MaxDepth, float, 4.0, "Max cloud depth.");
|
||||||
|
|||||||
@@ -167,6 +167,11 @@ private:
|
|||||||
int _toroIterations;
|
int _toroIterations;
|
||||||
std::string _databasePath;
|
std::string _databasePath;
|
||||||
bool _optimizeFromGraphEnd;
|
bool _optimizeFromGraphEnd;
|
||||||
|
bool _reextractLoopClosureFeatures;
|
||||||
|
int _reextractNNType;
|
||||||
|
float _reextractNNDR;
|
||||||
|
int _reextractFeatureType;
|
||||||
|
int _reextractMaxWords;
|
||||||
|
|
||||||
int _lcHypothesisId;
|
int _lcHypothesisId;
|
||||||
float _lcHypothesisValue;
|
float _lcHypothesisValue;
|
||||||
|
|||||||
@@ -114,6 +114,8 @@ public:
|
|||||||
const std::map<int, int> & getWordsChanged() const {return _wordsChanged;}
|
const std::map<int, int> & getWordsChanged() const {return _wordsChanged;}
|
||||||
void setImage(const std::vector<unsigned char> & image) {_image = image;}
|
void setImage(const std::vector<unsigned char> & image) {_image = image;}
|
||||||
const std::vector<unsigned char> & getImage() const {return _image;}
|
const std::vector<unsigned char> & getImage() const {return _image;}
|
||||||
|
void setImageRaw(const cv::Mat & image) {_imageRaw = image;}
|
||||||
|
const cv::Mat & getImageRaw() const {return _imageRaw;}
|
||||||
|
|
||||||
//metric stuff
|
//metric stuff
|
||||||
void setWords3(const std::multimap<int, pcl::PointXYZ> & words3) {_words3 = words3;}
|
void setWords3(const std::multimap<int, pcl::PointXYZ> & words3) {_words3 = words3;}
|
||||||
@@ -130,6 +132,8 @@ public:
|
|||||||
float getDepthCy() const {return _cy;}
|
float getDepthCy() const {return _cy;}
|
||||||
const Transform & getPose() const {return _pose;}
|
const Transform & getPose() const {return _pose;}
|
||||||
const Transform & getLocalTransform() const {return _localTransform;}
|
const Transform & getLocalTransform() const {return _localTransform;}
|
||||||
|
void setDepthRaw(const cv::Mat & depth) {_depthRaw = depth;}
|
||||||
|
const cv::Mat & getDepthRaw() const {return _depthRaw;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _id;
|
int _id;
|
||||||
@@ -159,6 +163,9 @@ private:
|
|||||||
Transform _pose;
|
Transform _pose;
|
||||||
Transform _localTransform; // camera_link -> base_link
|
Transform _localTransform; // camera_link -> base_link
|
||||||
std::multimap<int, pcl::PointXYZ> _words3; // word <id, keypoint>
|
std::multimap<int, pcl::PointXYZ> _words3; // word <id, keypoint>
|
||||||
|
|
||||||
|
cv::Mat _imageRaw;
|
||||||
|
cv::Mat _depthRaw;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rtabmap
|
} // namespace rtabmap
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class RTABMAP_EXP Statistics
|
|||||||
RTABMAP_STATS(Loop, ReactivateId,);
|
RTABMAP_STATS(Loop, ReactivateId,);
|
||||||
RTABMAP_STATS(Loop, Hypothesis_ratio,);
|
RTABMAP_STATS(Loop, Hypothesis_ratio,);
|
||||||
RTABMAP_STATS(Loop, Hypothesis_reactivated,);
|
RTABMAP_STATS(Loop, Hypothesis_reactivated,);
|
||||||
|
RTABMAP_STATS(Loop, VisualInliers,);
|
||||||
RTABMAP_STATS(Loop, Last_loop_closure_parent,);
|
RTABMAP_STATS(Loop, Last_loop_closure_parent,);
|
||||||
RTABMAP_STATS(Loop, Last_loop_closure_child,);
|
RTABMAP_STATS(Loop, Last_loop_closure_child,);
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ Memory::Memory(const ParametersMap & parameters) :
|
|||||||
_bowInlierDistance(Parameters::defaultLccBowInlierDistance()),
|
_bowInlierDistance(Parameters::defaultLccBowInlierDistance()),
|
||||||
_bowIterations(Parameters::defaultLccBowIterations()),
|
_bowIterations(Parameters::defaultLccBowIterations()),
|
||||||
_bowMaxDepth(Parameters::defaultLccBowMaxDepth()),
|
_bowMaxDepth(Parameters::defaultLccBowMaxDepth()),
|
||||||
|
_bowForce2D(Parameters::defaultLccBowForce2D()),
|
||||||
|
|
||||||
_icpDecimation(Parameters::defaultLccIcp3Decimation()),
|
_icpDecimation(Parameters::defaultLccIcp3Decimation()),
|
||||||
_icpMaxDepth(Parameters::defaultLccIcp3MaxDepth()),
|
_icpMaxDepth(Parameters::defaultLccIcp3MaxDepth()),
|
||||||
@@ -324,6 +325,7 @@ void Memory::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(parameters, Parameters::kLccBowInlierDistance(), _bowInlierDistance);
|
Parameters::parse(parameters, Parameters::kLccBowInlierDistance(), _bowInlierDistance);
|
||||||
Parameters::parse(parameters, Parameters::kLccBowIterations(), _bowIterations);
|
Parameters::parse(parameters, Parameters::kLccBowIterations(), _bowIterations);
|
||||||
Parameters::parse(parameters, Parameters::kLccBowMaxDepth(), _bowMaxDepth);
|
Parameters::parse(parameters, Parameters::kLccBowMaxDepth(), _bowMaxDepth);
|
||||||
|
Parameters::parse(parameters, Parameters::kLccBowForce2D(), _bowForce2D);
|
||||||
Parameters::parse(parameters, Parameters::kLccIcp3Decimation(), _icpDecimation);
|
Parameters::parse(parameters, Parameters::kLccIcp3Decimation(), _icpDecimation);
|
||||||
Parameters::parse(parameters, Parameters::kLccIcp3MaxDepth(), _icpMaxDepth);
|
Parameters::parse(parameters, Parameters::kLccIcp3MaxDepth(), _icpMaxDepth);
|
||||||
Parameters::parse(parameters, Parameters::kLccIcp3VoxelSize(), _icpVoxelSize);
|
Parameters::parse(parameters, Parameters::kLccIcp3VoxelSize(), _icpVoxelSize);
|
||||||
@@ -1636,7 +1638,7 @@ void Memory::rejectLoopClosure(int oldId, int newId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute transform newId -> oldId
|
// compute transform newId -> oldId
|
||||||
Transform Memory::computeVisualTransform(int oldId, int newId, std::string * rejectedMsg) const
|
Transform Memory::computeVisualTransform(int oldId, int newId, std::string * rejectedMsg, int * inliers) const
|
||||||
{
|
{
|
||||||
const Signature * oldS = this->getSignature(oldId);
|
const Signature * oldS = this->getSignature(oldId);
|
||||||
const Signature * newS = this->getSignature(newId);
|
const Signature * newS = this->getSignature(newId);
|
||||||
@@ -1645,7 +1647,7 @@ Transform Memory::computeVisualTransform(int oldId, int newId, std::string * rej
|
|||||||
|
|
||||||
if(oldS && newId)
|
if(oldS && newId)
|
||||||
{
|
{
|
||||||
return computeVisualTransform(*oldS, *newS, rejectedMsg);
|
return computeVisualTransform(*oldS, *newS, rejectedMsg, inliers);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1660,7 +1662,7 @@ Transform Memory::computeVisualTransform(int oldId, int newId, std::string * rej
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute transform newId -> oldId
|
// compute transform newId -> oldId
|
||||||
Transform Memory::computeVisualTransform(const Signature & oldS, const Signature & newS, std::string * rejectedMsg) const
|
Transform Memory::computeVisualTransform(const Signature & oldS, const Signature & newS, std::string * rejectedMsg, int * inliers) const
|
||||||
{
|
{
|
||||||
Transform transform;
|
Transform transform;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
@@ -1690,6 +1692,13 @@ Transform Memory::computeVisualTransform(const Signature & oldS, const Signature
|
|||||||
if(!t.isNull() && inliersCount >= _bowMinInliers)
|
if(!t.isNull() && inliersCount >= _bowMinInliers)
|
||||||
{
|
{
|
||||||
transform = t;
|
transform = t;
|
||||||
|
if(_bowForce2D)
|
||||||
|
{
|
||||||
|
UDEBUG("Forcing 2D...");
|
||||||
|
float x,y,z,r,p,yaw;
|
||||||
|
transform.getTranslationAndEulerAngles(x,y,z, r,p,yaw);
|
||||||
|
transform = util3d::transformFromEigen3f(pcl::getTransformation(x,y,0, 0, 0, yaw));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(inliersCount < _bowMinInliers)
|
else if(inliersCount < _bowMinInliers)
|
||||||
{
|
{
|
||||||
@@ -1701,6 +1710,11 @@ Transform Memory::computeVisualTransform(const Signature & oldS, const Signature
|
|||||||
msg = uFormat("Rejected identity with full inliers.");
|
msg = uFormat("Rejected identity with full inliers.");
|
||||||
UINFO(msg.c_str());
|
UINFO(msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(inliers)
|
||||||
|
{
|
||||||
|
*inliers = inliersCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2489,9 +2503,9 @@ void Memory::getImageDepth(
|
|||||||
float & fy,
|
float & fy,
|
||||||
float & cx,
|
float & cx,
|
||||||
float & cy,
|
float & cy,
|
||||||
Transform & localTransform) const
|
Transform & localTransform)
|
||||||
{
|
{
|
||||||
const Signature * s = this->getSignature(locationId);
|
Signature * s = this->_getSignature(locationId);
|
||||||
if(s)
|
if(s)
|
||||||
{
|
{
|
||||||
rgb = s->getImage();
|
rgb = s->getImage();
|
||||||
@@ -2506,6 +2520,79 @@ void Memory::getImageDepth(
|
|||||||
if(rgb.empty() && this->isRawDataKept() && _dbDriver)
|
if(rgb.empty() && this->isRawDataKept() && _dbDriver)
|
||||||
{
|
{
|
||||||
_dbDriver->getNodeData(locationId, rgb, depth, depth2d, fx, fy, cx, cy, localTransform);
|
_dbDriver->getNodeData(locationId, rgb, depth, depth2d, fx, fy, cx, cy, localTransform);
|
||||||
|
|
||||||
|
if(s)
|
||||||
|
{
|
||||||
|
// keep in cache
|
||||||
|
if(!rgb.empty())
|
||||||
|
{
|
||||||
|
s->setImage(rgb);
|
||||||
|
}
|
||||||
|
if(!depth.empty())
|
||||||
|
{
|
||||||
|
s->setDepth(depth, fx, fy, cx, cy);
|
||||||
|
}
|
||||||
|
if(!depth2d.empty())
|
||||||
|
{
|
||||||
|
s->setDepth2D(depth2d);
|
||||||
|
}
|
||||||
|
if(!localTransform.isNull())
|
||||||
|
{
|
||||||
|
s->setLocalTransform(localTransform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Memory::getImageDepthRaw(
|
||||||
|
int locationId,
|
||||||
|
cv::Mat & rgb,
|
||||||
|
cv::Mat & depth,
|
||||||
|
float & fx,
|
||||||
|
float & fy,
|
||||||
|
float & cx,
|
||||||
|
float & cy,
|
||||||
|
Transform & localTransform)
|
||||||
|
{
|
||||||
|
Signature * s = this->_getSignature(locationId);
|
||||||
|
if(s)
|
||||||
|
{
|
||||||
|
rgb = s->getImageRaw();
|
||||||
|
depth = s->getDepthRaw();
|
||||||
|
fx = s->getDepthFx();
|
||||||
|
fy = s->getDepthFy();
|
||||||
|
cx = s->getDepthCx();
|
||||||
|
cy = s->getDepthCy();
|
||||||
|
localTransform = s->getLocalTransform();
|
||||||
|
}
|
||||||
|
if(rgb.empty())
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> compressedRgb;
|
||||||
|
std::vector<unsigned char> compressedDepth;
|
||||||
|
std::vector<unsigned char> comressedDepth2d;
|
||||||
|
getImageDepth(locationId, compressedRgb, compressedDepth, comressedDepth2d, fx, fy, cx, cy, localTransform);
|
||||||
|
|
||||||
|
//uncomressed data
|
||||||
|
util3d::CompressionThread ctImage(compressedRgb, true);
|
||||||
|
util3d::CompressionThread ctDepth(compressedDepth, true);
|
||||||
|
ctImage.start();
|
||||||
|
ctDepth.start();
|
||||||
|
ctImage.join();
|
||||||
|
ctDepth.join();
|
||||||
|
rgb = ctImage.getUncompressedData();
|
||||||
|
depth = ctDepth.getUncompressedData();
|
||||||
|
if(s)
|
||||||
|
{
|
||||||
|
//save it uncompressed in the signature
|
||||||
|
if(!rgb.empty())
|
||||||
|
{
|
||||||
|
s->setImageRaw(rgb);
|
||||||
|
}
|
||||||
|
if(!depth.empty())
|
||||||
|
{
|
||||||
|
s->setDepthRaw(depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3110,6 +3197,8 @@ Signature * Memory::createSignature(const SensorData & data, bool keepRawData)
|
|||||||
data.depthCx(),
|
data.depthCx(),
|
||||||
data.depthCy(),
|
data.depthCy(),
|
||||||
data.localTransform());
|
data.localTransform());
|
||||||
|
s->setImageRaw(data.image());
|
||||||
|
s->setDepthRaw(data.depth());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -100,6 +100,11 @@ Rtabmap::Rtabmap() :
|
|||||||
_toroIterations(Parameters::defaultRGBDToroIterations()),
|
_toroIterations(Parameters::defaultRGBDToroIterations()),
|
||||||
_databasePath(""),
|
_databasePath(""),
|
||||||
_optimizeFromGraphEnd(Parameters::defaultRGBDOptimizeFromGraphEnd()),
|
_optimizeFromGraphEnd(Parameters::defaultRGBDOptimizeFromGraphEnd()),
|
||||||
|
_reextractLoopClosureFeatures(Parameters::defaultLccReextractLoopClosureFeatures()),
|
||||||
|
_reextractNNType(Parameters::defaultLccReextractNNType()),
|
||||||
|
_reextractNNDR(Parameters::defaultLccReextractNNDR()),
|
||||||
|
_reextractFeatureType(Parameters::defaultLccReextractFeatureType()),
|
||||||
|
_reextractMaxWords(Parameters::defaultLccReextractMaxWords()),
|
||||||
_lcHypothesisId(0),
|
_lcHypothesisId(0),
|
||||||
_lcHypothesisValue(0),
|
_lcHypothesisValue(0),
|
||||||
_retrievedId(0),
|
_retrievedId(0),
|
||||||
@@ -349,6 +354,11 @@ void Rtabmap::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(parameters, Parameters::kRGBDLocalLoopDetectionMaxDiffID(), _localDetectMaxDiffID);
|
Parameters::parse(parameters, Parameters::kRGBDLocalLoopDetectionMaxDiffID(), _localDetectMaxDiffID);
|
||||||
Parameters::parse(parameters, Parameters::kRGBDToroIterations(), _toroIterations);
|
Parameters::parse(parameters, Parameters::kRGBDToroIterations(), _toroIterations);
|
||||||
Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), _optimizeFromGraphEnd);
|
Parameters::parse(parameters, Parameters::kRGBDOptimizeFromGraphEnd(), _optimizeFromGraphEnd);
|
||||||
|
Parameters::parse(parameters, Parameters::kLccReextractLoopClosureFeatures(), _reextractLoopClosureFeatures);
|
||||||
|
Parameters::parse(parameters, Parameters::kLccReextractNNType(), _reextractNNType);
|
||||||
|
Parameters::parse(parameters, Parameters::kLccReextractNNDR(), _reextractNNDR);
|
||||||
|
Parameters::parse(parameters, Parameters::kLccReextractFeatureType(), _reextractFeatureType);
|
||||||
|
Parameters::parse(parameters, Parameters::kLccReextractMaxWords(), _reextractMaxWords);
|
||||||
|
|
||||||
// RGB-D SLAM stuff
|
// RGB-D SLAM stuff
|
||||||
if((iter=parameters.find(Parameters::kLccIcpType())) != parameters.end())
|
if((iter=parameters.find(Parameters::kLccIcpType())) != parameters.end())
|
||||||
@@ -1254,6 +1264,7 @@ bool Rtabmap::process(const SensorData & data)
|
|||||||
// Update loop closure links
|
// Update loop closure links
|
||||||
// (updated: place this after retrieval to be sure that neighbors of the loop closure are in RAM)
|
// (updated: place this after retrieval to be sure that neighbors of the loop closure are in RAM)
|
||||||
//=============================================================
|
//=============================================================
|
||||||
|
int loopClosureVisualInliers = 0; // for statistics
|
||||||
if(_lcHypothesisId>0)
|
if(_lcHypothesisId>0)
|
||||||
{
|
{
|
||||||
//Compute transform if metric data are present
|
//Compute transform if metric data are present
|
||||||
@@ -1261,7 +1272,65 @@ bool Rtabmap::process(const SensorData & data)
|
|||||||
if(_rgbdSlamMode)
|
if(_rgbdSlamMode)
|
||||||
{
|
{
|
||||||
std::string rejectedMsg;
|
std::string rejectedMsg;
|
||||||
transform = _memory->computeVisualTransform(_lcHypothesisId, signature->id(), &rejectedMsg);
|
if(_reextractLoopClosureFeatures)
|
||||||
|
{
|
||||||
|
ParametersMap customParameters;
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kLccBowInlierDistance(), uNumber2Str(_memory->getBowInlierDistance())));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kLccBowIterations(), uNumber2Str(_memory->getBowIterations())));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kLccBowMinInliers(), uNumber2Str(_memory->getBowMinInliers())));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kKpMaxDepth(), uNumber2Str(_memory->getBowMaxDepth())));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kLccBowForce2D(), uNumber2Str(_memory->getBowForce2D())));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kMemRehearsalSimilarity(), "1.0")); // desactivate rehearsal
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kMemImageKept(), "false"));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kMemSTMSize(), "0"));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kKpNNStrategy(), uNumber2Str(_reextractNNType))); // bruteforce
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kKpNndrRatio(), uNumber2Str(_reextractNNDR)));
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kKpDetectorStrategy(), uNumber2Str(_reextractFeatureType))); // FAST/BRIEF
|
||||||
|
customParameters.insert(ParametersPair(Parameters::kKpWordsPerImage(), uNumber2Str(_reextractMaxWords)));
|
||||||
|
|
||||||
|
Memory memory(customParameters);
|
||||||
|
|
||||||
|
UTimer timeT;
|
||||||
|
|
||||||
|
// Add signatures
|
||||||
|
float fxA, fyA, cxA, cyA;
|
||||||
|
float fxB, fyB, cxB, cyB;
|
||||||
|
rtabmap::Transform localTransformA, localTransformB;
|
||||||
|
|
||||||
|
cv::Mat imageA, depthA;
|
||||||
|
_memory->getImageDepthRaw(signature->id(), imageA, depthA, fxA, fyA, cxA, cyA, localTransformA);
|
||||||
|
SensorData dataFrom(imageA, depthA, fxA, fyA, cxA, cyA, Transform::getIdentity(), localTransformA, 1);
|
||||||
|
|
||||||
|
UDEBUG("timeA = %fs", timeT.ticks());
|
||||||
|
|
||||||
|
cv::Mat imageB, depthB;
|
||||||
|
_memory->getImageDepthRaw(_lcHypothesisId, imageB, depthB, fxB, fyB, cxB, cyB, localTransformB);
|
||||||
|
SensorData dataTo(imageB, depthB, fxB, fyB, cxB, cyB, Transform::getIdentity(), localTransformB, 2);
|
||||||
|
|
||||||
|
UDEBUG("timeB = %fs", timeT.ticks());
|
||||||
|
|
||||||
|
if(dataFrom.isValid() && dataFrom.isMetric() && dataTo.isValid() && dataTo.isMetric())
|
||||||
|
{
|
||||||
|
memory.update(dataFrom);
|
||||||
|
UDEBUG("timeUpA = %fs", timeT.ticks());
|
||||||
|
memory.update(dataTo);
|
||||||
|
UDEBUG("timeUpB = %fs", timeT.ticks());
|
||||||
|
|
||||||
|
transform = memory.computeVisualTransform(2, 1, &rejectedMsg, &loopClosureVisualInliers);
|
||||||
|
UDEBUG("timeTransform = %fs", timeT.ticks());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback to normal way (raw data not kept in database...)
|
||||||
|
UWARN("Loop closure: Some images not found in memory for re-extracting "
|
||||||
|
"features, is Mem/RawDataKept=false? Falling back with already extracted 3D features.");
|
||||||
|
transform = _memory->computeVisualTransform(_lcHypothesisId, signature->id(), &rejectedMsg, &loopClosureVisualInliers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transform = _memory->computeVisualTransform(_lcHypothesisId, signature->id(), &rejectedMsg, &loopClosureVisualInliers);
|
||||||
|
}
|
||||||
if(!transform.isNull() && _globalLoopClosureIcpType > 0)
|
if(!transform.isNull() && _globalLoopClosureIcpType > 0)
|
||||||
{
|
{
|
||||||
Transform icpTransform = _memory->computeIcpTransform(_lcHypothesisId, signature->id(), transform, _globalLoopClosureIcpType == 1, &rejectedMsg);
|
Transform icpTransform = _memory->computeIcpTransform(_lcHypothesisId, signature->id(), transform, _globalLoopClosureIcpType == 1, &rejectedMsg);
|
||||||
@@ -1451,6 +1520,7 @@ bool Rtabmap::process(const SensorData & data)
|
|||||||
statistics_.addStatistic(Statistics::kLoopVp_hypothesis(), vpHypothesis);
|
statistics_.addStatistic(Statistics::kLoopVp_hypothesis(), vpHypothesis);
|
||||||
statistics_.addStatistic(Statistics::kLoopReactivateId(), _retrievedId);
|
statistics_.addStatistic(Statistics::kLoopReactivateId(), _retrievedId);
|
||||||
statistics_.addStatistic(Statistics::kLoopHypothesis_ratio(), hypothesisRatio);
|
statistics_.addStatistic(Statistics::kLoopHypothesis_ratio(), hypothesisRatio);
|
||||||
|
statistics_.addStatistic(Statistics::kLoopVisualInliers(), loopClosureVisualInliers);
|
||||||
|
|
||||||
statistics_.addStatistic(Statistics::kLocalLoopOdom_corrected(), scanMatchingSuccess?1:0);
|
statistics_.addStatistic(Statistics::kLocalLoopOdom_corrected(), scanMatchingSuccess?1:0);
|
||||||
statistics_.addStatistic(Statistics::kLocalLoopTime_closures(), localLoopClosuresInTimeFound);
|
statistics_.addStatistic(Statistics::kLocalLoopTime_closures(), localLoopClosuresInTimeFound);
|
||||||
|
|||||||
@@ -3153,7 +3153,6 @@ void MainWindow::viewClouds()
|
|||||||
{
|
{
|
||||||
QWidget * window = new QWidget(this, Qt::Window);
|
QWidget * window = new QWidget(this, Qt::Window);
|
||||||
window->setAttribute(Qt::WA_DeleteOnClose);
|
window->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
window->setWindowFlags(Qt::Dialog);
|
|
||||||
if(meshes.size())
|
if(meshes.size())
|
||||||
{
|
{
|
||||||
window->setWindowTitle(tr("Meshes (%1 nodes)").arg(meshes.size()));
|
window->setWindowTitle(tr("Meshes (%1 nodes)").arg(meshes.size()));
|
||||||
|
|||||||
@@ -415,6 +415,13 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
|||||||
_ui->loopClosure_bowInlierDistance->setObjectName(Parameters::kLccBowInlierDistance().c_str());
|
_ui->loopClosure_bowInlierDistance->setObjectName(Parameters::kLccBowInlierDistance().c_str());
|
||||||
_ui->loopClosure_bowIterations->setObjectName(Parameters::kLccBowIterations().c_str());
|
_ui->loopClosure_bowIterations->setObjectName(Parameters::kLccBowIterations().c_str());
|
||||||
_ui->loopClosure_bowMaxDepth->setObjectName(Parameters::kLccBowMaxDepth().c_str());
|
_ui->loopClosure_bowMaxDepth->setObjectName(Parameters::kLccBowMaxDepth().c_str());
|
||||||
|
_ui->loopClosure_bowForce2D->setObjectName(Parameters::kLccBowForce2D().c_str());
|
||||||
|
|
||||||
|
_ui->groupBox_reextract->setObjectName(Parameters::kLccReextractLoopClosureFeatures().c_str());
|
||||||
|
_ui->reextract_nn->setObjectName(Parameters::kLccReextractNNType().c_str());
|
||||||
|
_ui->reextract_nndrRatio->setObjectName(Parameters::kLccReextractNNDR().c_str());
|
||||||
|
_ui->reextract_type->setObjectName(Parameters::kLccReextractFeatureType().c_str());
|
||||||
|
_ui->reextract_maxFeatures->setObjectName(Parameters::kLccReextractMaxWords().c_str());
|
||||||
|
|
||||||
_ui->globalDetection_icpType->setObjectName(Parameters::kLccIcpType().c_str());
|
_ui->globalDetection_icpType->setObjectName(Parameters::kLccIcpType().c_str());
|
||||||
_ui->globalDetection_icpMaxDistance->setObjectName(Parameters::kLccIcpMaxDistance().c_str());
|
_ui->globalDetection_icpMaxDistance->setObjectName(Parameters::kLccIcpMaxDistance().c_str());
|
||||||
@@ -1363,6 +1370,22 @@ bool PreferencesDialog::validateForm()
|
|||||||
_ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNBruteForce);
|
_ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNBruteForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BOW Reextract features type
|
||||||
|
if(_ui->reextract_nn->currentIndex() == VWDictionary::kNNFlannLSH && _ui->reextract_type->currentIndex() <= 1)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Parameter warning"),
|
||||||
|
tr("With the selected feature type (SURF or SIFT), parameter \"Visual word->Nearest Neighbor\" "
|
||||||
|
"cannot be LSH (used for binary descriptor). KD-tree is set instead."));
|
||||||
|
_ui->reextract_nn->setCurrentIndex(VWDictionary::kNNFlannKdTree);
|
||||||
|
}
|
||||||
|
else if(_ui->reextract_nn->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->reextract_type->currentIndex() >1)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Parameter warning"),
|
||||||
|
tr("With the selected feature type (ORB, FAST, FREAK or BRIEF), parameter \"Visual word->Nearest Neighbor\" "
|
||||||
|
"cannot be KD-Tree (used for float descriptor). BruteForce matching is set instead."));
|
||||||
|
_ui->reextract_nn->setCurrentIndex(VWDictionary::kNNBruteForce);
|
||||||
|
}
|
||||||
|
|
||||||
// odom type
|
// odom type
|
||||||
if(_ui->odom_bin_nn->currentIndex() == VWDictionary::kNNFlannLSH && _ui->odom_type->currentIndex() <= 1)
|
if(_ui->odom_bin_nn->currentIndex() == VWDictionary::kNNFlannLSH && _ui->odom_type->currentIndex() <= 1)
|
||||||
{
|
{
|
||||||
@@ -1896,7 +1919,9 @@ void PreferencesDialog::addParameter(const QObject * object, int value)
|
|||||||
this->addParameters(_ui->groupBox_vh_epipolar2);
|
this->addParameters(_ui->groupBox_vh_epipolar2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(comboBox == _ui->comboBox_detector_strategy || comboBox == _ui->odom_type)
|
else if(comboBox == _ui->comboBox_detector_strategy ||
|
||||||
|
comboBox == _ui->odom_type ||
|
||||||
|
comboBox == _ui->reextract_type)
|
||||||
{
|
{
|
||||||
if(value == 0) // surf
|
if(value == 0) // surf
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1035</width>
|
<width>1035</width>
|
||||||
<height>628</height>
|
<height>789</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -64,8 +64,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>737</width>
|
<width>732</width>
|
||||||
<height>895</height>
|
<height>1198</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>9</number>
|
<number>19</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="page_22">
|
<widget class="QWidget" name="page_22">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_29">
|
<layout class="QVBoxLayout" name="verticalLayout_29">
|
||||||
@@ -4984,7 +4984,7 @@ Warning when set to false: when some nodes are transferred, the first referentia
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_visualTransform2">
|
<widget class="QGroupBox" name="groupBox_visualTransform2">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Visual transformation</string>
|
<string>Loop closure constraint</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_49">
|
<layout class="QVBoxLayout" name="verticalLayout_49">
|
||||||
<item>
|
<item>
|
||||||
@@ -4998,7 +4998,7 @@ Warning when set to false: when some nodes are transferred, the first referentia
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QFormLayout" name="formLayout_6">
|
<layout class="QGridLayout" name="gridLayout_23" columnstretch="0,1">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QSpinBox" name="loopClosure_bowMinInliers">
|
<widget class="QSpinBox" name="loopClosure_bowMinInliers">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
@@ -5019,13 +5019,6 @@ Warning when set to false: when some nodes are transferred, the first referentia
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="label_14">
|
|
||||||
<property name="text">
|
|
||||||
<string>Maximum distance for visual word correspondences.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QDoubleSpinBox" name="loopClosure_bowInlierDistance">
|
<widget class="QDoubleSpinBox" name="loopClosure_bowInlierDistance">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
@@ -5045,10 +5038,10 @@ Warning when set to false: when some nodes are transferred, the first referentia
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLabel" name="label_15">
|
<widget class="QLabel" name="label_14">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Maximum iterations to compute the transform from visual words.</string>
|
<string>Maximum distance for visual word correspondences.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -5068,13 +5061,10 @@ Warning when set to false: when some nodes are transferred, the first referentia
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="label_146">
|
<widget class="QLabel" name="label_15">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max feature depth. Note that parameter "Visual Word"->"Max words depth" is applied before this.</string>
|
<string>Maximum iterations to compute the transform from visual words.</string>
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -5091,8 +5081,229 @@ Warning when set to false: when some nodes are transferred, the first referentia
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="label_146">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max feature depth. Note that parameter "Visual Word"->"Max words depth" is applied before this.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="loopClosure_bowForce2D">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="label_184">
|
||||||
|
<property name="text">
|
||||||
|
<string>Force 2D transform (3DoF: x,y and yaw).</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_reextract">
|
||||||
|
<property name="title">
|
||||||
|
<string>Re-extract features</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_46">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_171">
|
||||||
|
<property name="text">
|
||||||
|
<string>If not activated, when a loop closure constraint must be computed, the words already extracted for the loop closure detector are used. These words are limited (see Visual Word->Words Per Image) and matched to the loop closure detection vocabulary. When the vocabulary is large, there maybe less corresponding words on a loop closure.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_182">
|
||||||
|
<property name="text">
|
||||||
|
<string>By activating the re-extraction of the features, the features from the two images will be re-extracted using the settings below, and matched directly instead of using the big vocabulary. This adds an overhead processing time but it will mostly produce more corresponding words between the images, so better transformation computed. We recommend to use binary features for fast extraction and matching.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_183">
|
||||||
|
<property name="text">
|
||||||
|
<string>Note that this is used only for global loop closure, so not for local loop closure in time.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_25" columnstretch="0,1">
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QComboBox" name="reextract_nn">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>FLANN Linear</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>FLANN KdTree</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>FLANN LSH</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Brute Force</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Brute Force GPU</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QDoubleSpinBox" name="reextract_nndrRatio">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.700000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QSpinBox" name="reextract_maxFeatures">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="label_180">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max features extracted from the images (0 means inf).</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="label_179">
|
||||||
|
<property name="text">
|
||||||
|
<string>Nearest neighbor strategy. FLANN KdTree must be used only with SURF/SIFT. FLANN LSH must be used only with binary feature detector.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="label_181">
|
||||||
|
<property name="text">
|
||||||
|
<string>NNDR ratio
|
||||||
|
(A matching pair is accepted, if its distance is closer than X times the distance of the second nearest neighbor)
|
||||||
|
Lower the ratio -> higher the precision. 0 means disabled, matching the nearest.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QComboBox" name="reextract_type">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>SURF</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>SIFT</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>ORB</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>FAST+FREAK</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>FAST+BRIEF</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>GFTT+FREAK</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>GFTT+BRIEF</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="label_178">
|
||||||
|
<property name="text">
|
||||||
|
<string>Feature detector </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user