Odometry and stereo: added parameter OdomStereo/MaxSlope to filter bad stereo pair matches from cvOpticalFlow

git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@1967 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
matlabbe
2014-11-04 18:58:40 +00:00
parent 54084fc5e1
commit cbb0185adf
12 changed files with 948 additions and 533 deletions

View File

@@ -258,10 +258,11 @@ private:
int _stereoFlowIterations; int _stereoFlowIterations;
double _stereoFlowEpsilon; double _stereoFlowEpsilon;
int _stereoFlowMaxLevel; int _stereoFlowMaxLevel;
float _stereoMaxSlope;
int _stereoSubPixWinSize; int _subPixWinSize;
int _stereoSubPixIterations; int _subPixIterations;
double _stereoSubPixEps; double _subPixEps;
}; };
} // namespace rtabmap } // namespace rtabmap

View File

@@ -143,6 +143,7 @@ private:
int flowIterations_; int flowIterations_;
double flowEps_; double flowEps_;
int flowMaxLevel_; int flowMaxLevel_;
float stereoMaxSlope_;
int subPixWinSize_; int subPixWinSize_;
int subPixIterations_; int subPixIterations_;

View File

@@ -175,6 +175,10 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM_STR(Kp, DictionaryPath, "", "Path of the pre-computed dictionary"); RTABMAP_PARAM_STR(Kp, DictionaryPath, "", "Path of the pre-computed dictionary");
RTABMAP_PARAM(Kp, NewWordsComparedTogether, bool, true, "When adding new words to dictionary, they are compared also with each other (to detect same words in the same signature)."); RTABMAP_PARAM(Kp, NewWordsComparedTogether, bool, true, "When adding new words to dictionary, they are compared also with each other (to detect same words in the same signature).");
RTABMAP_PARAM(Kp, SubPixWinSize, int, 3, "See cv::cornerSubPix().");
RTABMAP_PARAM(Kp, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining.");
RTABMAP_PARAM(Kp, SubPixEps, double, 0.02, "See cv::cornerSubPix().");
//Database //Database
RTABMAP_PARAM(DbSqlite3, InMemory, bool, false, "Using database in the memory instead of a file on the hard disk."); RTABMAP_PARAM(DbSqlite3, InMemory, bool, false, "Using database in the memory instead of a file on the hard disk.");
RTABMAP_PARAM(DbSqlite3, CacheSize, unsigned int, 10000, "Sqlite cache size (default is 2000)."); RTABMAP_PARAM(DbSqlite3, CacheSize, unsigned int, 10000, "Sqlite cache size (default is 2000).");
@@ -276,14 +280,17 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(OdomBow, NNType, int, 3, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4"); RTABMAP_PARAM(OdomBow, NNType, int, 3, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4");
RTABMAP_PARAM(OdomBow, NNDR, float, 0.8, "NNDR: nearest neighbor distance ratio."); RTABMAP_PARAM(OdomBow, NNDR, float, 0.8, "NNDR: nearest neighbor distance ratio.");
// Odometry Optical Flow // Odometry common stuff between BOW and Optical Flow approaches
RTABMAP_PARAM(OdomFlow, WinSize, int, 9, "See cv::calcOpticalFlowPyrLK()."); RTABMAP_PARAM(OdomFlow, WinSize, int, 9, "Used for optical flow approach and for stereo matching. See cv::calcOpticalFlowPyrLK().");
RTABMAP_PARAM(OdomFlow, Iterations, int, 20, "See cv::calcOpticalFlowPyrLK()."); RTABMAP_PARAM(OdomFlow, Iterations, int, 20, "Used for optical flow approach and for stereo matching. See cv::calcOpticalFlowPyrLK().");
RTABMAP_PARAM(OdomFlow, Eps, double, 0.02, "See cv::calcOpticalFlowPyrLK()."); RTABMAP_PARAM(OdomFlow, Eps, double, 0.02, "Used for optical flow approach and for stereo matching. See cv::calcOpticalFlowPyrLK().");
RTABMAP_PARAM(OdomFlow, MaxLevel, int, 4, "See cv::calcOpticalFlowPyrLK()."); RTABMAP_PARAM(OdomFlow, MaxLevel, int, 4, "Used for optical flow approach and for stereo matching. See cv::calcOpticalFlowPyrLK().");
RTABMAP_PARAM(OdomFlow, SubPixWinSize, int, 3, "See cv::cornerSubPix().");
RTABMAP_PARAM(OdomFlow, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining."); RTABMAP_PARAM(OdomSubPix, WinSize, int, 3, "Can be used with BOW and optical flow approaches. See cv::cornerSubPix().");
RTABMAP_PARAM(OdomFlow, SubPixEps, double, 0.02, "See cv::cornerSubPix()."); RTABMAP_PARAM(OdomSubPix, Iterations, int, 0, "Can be used with BOW and optical flow approaches. See cv::cornerSubPix(). 0 disables sub pixel refining.");
RTABMAP_PARAM(OdomSubPix, Eps, double, 0.02, "Can be used with BOW and optical flow approaches. See cv::cornerSubPix().");
RTABMAP_PARAM(OdomStereo, MaxSlope, float, 0.1, "The maximum slope for each stereo pairs.");
// Loop closure constraint // Loop closure constraint
RTABMAP_PARAM(LccIcp, Type, int, 0, "0=No ICP, 1=ICP 3D, 2=ICP 2D"); RTABMAP_PARAM(LccIcp, Type, int, 0, "0=No ICP, 1=ICP 3D, 2=ICP 2D");
@@ -321,9 +328,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Stereo, Iterations, int, 20, "See cv::calcOpticalFlowPyrLK()."); RTABMAP_PARAM(Stereo, Iterations, int, 20, "See cv::calcOpticalFlowPyrLK().");
RTABMAP_PARAM(Stereo, Eps, double, 0.02, "See cv::calcOpticalFlowPyrLK()."); RTABMAP_PARAM(Stereo, Eps, double, 0.02, "See cv::calcOpticalFlowPyrLK().");
RTABMAP_PARAM(Stereo, MaxLevel, int, 4, "See cv::calcOpticalFlowPyrLK()."); RTABMAP_PARAM(Stereo, MaxLevel, int, 4, "See cv::calcOpticalFlowPyrLK().");
RTABMAP_PARAM(Stereo, SubPixWinSize, int, 3, "See cv::cornerSubPix()."); RTABMAP_PARAM(Stereo, MaxSlope, float, 0.1, "The maximum slope for each stereo pairs.");
RTABMAP_PARAM(Stereo, SubPixIterations, int, 0, "See cv::cornerSubPix(). 0 disables sub pixel refining.");
RTABMAP_PARAM(Stereo, SubPixEps, double, 0.02, "See cv::cornerSubPix().");
public: public:
virtual ~Parameters(); virtual ~Parameters();

View File

@@ -190,7 +190,8 @@ cv::Mat RTABMAP_EXP disparityFromStereoImages(
int flowWinSize = 9, int flowWinSize = 9,
int flowMaxLevel = 4, int flowMaxLevel = 4,
int flowIterations = 20, int flowIterations = 20,
double flowEps = 0.02); double flowEps = 0.02,
float maxCorrespondencesSlope = 0.1f);
cv::Mat RTABMAP_EXP depthFromStereoImages( cv::Mat RTABMAP_EXP depthFromStereoImages(
const cv::Mat & leftImage, const cv::Mat & leftImage,
@@ -207,7 +208,8 @@ cv::Mat RTABMAP_EXP disparityFromStereoCorrespondences(
const cv::Mat & leftImage, const cv::Mat & leftImage,
const std::vector<cv::Point2f> & leftCorners, const std::vector<cv::Point2f> & leftCorners,
const std::vector<cv::Point2f> & rightCorners, const std::vector<cv::Point2f> & rightCorners,
const std::vector<unsigned char> & mask); const std::vector<unsigned char> & mask,
float maxSlope = 0.1f);
cv::Mat RTABMAP_EXP depthFromStereoCorrespondences( cv::Mat RTABMAP_EXP depthFromStereoCorrespondences(
const cv::Mat & leftImage, const cv::Mat & leftImage,

View File

@@ -108,10 +108,11 @@ Memory::Memory(const ParametersMap & parameters) :
_stereoFlowIterations(Parameters::defaultStereoIterations()), _stereoFlowIterations(Parameters::defaultStereoIterations()),
_stereoFlowEpsilon(Parameters::defaultStereoEps()), _stereoFlowEpsilon(Parameters::defaultStereoEps()),
_stereoFlowMaxLevel(Parameters::defaultStereoMaxLevel()), _stereoFlowMaxLevel(Parameters::defaultStereoMaxLevel()),
_stereoMaxSlope(Parameters::defaultStereoMaxSlope()),
_stereoSubPixWinSize(Parameters::defaultStereoSubPixWinSize()), _subPixWinSize(Parameters::defaultKpSubPixWinSize()),
_stereoSubPixIterations(Parameters::defaultStereoSubPixIterations()), _subPixIterations(Parameters::defaultKpSubPixIterations()),
_stereoSubPixEps(Parameters::defaultStereoSubPixEps()) _subPixEps(Parameters::defaultKpSubPixEps())
{ {
_vwd = new VWDictionary(parameters); _vwd = new VWDictionary(parameters);
this->parseParameters(parameters); this->parseParameters(parameters);
@@ -418,9 +419,7 @@ void Memory::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kStereoIterations(), _stereoFlowIterations); Parameters::parse(parameters, Parameters::kStereoIterations(), _stereoFlowIterations);
Parameters::parse(parameters, Parameters::kStereoEps(), _stereoFlowEpsilon); Parameters::parse(parameters, Parameters::kStereoEps(), _stereoFlowEpsilon);
Parameters::parse(parameters, Parameters::kStereoMaxLevel(), _stereoFlowMaxLevel); Parameters::parse(parameters, Parameters::kStereoMaxLevel(), _stereoFlowMaxLevel);
Parameters::parse(parameters, Parameters::kStereoSubPixWinSize(), _stereoSubPixWinSize); Parameters::parse(parameters, Parameters::kStereoMaxSlope(), _stereoMaxSlope);
Parameters::parse(parameters, Parameters::kStereoSubPixIterations(), _stereoSubPixIterations);
Parameters::parse(parameters, Parameters::kStereoSubPixEps(), _stereoSubPixEps);
UASSERT_MSG(_bowMinInliers >= 1, uFormat("value=%d", _bowMinInliers).c_str()); UASSERT_MSG(_bowMinInliers >= 1, uFormat("value=%d", _bowMinInliers).c_str());
UASSERT_MSG(_bowInlierDistance > 0.0f, uFormat("value=%f", _bowInlierDistance).c_str()); UASSERT_MSG(_bowInlierDistance > 0.0f, uFormat("value=%f", _bowInlierDistance).c_str());
@@ -452,6 +451,10 @@ void Memory::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kKpMaxDepth(), _wordsMaxDepth); Parameters::parse(parameters, Parameters::kKpMaxDepth(), _wordsMaxDepth);
Parameters::parse(parameters, Parameters::kKpWordsPerImage(), _wordsPerImageTarget); Parameters::parse(parameters, Parameters::kKpWordsPerImage(), _wordsPerImageTarget);
Parameters::parse(parameters, Parameters::kKpSubPixWinSize(), _subPixWinSize);
Parameters::parse(parameters, Parameters::kKpSubPixIterations(), _subPixIterations);
Parameters::parse(parameters, Parameters::kKpSubPixEps(), _subPixEps);
if((iter=parameters.find(Parameters::kKpRoiRatios())) != parameters.end()) if((iter=parameters.find(Parameters::kKpRoiRatios())) != parameters.end())
{ {
this->setRoi((*iter).second); this->setRoi((*iter).second);
@@ -3098,101 +3101,166 @@ Signature * Memory::createSignature(const SensorData & data, bool keepRawData, S
{ {
//stereo //stereo
cv::Mat disparity; cv::Mat disparity;
keypoints = _feature2D->generateKeypoints(imageMono, 0, roi); bool subPixelOn = false;
if(_subPixWinSize > 0 && _subPixIterations > 0)
{
subPixelOn = true;
}
keypoints = _feature2D->generateKeypoints(imageMono, subPixelOn?_wordsPerImageTarget:0, roi);
t = timer.ticks(); t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f); if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f);
UDEBUG("time keypoints (%d) = %fs", (int)keypoints.size(), t); UDEBUG("time keypoints (%d) = %fs", (int)keypoints.size(), t);
std::vector<cv::Point2f> leftCorners;
cv::KeyPoint::convert(keypoints, leftCorners);
if(_stereoSubPixWinSize > 0 && _stereoSubPixIterations > 0)
{
cv::cornerSubPix( imageMono, leftCorners,
cv::Size( _stereoSubPixWinSize, _stereoSubPixWinSize ),
cv::Size( -1, -1 ),
cv::TermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, _stereoSubPixIterations, _stereoSubPixEps ) );
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemStereo_subpixel(), t*1000.0f);
UDEBUG("time subpix left kpts=%fs", t);
}
//generate a disparity map
disparity = util3d::disparityFromStereoImages(
imageMono,
data.rightImage(),
leftCorners,
_stereoFlowWinSize,
_stereoFlowMaxLevel,
_stereoFlowIterations,
_stereoFlowEpsilon);
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemStereo_correspondences(), t*1000.0f);
UDEBUG("generate disparity = %fs", t);
if(_wordsMaxDepth > 0.0f)
{
// disparity = baseline * fx / depth;
float minDisparity = data.baseline() * data.fx() / _wordsMaxDepth;
Feature2D::filterKeypointsByDisparity(keypoints, disparity, minDisparity);
UDEBUG("filter keypoints by disparity (%d)", (int)keypoints.size());
}
if(_wordsPerImageTarget && (int)keypoints.size() > _wordsPerImageTarget)
{
Feature2D::limitKeypoints(keypoints, _wordsPerImageTarget);
UDEBUG("limit keypoints max (%d)", _wordsPerImageTarget);
}
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_filtering(), t*1000.0f);
UDEBUG("time keypoints filtering = %fs", _wordsPerImageTarget);
if(keypoints.size()) if(keypoints.size())
{ {
descriptors = _feature2D->generateDescriptors(imageMono, keypoints); std::vector<cv::Point2f> leftCorners;
t = timer.ticks(); if(subPixelOn)
if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f); {
UDEBUG("time descriptors (%d) = %fs", descriptors.rows, t); // descriptors should be extracted before subpixel
descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
UDEBUG("time descriptors (%d) = %fs", descriptors.rows, t);
keypoints3D = util3d::generateKeypoints3DDisparity(keypoints, disparity, data.fx(), data.baseline(), data.cx(), data.cy(), data.localTransform()); cv::KeyPoint::convert(keypoints, leftCorners);
cv::cornerSubPix( imageMono, leftCorners,
cv::Size( _subPixWinSize, _subPixWinSize ),
cv::Size( -1, -1 ),
cv::TermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, _subPixIterations, _subPixEps ) );
for(unsigned int i=0;i<leftCorners.size(); ++i)
{
keypoints[i].pt = leftCorners[i];
}
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemStereo_subpixel(), t*1000.0f);
UDEBUG("time subpix left kpts=%fs", t);
}
else
{
cv::KeyPoint::convert(keypoints, leftCorners);
}
//generate a disparity map
disparity = util3d::disparityFromStereoImages(
imageMono,
data.rightImage(),
leftCorners,
_stereoFlowWinSize,
_stereoFlowMaxLevel,
_stereoFlowIterations,
_stereoFlowEpsilon,
_stereoMaxSlope);
t = timer.ticks(); t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f); if(stats) stats->addStatistic(Statistics::kTimingMemStereo_correspondences(), t*1000.0f);
UDEBUG("time keypoints 3D (%d) = %fs", (int)keypoints3D->size(), t); UDEBUG("generate disparity = %fs", t);
if(_wordsMaxDepth > 0.0f)
{
// disparity = baseline * fx / depth;
float minDisparity = data.baseline() * data.fx() / _wordsMaxDepth;
Feature2D::filterKeypointsByDisparity(keypoints, descriptors, disparity, minDisparity);
UDEBUG("filter keypoints by disparity (%d)", (int)keypoints.size());
}
if(_wordsPerImageTarget && (int)keypoints.size() > _wordsPerImageTarget)
{
Feature2D::limitKeypoints(keypoints, descriptors, _wordsPerImageTarget);
UDEBUG("limit keypoints max (%d)", _wordsPerImageTarget);
}
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_filtering(), t*1000.0f);
UDEBUG("time keypoints filtering = %fs", _wordsPerImageTarget);
if(keypoints.size())
{
if(!subPixelOn)
{
descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
UDEBUG("time descriptors (%d) = %fs", descriptors.rows, t);
}
keypoints3D = util3d::generateKeypoints3DDisparity(keypoints, disparity, data.fx(), data.baseline(), data.cx(), data.cy(), data.localTransform());
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f);
UDEBUG("time keypoints 3D (%d) = %fs", (int)keypoints3D->size(), t);
}
} }
} }
else if(!data.depth().empty()) else if(!data.depth().empty())
{ {
//depth //depth
keypoints = _feature2D->generateKeypoints(imageMono, 0, roi); bool subPixelOn = false;
if(_subPixWinSize > 0 && _subPixIterations > 0)
{
subPixelOn = true;
}
keypoints = _feature2D->generateKeypoints(imageMono, subPixelOn?_wordsPerImageTarget:0, roi);
t = timer.ticks(); t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f); if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f);
UDEBUG("time keypoints (%d) = %fs", (int)keypoints.size(), t); UDEBUG("time keypoints (%d) = %fs", (int)keypoints.size(), t);
if(_wordsMaxDepth > 0.0f)
{
Feature2D::filterKeypointsByDepth(keypoints, data.depth(), _wordsMaxDepth);
UDEBUG("filter keypoints by depth (%d)", (int)keypoints.size());
}
if(_wordsPerImageTarget && (int)keypoints.size() > _wordsPerImageTarget)
{
Feature2D::limitKeypoints(keypoints, _wordsPerImageTarget);
UDEBUG("limit keypoints max (%d)", _wordsPerImageTarget);
}
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_filtering(), t*1000.0f);
UDEBUG("time keypoints filtering = %fs", _wordsPerImageTarget);
if(keypoints.size()) if(keypoints.size())
{ {
descriptors = _feature2D->generateDescriptors(imageMono, keypoints); if(subPixelOn)
t = timer.ticks(); {
if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f); // descriptors should be extracted before subpixel
UDEBUG("time descriptors (%d) = %fs", descriptors.rows, t); descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
UDEBUG("time descriptors (%d) = %fs", descriptors.rows, t);
keypoints3D = util3d::generateKeypoints3DDepth(keypoints, data.depth(), data.fx(), data.fy(), data.cx(), data.cy(), data.localTransform()); std::vector<cv::Point2f> leftCorners;
cv::KeyPoint::convert(keypoints, leftCorners);
cv::cornerSubPix( imageMono, leftCorners,
cv::Size( _subPixWinSize, _subPixWinSize ),
cv::Size( -1, -1 ),
cv::TermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, _subPixIterations, _subPixEps ) );
for(unsigned int i=0;i<leftCorners.size(); ++i)
{
keypoints[i].pt = leftCorners[i];
}
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemStereo_subpixel(), t*1000.0f);
UDEBUG("time subpix left kpts=%fs", t);
}
if(_wordsMaxDepth > 0.0f)
{
Feature2D::filterKeypointsByDepth(keypoints, descriptors, data.depth(), _wordsMaxDepth);
UDEBUG("filter keypoints by depth (%d)", (int)keypoints.size());
}
if(_wordsPerImageTarget && (int)keypoints.size() > _wordsPerImageTarget)
{
Feature2D::limitKeypoints(keypoints, descriptors, _wordsPerImageTarget);
UDEBUG("limit keypoints max (%d)", _wordsPerImageTarget);
}
t = timer.ticks(); t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f); if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_filtering(), t*1000.0f);
UDEBUG("time keypoints 3D (%d) = %fs", (int)keypoints3D->size(), t); UDEBUG("time keypoints filtering = %fs", _wordsPerImageTarget);
if(keypoints.size())
{
if(!subPixelOn)
{
descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
UDEBUG("time descriptors (%d) = %fs", descriptors.rows, t);
}
keypoints3D = util3d::generateKeypoints3DDepth(keypoints, data.depth(), data.fx(), data.fy(), data.cx(), data.cy(), data.localTransform());
t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f);
UDEBUG("time keypoints 3D (%d) = %fs", (int)keypoints3D->size(), t);
}
} }
} }
else else
@@ -3252,7 +3320,8 @@ Signature * Memory::createSignature(const SensorData & data, bool keepRawData, S
_stereoFlowWinSize, _stereoFlowWinSize,
_stereoFlowMaxLevel, _stereoFlowMaxLevel,
_stereoFlowIterations, _stereoFlowIterations,
_stereoFlowEpsilon); _stereoFlowEpsilon,
_stereoMaxSlope);
t = timer.ticks(); t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemStereo_correspondences(), t*1000.0f); if(stats) stats->addStatistic(Statistics::kTimingMemStereo_correspondences(), t*1000.0f);
UDEBUG("generate disparity = %fs", t); UDEBUG("generate disparity = %fs", t);

View File

@@ -157,23 +157,25 @@ OdometryBOW::OdometryBOW(const ParametersMap & parameters) :
int flowIterations_ = Parameters::defaultOdomFlowIterations(); int flowIterations_ = Parameters::defaultOdomFlowIterations();
double flowEps_ = Parameters::defaultOdomFlowEps(); double flowEps_ = Parameters::defaultOdomFlowEps();
int flowMaxLevel_ = Parameters::defaultOdomFlowMaxLevel(); int flowMaxLevel_ = Parameters::defaultOdomFlowMaxLevel();
int subPixWinSize_ = Parameters::defaultOdomFlowSubPixWinSize(); float stereoMaxSlope_ = Parameters::defaultOdomStereoMaxSlope();
int subPixIterations_ = Parameters::defaultOdomFlowSubPixIterations(); int subPixWinSize_ = Parameters::defaultOdomSubPixWinSize();
double subPixEps_ = Parameters::defaultOdomFlowSubPixEps(); int subPixIterations_ = Parameters::defaultOdomSubPixIterations();
double subPixEps_ = Parameters::defaultOdomSubPixEps();
Parameters::parse(parameters, Parameters::kOdomFlowWinSize(), flowWinSize); Parameters::parse(parameters, Parameters::kOdomFlowWinSize(), flowWinSize);
Parameters::parse(parameters, Parameters::kOdomFlowIterations(), flowIterations_); Parameters::parse(parameters, Parameters::kOdomFlowIterations(), flowIterations_);
Parameters::parse(parameters, Parameters::kOdomFlowEps(), flowEps_); Parameters::parse(parameters, Parameters::kOdomFlowEps(), flowEps_);
Parameters::parse(parameters, Parameters::kOdomFlowMaxLevel(), flowMaxLevel_); Parameters::parse(parameters, Parameters::kOdomFlowMaxLevel(), flowMaxLevel_);
Parameters::parse(parameters, Parameters::kOdomFlowSubPixWinSize(), subPixWinSize_); Parameters::parse(parameters, Parameters::kOdomSubPixWinSize(), subPixWinSize_);
Parameters::parse(parameters, Parameters::kOdomFlowSubPixIterations(), subPixIterations_); Parameters::parse(parameters, Parameters::kOdomSubPixIterations(), subPixIterations_);
Parameters::parse(parameters, Parameters::kOdomFlowSubPixEps(), subPixEps_); Parameters::parse(parameters, Parameters::kOdomSubPixEps(), subPixEps_);
customParameters.insert(ParametersPair(Parameters::kStereoWinSize(), uNumber2Str(flowWinSize))); customParameters.insert(ParametersPair(Parameters::kStereoWinSize(), uNumber2Str(flowWinSize)));
customParameters.insert(ParametersPair(Parameters::kStereoIterations(), uNumber2Str(flowIterations_))); customParameters.insert(ParametersPair(Parameters::kStereoIterations(), uNumber2Str(flowIterations_)));
customParameters.insert(ParametersPair(Parameters::kStereoEps(), uNumber2Str(flowEps_))); customParameters.insert(ParametersPair(Parameters::kStereoEps(), uNumber2Str(flowEps_)));
customParameters.insert(ParametersPair(Parameters::kStereoMaxLevel(), uNumber2Str(flowMaxLevel_))); customParameters.insert(ParametersPair(Parameters::kStereoMaxLevel(), uNumber2Str(flowMaxLevel_)));
customParameters.insert(ParametersPair(Parameters::kStereoSubPixWinSize(), uNumber2Str(subPixWinSize_))); customParameters.insert(ParametersPair(Parameters::kStereoMaxSlope(), uNumber2Str(stereoMaxSlope_)));
customParameters.insert(ParametersPair(Parameters::kStereoSubPixIterations(), uNumber2Str(subPixIterations_))); customParameters.insert(ParametersPair(Parameters::kKpSubPixWinSize(), uNumber2Str(subPixWinSize_)));
customParameters.insert(ParametersPair(Parameters::kStereoSubPixEps(), uNumber2Str(subPixEps_))); customParameters.insert(ParametersPair(Parameters::kKpSubPixIterations(), uNumber2Str(subPixIterations_)));
customParameters.insert(ParametersPair(Parameters::kKpSubPixEps(), uNumber2Str(subPixEps_)));
// add only feature stuff // add only feature stuff
for(ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter) for(ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
@@ -445,18 +447,20 @@ OdometryOpticalFlow::OdometryOpticalFlow(const ParametersMap & parameters) :
flowIterations_(Parameters::defaultOdomFlowIterations()), flowIterations_(Parameters::defaultOdomFlowIterations()),
flowEps_(Parameters::defaultOdomFlowEps()), flowEps_(Parameters::defaultOdomFlowEps()),
flowMaxLevel_(Parameters::defaultOdomFlowMaxLevel()), flowMaxLevel_(Parameters::defaultOdomFlowMaxLevel()),
subPixWinSize_(Parameters::defaultOdomFlowSubPixWinSize()), stereoMaxSlope_(Parameters::defaultOdomStereoMaxSlope()),
subPixIterations_(Parameters::defaultOdomFlowSubPixIterations()), subPixWinSize_(Parameters::defaultOdomSubPixWinSize()),
subPixEps_(Parameters::defaultOdomFlowSubPixEps()), subPixIterations_(Parameters::defaultOdomSubPixIterations()),
subPixEps_(Parameters::defaultOdomSubPixEps()),
lastCorners3D_(new pcl::PointCloud<pcl::PointXYZ>) lastCorners3D_(new pcl::PointCloud<pcl::PointXYZ>)
{ {
Parameters::parse(parameters, Parameters::kOdomFlowWinSize(), flowWinSize_); Parameters::parse(parameters, Parameters::kOdomFlowWinSize(), flowWinSize_);
Parameters::parse(parameters, Parameters::kOdomFlowIterations(), flowIterations_); Parameters::parse(parameters, Parameters::kOdomFlowIterations(), flowIterations_);
Parameters::parse(parameters, Parameters::kOdomFlowEps(), flowEps_); Parameters::parse(parameters, Parameters::kOdomFlowEps(), flowEps_);
Parameters::parse(parameters, Parameters::kOdomFlowMaxLevel(), flowMaxLevel_); Parameters::parse(parameters, Parameters::kOdomFlowMaxLevel(), flowMaxLevel_);
Parameters::parse(parameters, Parameters::kOdomFlowSubPixWinSize(), subPixWinSize_); Parameters::parse(parameters, Parameters::kOdomStereoMaxSlope(), stereoMaxSlope_);
Parameters::parse(parameters, Parameters::kOdomFlowSubPixIterations(), subPixIterations_); Parameters::parse(parameters, Parameters::kOdomSubPixWinSize(), subPixWinSize_);
Parameters::parse(parameters, Parameters::kOdomFlowSubPixEps(), subPixEps_); Parameters::parse(parameters, Parameters::kOdomSubPixIterations(), subPixIterations_);
Parameters::parse(parameters, Parameters::kOdomSubPixEps(), subPixEps_);
ParametersMap::const_iterator iter; ParametersMap::const_iterator iter;
Feature2D::Type detectorStrategy = (Feature2D::Type)Parameters::defaultOdomFeatureType(); Feature2D::Type detectorStrategy = (Feature2D::Type)Parameters::defaultOdomFeatureType();
@@ -624,7 +628,10 @@ Transform OdometryOpticalFlow::computeTransformStereo(
{ {
float lastDisparity = lastCornersKept[i].x - lastCornersKeptRight[i].x; float lastDisparity = lastCornersKept[i].x - lastCornersKeptRight[i].x;
float newDisparity = newCornersKept[i].x - newCornersKeptRight[i].x; float newDisparity = newCornersKept[i].x - newCornersKeptRight[i].x;
if(lastDisparity > 0.0f && newDisparity > 0.0f) float lastSlope = fabs((lastCornersKept[i].y-lastCornersKeptRight[i].y) / (lastCornersKept[i].x-lastCornersKeptRight[i].x));
float newSlope = fabs((newCornersKept[i].y-newCornersKeptRight[i].y) / (newCornersKept[i].x-newCornersKeptRight[i].x));
if(lastDisparity > 0.0f && newDisparity > 0.0f &&
lastSlope < stereoMaxSlope_ && newSlope < stereoMaxSlope_)
{ {
pcl::PointXYZ lastPt3D = util3d::projectDisparityTo3D( pcl::PointXYZ lastPt3D = util3d::projectDisparityTo3D(
lastCornersKept[i], lastCornersKept[i],
@@ -697,14 +704,14 @@ Transform OdometryOpticalFlow::computeTransformStereo(
UWARN("Transform not valid (inliers = %d/%d)", inliers, correspondences); UWARN("Transform not valid (inliers = %d/%d)", inliers, correspondences);
} }
/*if(correspondencesLast->size() >= 6) //if(correspondencesLast->size() >= 6)
{ //{
UWARN("saved pcd"); // UWARN("saved pcd");
pcl::io::savePCDFile("last.pcd", *correspondencesLast); // pcl::io::savePCDFile("last.pcd", *correspondencesLast);
pcl::io::savePCDFile("new.pcd", *correspondencesNew); // pcl::io::savePCDFile("new.pcd", *correspondencesNew);
correspondencesNew = util3d::transformPointCloud(correspondencesNew, output); //correspondencesNew = util3d::transformPointCloud(correspondencesNew, output);
pcl::io::savePCDFile("new2.pcd", *correspondencesNew); //pcl::io::savePCDFile("new2.pcd", *correspondencesNew);
}*/ //}
} }
else else
{ {

View File

@@ -893,7 +893,8 @@ cv::Mat disparityFromStereoImages(
int flowWinSize, int flowWinSize,
int flowMaxLevel, int flowMaxLevel,
int flowIterations, int flowIterations,
double flowEps) double flowEps,
float maxCorrespondencesSlope)
{ {
UASSERT(!leftImage.empty() && !rightImage.empty() && UASSERT(!leftImage.empty() && !rightImage.empty() &&
leftImage.type() == CV_8UC1 && rightImage.type() == CV_8UC1 && leftImage.type() == CV_8UC1 && rightImage.type() == CV_8UC1 &&
@@ -917,7 +918,7 @@ cv::Mat disparityFromStereoImages(
cv::OPTFLOW_LK_GET_MIN_EIGENVALS, 1e-4); cv::OPTFLOW_LK_GET_MIN_EIGENVALS, 1e-4);
UDEBUG("cv::calcOpticalFlowPyrLK() end"); UDEBUG("cv::calcOpticalFlowPyrLK() end");
return disparityFromStereoCorrespondences(leftImage, leftCorners, rightCorners, status); return disparityFromStereoCorrespondences(leftImage, leftCorners, rightCorners, status, maxCorrespondencesSlope);
} }
cv::Mat depthFromStereoImages( cv::Mat depthFromStereoImages(
@@ -961,7 +962,8 @@ cv::Mat disparityFromStereoCorrespondences(
const cv::Mat & leftImage, const cv::Mat & leftImage,
const std::vector<cv::Point2f> & leftCorners, const std::vector<cv::Point2f> & leftCorners,
const std::vector<cv::Point2f> & rightCorners, const std::vector<cv::Point2f> & rightCorners,
const std::vector<unsigned char> & mask) const std::vector<unsigned char> & mask,
float maxSlope)
{ {
UASSERT(!leftImage.empty() && leftCorners.size() == rightCorners.size()); UASSERT(!leftImage.empty() && leftCorners.size() == rightCorners.size());
UASSERT(mask.size() == 0 || mask.size() == leftCorners.size()); UASSERT(mask.size() == 0 || mask.size() == leftCorners.size());
@@ -971,7 +973,8 @@ cv::Mat disparityFromStereoCorrespondences(
if(mask.size() == 0 || mask[i]) if(mask.size() == 0 || mask[i])
{ {
float d = leftCorners[i].x - rightCorners[i].x; float d = leftCorners[i].x - rightCorners[i].x;
if(d > 0.0f) float slope = fabs((leftCorners[i].y - rightCorners[i].y) / (leftCorners[i].x - rightCorners[i].x));
if(d > 0.0f && slope < maxSlope)
{ {
disparity.at<float>(int(leftCorners[i].y+0.5f), int(leftCorners[i].x+0.5f)) = d; disparity.at<float>(int(leftCorners[i].y+0.5f), int(leftCorners[i].x+0.5f)) = d;
} }

View File

@@ -52,6 +52,7 @@ namespace rtabmap
{ {
class Memory; class Memory;
class ImageView; class ImageView;
class Signature;
class RTABMAPGUI_EXP DatabaseViewer : public QMainWindow class RTABMAPGUI_EXP DatabaseViewer : public QMainWindow
{ {
@@ -104,6 +105,7 @@ private:
rtabmap::ImageView * view, rtabmap::ImageView * view,
QLabel * labelId, QLabel * labelId,
bool updateConstraintView = true); bool updateConstraintView = true);
void updateStereo(const Signature * data);
void updateWordsMatching(); void updateWordsMatching();
void updateConstraintView(const rtabmap::Link & link, void updateConstraintView(const rtabmap::Link & link,
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloudFrom = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>), const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloudFrom = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>),

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtGui/QInputDialog> #include <QtGui/QInputDialog>
#include <QtGui/QGraphicsLineItem> #include <QtGui/QGraphicsLineItem>
#include <QtGui/QCloseEvent> #include <QtGui/QCloseEvent>
#include <QtGui/QGraphicsOpacityEffect>
#include <QtCore/QBuffer> #include <QtCore/QBuffer>
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
#include <rtabmap/utilite/ULogger.h> #include <rtabmap/utilite/ULogger.h>
@@ -47,6 +48,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rtabmap/gui/UCv2Qt.h" #include "rtabmap/gui/UCv2Qt.h"
#include "rtabmap/core/util3d.h" #include "rtabmap/core/util3d.h"
#include "rtabmap/core/Signature.h" #include "rtabmap/core/Signature.h"
#include "rtabmap/core/Features2d.h"
#include "rtabmap/gui/DataRecorder.h" #include "rtabmap/gui/DataRecorder.h"
#include "rtabmap/core/SensorData.h" #include "rtabmap/core/SensorData.h"
#include "ExportDialog.h" #include "ExportDialog.h"
@@ -76,12 +78,14 @@ DatabaseViewer::DatabaseViewer(QWidget * parent) :
ui_->dockWidget_graphView->setVisible(false); ui_->dockWidget_graphView->setVisible(false);
ui_->dockWidget_icp->setVisible(false); ui_->dockWidget_icp->setVisible(false);
ui_->dockWidget_visual->setVisible(false); ui_->dockWidget_visual->setVisible(false);
ui_->dockWidget_stereoView->setVisible(false);
ui_->dockWidget_icp->setFloating(true); ui_->dockWidget_icp->setFloating(true);
ui_->dockWidget_visual->setFloating(true); ui_->dockWidget_visual->setFloating(true);
ui_->menuView->addAction(ui_->dockWidget_constraints->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_constraints->toggleViewAction());
ui_->menuView->addAction(ui_->dockWidget_graphView->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_graphView->toggleViewAction());
ui_->menuView->addAction(ui_->dockWidget_icp->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_icp->toggleViewAction());
ui_->menuView->addAction(ui_->dockWidget_visual->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_visual->toggleViewAction());
ui_->menuView->addAction(ui_->dockWidget_stereoView->toggleViewAction());
connect(ui_->dockWidget_graphView->toggleViewAction(), SIGNAL(triggered()), this, SLOT(updateGraphView())); connect(ui_->dockWidget_graphView->toggleViewAction(), SIGNAL(triggered()), this, SLOT(updateGraphView()));
connect(ui_->actionQuit, SIGNAL(triggered()), this, SLOT(close())); connect(ui_->actionQuit, SIGNAL(triggered()), this, SLOT(close()));
@@ -994,6 +998,12 @@ void DatabaseViewer::update(int value,
} }
mapId = memory_->getMapId(id); mapId = memory_->getMapId(id);
//stereo
if(!data.getDepthRaw().empty() && data.getDepthRaw().type() == CV_8UC1)
{
this->updateStereo(&data);
}
} }
if(!imgDepth.isNull()) if(!imgDepth.isNull())
@@ -1121,6 +1131,168 @@ void DatabaseViewer::update(int value,
view->fitInView(view->sceneRect(), Qt::KeepAspectRatio); view->fitInView(view->sceneRect(), Qt::KeepAspectRatio);
} }
void DatabaseViewer::updateStereo(const Signature * data)
{
if(ui_->dockWidget_stereoView->isVisible() && !data->getImageRaw().empty() && !data->getDepthRaw().empty() && data->getDepthRaw().type() == CV_8UC1)
{
cv::Mat leftMono;
if(data->getImageRaw().channels() == 3)
{
cv::cvtColor(data->getImageRaw(), leftMono, CV_BGR2GRAY);
}
else
{
leftMono = data->getImageRaw();
}
UTimer timer;
// generate kpts
std::vector<cv::KeyPoint> kpts;
cv::Rect roi = Feature2D::computeRoi(leftMono, "0.03 0.03 0.04 0.04");
ParametersMap parameters;
parameters.insert(ParametersPair(Parameters::kGFTTMaxCorners(), "1000"));
parameters.insert(ParametersPair(Parameters::kGFTTMinDistance(), "10"));
Feature2D::Type type = Feature2D::kFeatureGfttBrief;
Feature2D * kptDetector = Feature2D::create(type, parameters);
kpts = kptDetector->generateKeypoints(leftMono, 0, roi);
delete kptDetector;
float timeKpt = timer.ticks();
std::vector<cv::Point2f> leftCorners;
cv::KeyPoint::convert(kpts, leftCorners);
// Find features in the new left image
std::vector<unsigned char> status;
std::vector<float> err;
std::vector<cv::Point2f> rightCorners;
cv::calcOpticalFlowPyrLK(
leftMono,
data->getDepthRaw(),
leftCorners,
rightCorners,
status,
err,
cv::Size(21, 21), 4,
cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, 20, 0.02));
float timeFlow = timer.ticks();
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
cloud->resize(kpts.size());
float bad_point = std::numeric_limits<float>::quiet_NaN ();
UASSERT(status.size() == kpts.size());
int oi = 0;
for(unsigned int i=0; i<status.size(); ++i)
{
pcl::PointXYZ pt(bad_point, bad_point, bad_point);
if(status[i])
{
float disparity = leftCorners[i].x - rightCorners[i].x;
if(disparity > 0.0f)
{
if(fabs((leftCorners[i].y-rightCorners[i].y) / (leftCorners[i].x-rightCorners[i].x)) < 0.1)
{
pcl::PointXYZ tmpPt = util3d::projectDisparityTo3D(
leftCorners[i],
disparity,
data->getDepthCx(), data->getDepthCy(), data->getDepthFx(), data->getDepthFy());
if(pcl::isFinite(tmpPt))
{
pt = pcl::transformPoint(tmpPt, util3d::transformToEigen3f(data->getLocalTransform()));
if(fabs(pt.x) > 2 || fabs(pt.y) > 2 || fabs(pt.z) > 2)
{
status[i] = 100; //blue
}
cloud->at(oi++) = pt;
}
}
else
{
status[i] = 101; //yellow
}
}
else
{
status[i] = 102; //magenta
}
}
}
cloud->resize(oi);
UINFO("correspondences = %d/%d (%f) (time kpt=%fs flow=%fs)",
(int)cloud->size(), (int)leftCorners.size(), float(cloud->size())/float(leftCorners.size()), timeKpt, timeFlow);
ui_->stereoViewer->updateCameraPosition(Transform::getIdentity());
ui_->stereoViewer->addOrUpdateCloud("stereo", cloud);
ui_->stereoViewer->render();
std::vector<cv::KeyPoint> rightKpts;
cv::KeyPoint::convert(rightCorners, rightKpts);
std::vector<cv::DMatch> good_matches(kpts.size());
for(unsigned int i=0; i<good_matches.size(); ++i)
{
good_matches[i].trainIdx = i;
good_matches[i].queryIdx = i;
}
//
//cv::Mat imageMatches;
//cv::drawMatches( leftMono, kpts, data->getDepthRaw(), rightKpts,
// good_matches, imageMatches, cv::Scalar::all(-1), cv::Scalar::all(-1),
// std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//ui_->graphicsView_stereo->setImage(uCvMat2QImage(imageMatches));
ui_->graphicsView_stereo->scene()->clear();
ui_->graphicsView_stereo->setSceneRect(0,0,(float)leftMono.cols, (float)leftMono.rows);
ui_->graphicsView_stereo->setLinesShown(true);
ui_->graphicsView_stereo->setFeaturesShown(false);
QGraphicsPixmapItem * item1 = ui_->graphicsView_stereo->scene()->addPixmap(QPixmap::fromImage(uCvMat2QImage(data->getImageRaw())));
QGraphicsPixmapItem * item2 = ui_->graphicsView_stereo->scene()->addPixmap(QPixmap::fromImage(uCvMat2QImage(data->getDepthRaw())));
QGraphicsOpacityEffect * effect1 = new QGraphicsOpacityEffect();
QGraphicsOpacityEffect * effect2 = new QGraphicsOpacityEffect();
effect1->setOpacity(0.5);
effect2->setOpacity(0.5);
item1->setGraphicsEffect(effect1);
item2->setGraphicsEffect(effect2);
// Draw lines between corresponding features...
for(unsigned int i=0; i<kpts.size(); ++i)
{
QColor c = Qt::green;
if(status[i] == 0)
{
c = Qt::red;
}
else if(status[i] == 100)
{
c = Qt::blue;
}
else if(status[i] == 101)
{
c = Qt::yellow;
}
else if(status[i] == 102)
{
c = Qt::magenta;
}
QGraphicsLineItem * item = ui_->graphicsView_stereo->scene()->addLine(
kpts[i].pt.x,
kpts[i].pt.y,
rightKpts[i].pt.x,
rightKpts[i].pt.y,
QPen(c));
item->setZValue(1);
}
}
}
void DatabaseViewer::updateWordsMatching() void DatabaseViewer::updateWordsMatching()
{ {
int from = ids_.at(ui_->horizontalSlider_A->value()); int from = ids_.at(ui_->horizontalSlider_A->value());

View File

@@ -346,6 +346,10 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->toolButton_dictionaryPath, SIGNAL(clicked()), this, SLOT(changeDictionaryPath())); connect(_ui->toolButton_dictionaryPath, SIGNAL(clicked()), this, SLOT(changeDictionaryPath()));
_ui->checkBox_kp_newWordsComparedTogether->setObjectName(Parameters::kKpNewWordsComparedTogether().c_str()); _ui->checkBox_kp_newWordsComparedTogether->setObjectName(Parameters::kKpNewWordsComparedTogether().c_str());
_ui->subpix_winSize->setObjectName(Parameters::kKpSubPixWinSize().c_str());
_ui->subpix_iterations->setObjectName(Parameters::kKpSubPixIterations().c_str());
_ui->subpix_eps->setObjectName(Parameters::kKpSubPixEps().c_str());
//SURF detector //SURF detector
_ui->surf_doubleSpinBox_hessianThr->setObjectName(Parameters::kSURFHessianThreshold().c_str()); _ui->surf_doubleSpinBox_hessianThr->setObjectName(Parameters::kSURFHessianThreshold().c_str());
_ui->surf_spinBox_octaves->setObjectName(Parameters::kSURFOctaves().c_str()); _ui->surf_spinBox_octaves->setObjectName(Parameters::kSURFOctaves().c_str());
@@ -478,18 +482,18 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->odom_flow_maxLevel->setObjectName(Parameters::kOdomFlowMaxLevel().c_str()); _ui->odom_flow_maxLevel->setObjectName(Parameters::kOdomFlowMaxLevel().c_str());
_ui->odom_flow_iterations->setObjectName(Parameters::kOdomFlowIterations().c_str()); _ui->odom_flow_iterations->setObjectName(Parameters::kOdomFlowIterations().c_str());
_ui->odom_flow_eps->setObjectName(Parameters::kOdomFlowEps().c_str()); _ui->odom_flow_eps->setObjectName(Parameters::kOdomFlowEps().c_str());
_ui->odom_flow_subpix_winSize->setObjectName(Parameters::kOdomFlowSubPixWinSize().c_str()); _ui->odom_stereo_maxSlope->setObjectName(Parameters::kOdomStereoMaxSlope().c_str());
_ui->odom_flow_subpix_iterations->setObjectName(Parameters::kOdomFlowSubPixIterations().c_str()); _ui->odom_subpix_winSize->setObjectName(Parameters::kOdomSubPixWinSize().c_str());
_ui->odom_flow_subpix_eps->setObjectName(Parameters::kOdomFlowSubPixEps().c_str()); _ui->odom_subpix_iterations->setObjectName(Parameters::kOdomSubPixIterations().c_str());
_ui->odom_subpix_eps->setObjectName(Parameters::kOdomSubPixEps().c_str());
//Stereo //Stereo
_ui->stereo_winSize->setObjectName(Parameters::kStereoWinSize().c_str()); _ui->stereo_flow_winSize->setObjectName(Parameters::kStereoWinSize().c_str());
_ui->stereo_maxLevel->setObjectName(Parameters::kStereoMaxLevel().c_str()); _ui->stereo_flow_maxLevel->setObjectName(Parameters::kStereoMaxLevel().c_str());
_ui->stereo_iterations->setObjectName(Parameters::kStereoIterations().c_str()); _ui->stereo_flow_iterations->setObjectName(Parameters::kStereoIterations().c_str());
_ui->stereo_eps->setObjectName(Parameters::kStereoEps().c_str()); _ui->stereo_flow_eps->setObjectName(Parameters::kStereoEps().c_str());
_ui->stereo_subpix_winSize->setObjectName(Parameters::kStereoSubPixWinSize().c_str()); _ui->stereo_maxSlope->setObjectName(Parameters::kStereoMaxSlope().c_str());
_ui->stereo_subpix_iterations->setObjectName(Parameters::kStereoSubPixIterations().c_str());
_ui->stereo_subpix_eps->setObjectName(Parameters::kStereoSubPixEps().c_str());
setupSignals(); setupSignals();
// custom signals // custom signals
@@ -813,8 +817,8 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->checkBox_mls->setChecked(false); _ui->checkBox_mls->setChecked(false);
_ui->doubleSpinBox_mlsRadius->setValue(0.04); _ui->doubleSpinBox_mlsRadius->setValue(0.04);
_ui->groupBox_poseFiltering->setChecked(false); _ui->groupBox_poseFiltering->setChecked(true);
_ui->doubleSpinBox_cloudFilterRadius->setValue(0.1); _ui->doubleSpinBox_cloudFilterRadius->setValue(0.3);
_ui->doubleSpinBox_cloudFilterAngle->setValue(30); _ui->doubleSpinBox_cloudFilterAngle->setValue(30);
_ui->checkBox_map_shown->setChecked(false); _ui->checkBox_map_shown->setChecked(false);

View File

@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1187</width> <width>1187</width>
<height>711</height> <height>851</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -1011,6 +1011,24 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="dockWidget_stereoView">
<property name="windowTitle">
<string>Stereo view</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_5">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="rtabmap::ImageView" name="graphicsView_stereo"/>
</item>
<item>
<widget class="rtabmap::CloudViewer" name="stereoViewer" native="true"/>
</item>
</layout>
</widget>
</widget>
<action name="actionOpen_database"> <action name="actionOpen_database">
<property name="text"> <property name="text">
<string>Open database</string> <string>Open database</string>
@@ -1103,17 +1121,17 @@
</action> </action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>rtabmap::ImageView</class>
<extends>QGraphicsView</extends>
<header>rtabmap/gui/ImageView.h</header>
</customwidget>
<customwidget> <customwidget>
<class>rtabmap::CloudViewer</class> <class>rtabmap::CloudViewer</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>rtabmap/gui/CloudViewer.h</header> <header>rtabmap/gui/CloudViewer.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>rtabmap::ImageView</class>
<extends>QGraphicsView</extends>
<header>rtabmap/gui/ImageView.h</header>
</customwidget>
<customwidget> <customwidget>
<class>rtabmap::GraphViewer</class> <class>rtabmap::GraphViewer</class>
<extends>QGraphicsView</extends> <extends>QGraphicsView</extends>

File diff suppressed because it is too large Load Diff