If OpenCV nonfree module is not found, RTAB-Map will still build but with disabled SURF/SIFT options. Default BOW dictionary will be ORB in this case.

git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@2071 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
matlabbe
2014-11-21 23:37:23 +00:00
parent 08d0bc4ad5
commit 374ef280f2
10 changed files with 223 additions and 32 deletions

View File

@@ -28,8 +28,6 @@ SET(PROJECT_VERSION_PATCH ${RTABMAP_PATCH_VERSION})
SET(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") SET(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/corelib/include/${PROJECT_PREFIX}/core/Version.h)
####### COMPILATION PARAMS ####### ####### COMPILATION PARAMS #######
# In case of Makefiles if the user does not setup CMAKE_BUILD_TYPE, assume it's Release: # In case of Makefiles if the user does not setup CMAKE_BUILD_TYPE, assume it's Release:
IF(${CMAKE_GENERATOR} MATCHES ".*Makefiles") IF(${CMAKE_GENERATOR} MATCHES ".*Makefiles")
@@ -132,7 +130,13 @@ IF(APPLE)
ENDIF(APPLE) ENDIF(APPLE)
####### DEPENDENCIES ####### ####### DEPENDENCIES #######
FIND_PACKAGE(OpenCV REQUIRED core highgui flann features2d calib3d imgproc nonfree gpu) FIND_PACKAGE(OpenCV REQUIRED)
IF(OPENCV_NONFREE_FOUND)
ADD_DEFINITIONS(-DWITH_NONFREE)
SET(NONFREE 1)
ELSE()
SET(NONFREE 0)
ENDIF()
FIND_PACKAGE(PCL 1.7 REQUIRED) FIND_PACKAGE(PCL 1.7 REQUIRED)
FIND_PACKAGE(VTK REQUIRED) FIND_PACKAGE(VTK REQUIRED)
IF("${VTK_MAJOR_VERSION}" EQUAL 5) IF("${VTK_MAJOR_VERSION}" EQUAL 5)
@@ -174,6 +178,8 @@ ENDIF(APPLE AND BUILD_AS_BUNDLE)
####### SOURCES (Projects) ####### ####### SOURCES (Projects) #######
CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/corelib/include/${PROJECT_PREFIX}/core/Version.h)
ADD_SUBDIRECTORY( utilite ) ADD_SUBDIRECTORY( utilite )
ADD_SUBDIRECTORY( corelib ) ADD_SUBDIRECTORY( corelib )
@@ -321,6 +327,12 @@ IF(APPLE)
MESSAGE(STATUS " BUILD_AS_BUNDLE = ${BUILD_AS_BUNDLE}") MESSAGE(STATUS " BUILD_AS_BUNDLE = ${BUILD_AS_BUNDLE}")
ENDIF(APPLE) ENDIF(APPLE)
IF(OPENCV_NONFREE_FOUND)
MESSAGE(STATUS " With OpenCV nonfree module (SIFT/SURF) = YES")
ELSE()
MESSAGE(STATUS " With OpenCV nonfree module (SIFT/SURF) = NO (not found)")
ENDIF()
IF(Freenect_FOUND) IF(Freenect_FOUND)
MESSAGE(STATUS " With Freenect = YES") MESSAGE(STATUS " With Freenect = YES")
ELSE() ELSE()

View File

@@ -37,5 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define RTABMAP_VERSION_COMPARE(major, minor, patch) (major>=@PROJECT_VERSION_MAJOR@ || (major==@PROJECT_VERSION_MAJOR@ && minor>=@PROJECT_VERSION_MINOR@) || (major==@PROJECT_VERSION_MAJOR@ && minor==@PROJECT_VERSION_MINOR@ && patch >=@PROJECT_VERSION_PATCH@)) #define RTABMAP_VERSION_COMPARE(major, minor, patch) (major>=@PROJECT_VERSION_MAJOR@ || (major==@PROJECT_VERSION_MAJOR@ && minor>=@PROJECT_VERSION_MINOR@) || (major==@PROJECT_VERSION_MAJOR@ && minor==@PROJECT_VERSION_MINOR@ && patch >=@PROJECT_VERSION_PATCH@))
#define RTABMAP_NONFREE @NONFREE@
#endif /* VERSION_H_ */ #endif /* VERSION_H_ */

View File

@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// default parameters // default parameters
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines #include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
#include "rtabmap/core/Version.h" // DLL export/import defines
#include <string> #include <string>
#include <map> #include <map>
@@ -102,6 +103,37 @@ typedef std::pair<std::string, std::string> ParametersPair;
Dummy##PREFIX##NAME dummy##PREFIX##NAME; Dummy##PREFIX##NAME dummy##PREFIX##NAME;
// end define PARAM // end define PARAM
/**
* Macro used to create parameter's key and default value.
* This macro must be used only in the Parameters class definition (in this file).
* They are automatically added to the default parameters map of the class Parameters.
* Example:
* @code
* //for PARAM(Video, ImageWidth, int, 640), the output will be :
* public:
* static std::string kVideoImageWidth() {return std::string("Video/ImageWidth");}
* static int defaultVideoImageWidth() {return 640;}
* private:
* class DummyVideoImageWidth {
* public:
* DummyVideoImageWidth() {parameters_.insert(ParametersPair("Video/ImageWidth", "640"));}
* };
* DummyVideoImageWidth dummyVideoImageWidth;
* @endcode
*/
#define RTABMAP_PARAM_COND(PREFIX, NAME, TYPE, COND, DEFAULT_VALUE1, DEFAULT_VALUE2, DESCRIPTION) \
public: \
static std::string k##PREFIX##NAME() {return std::string(#PREFIX "/" #NAME);} \
static TYPE default##PREFIX##NAME() {return COND?DEFAULT_VALUE1:DEFAULT_VALUE2;} \
private: \
class Dummy##PREFIX##NAME { \
public: \
Dummy##PREFIX##NAME() {parameters_.insert(ParametersPair(#PREFIX "/" #NAME, COND?#DEFAULT_VALUE1:#DEFAULT_VALUE2)); \
descriptions_.insert(ParametersPair(#PREFIX "/" #NAME, DESCRIPTION));} \
}; \
Dummy##PREFIX##NAME dummy##PREFIX##NAME;
// end define PARAM
/** /**
* Class Parameters. * Class Parameters.
* This class is used to manage all custom parameters * This class is used to manage all custom parameters
@@ -162,13 +194,13 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Mem, InitWMWithAllNodes, bool, false, "Initialize the Working Memory with all nodes in Long-Term Memory. When false, it is initialized with nodes of the previous session.") RTABMAP_PARAM(Mem, InitWMWithAllNodes, bool, false, "Initialize the Working Memory with all nodes in Long-Term Memory. When false, it is initialized with nodes of the previous session.")
// KeypointMemory (Keypoint-based) // KeypointMemory (Keypoint-based)
RTABMAP_PARAM(Kp, NNStrategy, int, 1, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4"); 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, IncrementalDictionary, bool, true, "");
RTABMAP_PARAM(Kp, MaxDepth, float, 0.0, "Filter extracted keypoints by depth (0=inf)"); RTABMAP_PARAM(Kp, MaxDepth, float, 0.0, "Filter extracted keypoints by depth (0=inf)");
RTABMAP_PARAM(Kp, WordsPerImage, int, 400, ""); RTABMAP_PARAM(Kp, WordsPerImage, int, 400, "");
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.2, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad)."); RTABMAP_PARAM(Kp, BadSignRatio, float, 0.2, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad).");
RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)"); RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)");
RTABMAP_PARAM(Kp, DetectorStrategy, int, 0, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK."); RTABMAP_PARAM_COND(Kp, DetectorStrategy, int, RTABMAP_NONFREE, 0, 2, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK.");
RTABMAP_PARAM(Kp, TfIdfLikelihoodUsed, bool, true, "Use of the td-idf strategy to compute the likelihood."); RTABMAP_PARAM(Kp, TfIdfLikelihoodUsed, bool, true, "Use of the td-idf strategy to compute the likelihood.");
RTABMAP_PARAM(Kp, Parallelized, bool, true, "If the dictionary update and signature creation were parallelized."); RTABMAP_PARAM(Kp, Parallelized, bool, true, "If the dictionary update and signature creation were parallelized.");
RTABMAP_PARAM_STR(Kp, RoiRatios, "0.0 0.0 0.0 0.0", "Region of interest ratios [left, right, top, bottom]."); RTABMAP_PARAM_STR(Kp, RoiRatios, "0.0 0.0 0.0 0.0", "Region of interest ratios [left, right, top, bottom].");
@@ -210,14 +242,14 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(GFTT, MaxCorners, int, 400, ""); RTABMAP_PARAM(GFTT, MaxCorners, int, 400, "");
RTABMAP_PARAM(GFTT, QualityLevel, double, 0.01, ""); RTABMAP_PARAM(GFTT, QualityLevel, double, 0.01, "");
RTABMAP_PARAM(GFTT, MinDistance, double, 1, ""); RTABMAP_PARAM(GFTT, MinDistance, double, 5, "");
RTABMAP_PARAM(GFTT, BlockSize, int, 3, ""); RTABMAP_PARAM(GFTT, BlockSize, int, 3, "");
RTABMAP_PARAM(GFTT, UseHarrisDetector, bool, false, ""); RTABMAP_PARAM(GFTT, UseHarrisDetector, bool, false, "");
RTABMAP_PARAM(GFTT, K, double, 0.04, ""); RTABMAP_PARAM(GFTT, K, double, 0.04, "");
RTABMAP_PARAM(ORB, NFeatures, int, 500, "The maximum number of features to retain."); RTABMAP_PARAM(ORB, NFeatures, int, 400, "The maximum number of features to retain.");
RTABMAP_PARAM(ORB, ScaleFactor, float, 1.2, "Pyramid decimation ratio, greater than 1. scaleFactor==2 means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer."); RTABMAP_PARAM(ORB, ScaleFactor, float, 1.2, "Pyramid decimation ratio, greater than 1. scaleFactor==2 means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer.");
RTABMAP_PARAM(ORB, NLevels, int, 8, "The number of pyramid levels. The smallest level will have linear size equal to input_image_linear_size/pow(scaleFactor, nlevels)."); RTABMAP_PARAM(ORB, NLevels, int, 1, "The number of pyramid levels. The smallest level will have linear size equal to input_image_linear_size/pow(scaleFactor, nlevels).");
RTABMAP_PARAM(ORB, EdgeThreshold, int, 31, "This is size of the border where the features are not detected. It should roughly match the patchSize parameter."); RTABMAP_PARAM(ORB, EdgeThreshold, int, 31, "This is size of the border where the features are not detected. It should roughly match the patchSize parameter.");
RTABMAP_PARAM(ORB, FirstLevel, int, 0, "It should be 0 in the current implementation."); RTABMAP_PARAM(ORB, FirstLevel, int, 0, "It should be 0 in the current implementation.");
RTABMAP_PARAM(ORB, WTA_K, int, 2, "The number of points that produce each element of the oriented BRIEF descriptor. The default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 random points (of course, those point coordinates are random, but they are generated from the pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, denoted as NORM_HAMMING2 (2 bits per bin). When WTA_K=4, we take 4 random points to compute each bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3)."); RTABMAP_PARAM(ORB, WTA_K, int, 2, "The number of points that produce each element of the oriented BRIEF descriptor. The default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 random points (of course, those point coordinates are random, but they are generated from the pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, denoted as NORM_HAMMING2 (2 bits per bin). When WTA_K=4, we take 4 random points to compute each bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3).");
@@ -300,7 +332,7 @@ class RTABMAP_EXP Parameters
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, 4.0, "Max depth of the words (0 means no limit)."); RTABMAP_PARAM(LccBow, MaxDepth, float, 4.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(LccBow, Force2D, bool, false, "Force 2D transform (3Dof: x,y and yaw).");
RTABMAP_PARAM(LccReextract, Activated, bool, false, "Activate re-extracting features on global loop closure."); RTABMAP_PARAM_COND(LccReextract, Activated, bool, RTABMAP_NONFREE, false, true, "Activate re-extracting features on global loop closure.");
RTABMAP_PARAM(LccReextract, NNType, int, 3, "kNNFlannNaive=0, kNNFlannKdTree=1, kNNFlannLSH=2, kNNBruteForce=3, kNNBruteForceGPU=4."); 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, 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 7=BRISK."); RTABMAP_PARAM(LccReextract, FeatureType, int, 4, "0=SURF 1=SIFT 2=ORB 3=FAST/FREAK 4=FAST/BRIEF 5=GFTT/FREAK 6=GFTT/BRIEF 7=BRISK.");

View File

@@ -196,7 +196,7 @@ cv::Mat CameraImages::captureImage()
{ {
ULOGGER_DEBUG("Loading image : %s", fullPath.c_str()); ULOGGER_DEBUG("Loading image : %s", fullPath.c_str());
#if CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4 #if CV_MAJOR_VERSION >2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
img = cv::imread(fullPath.c_str(), cv::IMREAD_UNCHANGED); img = cv::imread(fullPath.c_str(), cv::IMREAD_UNCHANGED);
#else #else
img = cv::imread(fullPath.c_str(), -1); img = cv::imread(fullPath.c_str(), -1);

View File

@@ -37,12 +37,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <opencv2/gpu/gpu.hpp> #include <opencv2/gpu/gpu.hpp>
#include <opencv2/core/version.hpp> #include <opencv2/core/version.hpp>
#if CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4 #ifdef WITH_NONFREE
#if CV_MAJOR_VERSION > 2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
#include <opencv2/nonfree/gpu.hpp> #include <opencv2/nonfree/gpu.hpp>
#include <opencv2/nonfree/features2d.hpp> #include <opencv2/nonfree/features2d.hpp>
#endif #endif
#endif
#define OPENCV_SURF_GPU CV_MAJOR_VERSION >= 2 and CV_MINOR_VERSION >=2 and CV_SUBMINOR_VERSION>=1
namespace rtabmap { namespace rtabmap {
@@ -321,21 +321,30 @@ cv::Rect Feature2D::computeRoi(const cv::Mat & image, const std::vector<float> &
///////////////////// /////////////////////
Feature2D * Feature2D::create(Feature2D::Type & type, const ParametersMap & parameters) Feature2D * Feature2D::create(Feature2D::Type & type, const ParametersMap & parameters)
{ {
if(RTABMAP_NONFREE == 0 &&
(type == Feature2D::kFeatureSurf || type == Feature2D::kFeatureSift))
{
UERROR("SURF/SIFT features cannot be used because OpenCV was not built with nonfree module. ORB is used instead.");
type = Feature2D::kFeatureOrb;
}
Feature2D * feature2D = 0; Feature2D * feature2D = 0;
switch(type) switch(type)
{ {
case Feature2D::kFeatureSurf:
feature2D = new SURF(parameters);
break;
case Feature2D::kFeatureSift: case Feature2D::kFeatureSift:
feature2D = new SIFT(parameters); feature2D = new SIFT(parameters);
break; break;
case Feature2D::kFeatureOrb:
feature2D = new ORB(parameters);
break;
case Feature2D::kFeatureFastBrief: case Feature2D::kFeatureFastBrief:
feature2D = new FAST_BRIEF(parameters); feature2D = new FAST_BRIEF(parameters);
break; break;
case Feature2D::kFeatureFastFreak: case Feature2D::kFeatureFastFreak:
feature2D = new FAST_FREAK(parameters); feature2D = new FAST_FREAK(parameters);
break; break;
case Feature2D::kFeatureOrb:
feature2D = new ORB(parameters);
break;
case Feature2D::kFeatureGfttFreak: case Feature2D::kFeatureGfttFreak:
feature2D = new GFTT_FREAK(parameters); feature2D = new GFTT_FREAK(parameters);
break; break;
@@ -345,11 +354,18 @@ Feature2D * Feature2D::create(Feature2D::Type & type, const ParametersMap & para
case Feature2D::kFeatureBrisk: case Feature2D::kFeatureBrisk:
feature2D = new BRISK(parameters); feature2D = new BRISK(parameters);
break; break;
case Feature2D::kFeatureSurf: #ifdef WITH_NONFREE
default: default:
feature2D = new SURF(parameters); feature2D = new SURF(parameters);
type = Feature2D::kFeatureSurf; type = Feature2D::kFeatureSurf;
break; break;
#else
default:
feature2D = new ORB(parameters);
type = Feature2D::kFeatureOrb;
break;
#endif
} }
return feature2D; return feature2D;
} }
@@ -417,6 +433,7 @@ SURF::SURF(const ParametersMap & parameters) :
SURF::~SURF() SURF::~SURF()
{ {
#ifdef WITH_NONFREE
if(_surf) if(_surf)
{ {
delete _surf; delete _surf;
@@ -425,6 +442,7 @@ SURF::~SURF()
{ {
delete _gpuSurf; delete _gpuSurf;
} }
#endif
} }
void SURF::parseParameters(const ParametersMap & parameters) void SURF::parseParameters(const ParametersMap & parameters)
@@ -437,6 +455,7 @@ void SURF::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kSURFGpuKeypointsRatio(), gpuKeypointsRatio_); Parameters::parse(parameters, Parameters::kSURFGpuKeypointsRatio(), gpuKeypointsRatio_);
Parameters::parse(parameters, Parameters::kSURFGpuVersion(), gpuVersion_); Parameters::parse(parameters, Parameters::kSURFGpuVersion(), gpuVersion_);
#ifdef WITH_NONFREE
if(_gpuSurf) if(_gpuSurf)
{ {
delete _gpuSurf; delete _gpuSurf;
@@ -461,12 +480,17 @@ void SURF::parseParameters(const ParametersMap & parameters)
_surf = new cv::SURF(hessianThreshold_, nOctaves_, nOctaveLayers_, extended_, upright_); _surf = new cv::SURF(hessianThreshold_, nOctaves_, nOctaveLayers_, extended_, upright_);
} }
#else
UERROR("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
#endif
} }
std::vector<cv::KeyPoint> SURF::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const std::vector<cv::KeyPoint> SURF::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
{ {
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U); UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
std::vector<cv::KeyPoint> keypoints; std::vector<cv::KeyPoint> keypoints;
#ifdef WITH_NONFREE
cv::Mat imgRoi(image, roi); cv::Mat imgRoi(image, roi);
if(_gpuSurf) if(_gpuSurf)
{ {
@@ -477,7 +501,9 @@ std::vector<cv::KeyPoint> SURF::generateKeypointsImpl(const cv::Mat & image, con
{ {
_surf->detect(imgRoi, keypoints); _surf->detect(imgRoi, keypoints);
} }
#else
UERROR("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
#endif
return keypoints; return keypoints;
} }
@@ -485,6 +511,7 @@ cv::Mat SURF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::Key
{ {
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U); UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
cv::Mat descriptors; cv::Mat descriptors;
#ifdef WITH_NONFREE
if(_gpuSurf) if(_gpuSurf)
{ {
cv::gpu::GpuMat imgGpu(image); cv::gpu::GpuMat imgGpu(image);
@@ -505,6 +532,9 @@ cv::Mat SURF::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::Key
{ {
_surf->compute(image, keypoints, descriptors); _surf->compute(image, keypoints, descriptors);
} }
#else
UERROR("RTAB-Map is not built with OpenCV nonfree module so SURF cannot be used!");
#endif
return descriptors; return descriptors;
} }
@@ -525,10 +555,14 @@ SIFT::SIFT(const ParametersMap & parameters) :
SIFT::~SIFT() SIFT::~SIFT()
{ {
#ifdef WITH_NONFREE
if(_sift) if(_sift)
{ {
delete _sift; delete _sift;
} }
#else
UERROR("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
#endif
} }
void SIFT::parseParameters(const ParametersMap & parameters) void SIFT::parseParameters(const ParametersMap & parameters)
@@ -539,6 +573,7 @@ void SIFT::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kSIFTNOctaveLayers(), nOctaveLayers_); Parameters::parse(parameters, Parameters::kSIFTNOctaveLayers(), nOctaveLayers_);
Parameters::parse(parameters, Parameters::kSIFTSigma(), sigma_); Parameters::parse(parameters, Parameters::kSIFTSigma(), sigma_);
#ifdef WITH_NONFREE
if(_sift) if(_sift)
{ {
delete _sift; delete _sift;
@@ -546,14 +581,21 @@ void SIFT::parseParameters(const ParametersMap & parameters)
} }
_sift = new cv::SIFT(nfeatures_, nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_); _sift = new cv::SIFT(nfeatures_, nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_);
#else
UERROR("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
#endif
} }
std::vector<cv::KeyPoint> SIFT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const std::vector<cv::KeyPoint> SIFT::generateKeypointsImpl(const cv::Mat & image, const cv::Rect & roi) const
{ {
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U); UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
std::vector<cv::KeyPoint> keypoints; std::vector<cv::KeyPoint> keypoints;
#ifdef WITH_NONFREE
cv::Mat imgRoi(image, roi); cv::Mat imgRoi(image, roi);
_sift->detect(imgRoi, keypoints); // Opencv keypoints _sift->detect(imgRoi, keypoints); // Opencv keypoints
#else
UERROR("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
#endif
return keypoints; return keypoints;
} }
@@ -561,7 +603,11 @@ cv::Mat SIFT::generateDescriptorsImpl(const cv::Mat & image, std::vector<cv::Key
{ {
UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U); UASSERT(!image.empty() && image.channels() == 1 && image.depth() == CV_8U);
cv::Mat descriptors; cv::Mat descriptors;
#ifdef WITH_NONFREE
_sift->compute(image, keypoints, descriptors); _sift->compute(image, keypoints, descriptors);
#else
UERROR("RTAB-Map is not built with OpenCV nonfree module so SIFT cannot be used!");
#endif
return descriptors; return descriptors;
} }

View File

@@ -73,8 +73,7 @@ Memory::Memory(const ParametersMap & parameters) :
_signaturesAdded(0), _signaturesAdded(0),
_postInitClosingEvents(false), _postInitClosingEvents(false),
_feature2D(new SURF(parameters)), _featureType((Feature2D::Type)Parameters::defaultKpDetectorStrategy()),
_featureType(Feature2D::kFeatureSurf),
_badSignRatio(Parameters::defaultKpBadSignRatio()), _badSignRatio(Parameters::defaultKpBadSignRatio()),
_tfIdfLikelihoodUsed(Parameters::defaultKpTfIdfLikelihoodUsed()), _tfIdfLikelihoodUsed(Parameters::defaultKpTfIdfLikelihoodUsed()),
_parallelized(Parameters::defaultKpParallelized()), _parallelized(Parameters::defaultKpParallelized()),
@@ -114,6 +113,7 @@ Memory::Memory(const ParametersMap & parameters) :
_subPixIterations(Parameters::defaultKpSubPixIterations()), _subPixIterations(Parameters::defaultKpSubPixIterations()),
_subPixEps(Parameters::defaultKpSubPixEps()) _subPixEps(Parameters::defaultKpSubPixEps())
{ {
_feature2D = Feature2D::create(_featureType, parameters);
_vwd = new VWDictionary(parameters); _vwd = new VWDictionary(parameters);
this->parseParameters(parameters); this->parseParameters(parameters);
} }

View File

@@ -41,7 +41,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pcl/ModelCoefficients.h> #include <pcl/ModelCoefficients.h>
#include <pcl/segmentation/sac_segmentation.h> #include <pcl/segmentation/sac_segmentation.h>
#ifdef WITH_NONFREE
#include <opencv2/nonfree/features2d.hpp> #include <opencv2/nonfree/features2d.hpp>
#endif
#include <opencv2/calib3d/calib3d.hpp> #include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/video/tracking.hpp> #include <opencv2/video/tracking.hpp>
#include <rtabmap/core/VWDictionary.h> #include <rtabmap/core/VWDictionary.h>
@@ -1123,7 +1125,7 @@ cv::Mat uncompressImage(const cv::Mat & bytes)
cv::Mat image; cv::Mat image;
if(!bytes.empty()) if(!bytes.empty())
{ {
#if CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED); image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
#else #else
image = cv::imdecode(bytes, -1); image = cv::imdecode(bytes, -1);
@@ -1137,7 +1139,7 @@ cv::Mat uncompressImage(const std::vector<unsigned char> & bytes)
cv::Mat image; cv::Mat image;
if(bytes.size()) if(bytes.size())
{ {
#if CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4 #if CV_MAJOR_VERSION>2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4)
image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED); image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
#else #else
image = cv::imdecode(bytes, -1); image = cv::imdecode(bytes, -1);

View File

@@ -41,9 +41,15 @@ AboutDialog::AboutDialog(QWidget * parent) :
QString version = Rtabmap::getVersion().c_str(); QString version = Rtabmap::getVersion().c_str();
#if DEMO_BUILD #if DEMO_BUILD
version.append(" [DEMO]"); version.append(" [DEMO]");
#endif
QString cv_version = CV_VERSION;
#if WITH_NONFREE
cv_version.append(" [With nonfree]");
#else
cv_version.append(" [Without nonfree]");
#endif #endif
_ui->label_version->setText(version); _ui->label_version->setText(version);
_ui->label_opencv_version->setText(CV_VERSION); _ui->label_opencv_version->setText(cv_version);
_ui->label_pcl_version->setText(PCL_VERSION_PRETTY); _ui->label_pcl_version->setText(PCL_VERSION_PRETTY);
} }

View File

@@ -113,6 +113,20 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->label_map_shown->setText(_ui->label_map_shown->text() + " (Disabled, PCL >=1.7.2 required)"); _ui->label_map_shown->setText(_ui->label_map_shown->text() + " (Disabled, PCL >=1.7.2 required)");
#endif #endif
if(RTABMAP_NONFREE == 0)
{
_ui->comboBox_detector_strategy->setItemData(0, 0, Qt::UserRole - 1);
_ui->comboBox_detector_strategy->setItemData(1, 0, Qt::UserRole - 1);
_ui->reextract_type->setItemData(0, 0, Qt::UserRole - 1);
_ui->reextract_type->setItemData(1, 0, Qt::UserRole - 1);
_ui->odom_type->setItemData(0, 0, Qt::UserRole - 1);
_ui->odom_type->setItemData(1, 0, Qt::UserRole - 1);
_ui->comboBox_dictionary_strategy->setItemData(1, 0, Qt::UserRole - 1);
_ui->reextract_nn->setItemData(1, 0, Qt::UserRole - 1);
_ui->odom_bin_nn->setItemData(1, 0, Qt::UserRole - 1);
}
_ui->predictionPlot->showLegend(false); _ui->predictionPlot->showLegend(false);
_ui->groupBox_openni2->setVisible(false); _ui->groupBox_openni2->setVisible(false);
@@ -530,6 +544,13 @@ PreferencesDialog::~PreferencesDialog() {
void PreferencesDialog::init() void PreferencesDialog::init()
{ {
//First set all default values
const ParametersMap & defaults = Parameters::getDefaultParameters();
for(ParametersMap::const_iterator iter=defaults.begin(); iter!=defaults.end(); ++iter)
{
this->setParameter(iter->first, iter->second);
}
this->readSettings(); this->readSettings();
this->writeSettings();// This will create the ini file if not exist this->writeSettings();// This will create the ini file if not exist
@@ -1452,21 +1473,50 @@ void PreferencesDialog::writeCoreSettings(const QString & filePath)
bool PreferencesDialog::validateForm() bool PreferencesDialog::validateForm()
{ {
//verify binary featrues and nearest neighbor if(RTABMAP_NONFREE == 0)
{
// verify that SURF/SIFT cannot be selected if not built with OpenCV nonfree module
// BOW dictionary type
if(_ui->comboBox_detector_strategy->currentIndex() <= 1)
{
QMessageBox::warning(this, tr("Parameter warning"),
tr("Selected feature type (SURF/SIFT) is not available. RTAB-Map is not built "
"with the nonfree module from OpenCV. ORB is set instead for the bag-of-words dictionary."));
_ui->comboBox_detector_strategy->setCurrentIndex(Feature2D::kFeatureOrb);
}
// BOW Reextract features type
if(_ui->reextract_type->currentIndex() <= 1)
{
QMessageBox::warning(this, tr("Parameter warning"),
tr("Selected feature type (SURF/SIFT) is not available. RTAB-Map is not built "
"with the nonfree module from OpenCV. Fast/Brief is set instead for the re-extraction "
"of features on loop closure."));
_ui->reextract_type->setCurrentIndex(Feature2D::kFeatureFastBrief);
}
// odom type
if(_ui->odom_type->currentIndex() <= 1)
{
QMessageBox::warning(this, tr("Parameter warning"),
tr("Selected feature type (SURF/SIFT) is not available. RTAB-Map is not built "
"with the nonfree module from OpenCV. GFTT/Brief is set instead for odometry."));
_ui->odom_type->setCurrentIndex(Feature2D::kFeatureGfttBrief);
}
}
//verify binary features and nearest neighbor
// BOW dictionary type // BOW dictionary type
if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannLSH && _ui->comboBox_detector_strategy->currentIndex() <= 1) if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannLSH && _ui->comboBox_detector_strategy->currentIndex() <= 1)
{ {
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (SURF or SIFT), parameter \"Visual word->Nearest Neighbor\" " 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.")); "cannot be LSH (used for binary descriptor). KD-tree is set instead for the bag-of-words dictionary."));
_ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNFlannKdTree); _ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNFlannKdTree);
} }
else if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->comboBox_detector_strategy->currentIndex() >1) else if(_ui->comboBox_dictionary_strategy->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->comboBox_detector_strategy->currentIndex() >1)
{ {
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (ORB, FAST, FREAK or BRIEF), parameter \"Visual word->Nearest Neighbor\" " 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.")); "cannot be KD-Tree (used for float descriptor). BruteForce matching is set instead for the bag-of-words dictionary."));
_ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNBruteForce); _ui->comboBox_dictionary_strategy->setCurrentIndex(VWDictionary::kNNBruteForce);
} }
@@ -1475,14 +1525,16 @@ bool PreferencesDialog::validateForm()
{ {
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (SURF or SIFT), parameter \"Visual word->Nearest Neighbor\" " 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.")); "cannot be LSH (used for binary descriptor). KD-tree is set instead for the re-extraction "
"of features on loop closure."));
_ui->reextract_nn->setCurrentIndex(VWDictionary::kNNFlannKdTree); _ui->reextract_nn->setCurrentIndex(VWDictionary::kNNFlannKdTree);
} }
else if(_ui->reextract_nn->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->reextract_type->currentIndex() >1) else if(_ui->reextract_nn->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->reextract_type->currentIndex() >1)
{ {
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (ORB, FAST, FREAK or BRIEF), parameter \"Visual word->Nearest Neighbor\" " 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.")); "cannot be KD-Tree (used for float descriptor). BruteForce matching is set instead for the re-extraction "
"of features on loop closure."));
_ui->reextract_nn->setCurrentIndex(VWDictionary::kNNBruteForce); _ui->reextract_nn->setCurrentIndex(VWDictionary::kNNBruteForce);
} }
@@ -1491,14 +1543,14 @@ bool PreferencesDialog::validateForm()
{ {
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (SURF or SIFT), parameter \"Odometry->Nearest Neighbor\" " tr("With the selected feature type (SURF or SIFT), parameter \"Odometry->Nearest Neighbor\" "
"cannot be LSH (used for binary descriptor). KD-tree is set instead.")); "cannot be LSH (used for binary descriptor). KD-tree is set instead for odometry."));
_ui->odom_bin_nn->setCurrentIndex(VWDictionary::kNNFlannKdTree); _ui->odom_bin_nn->setCurrentIndex(VWDictionary::kNNFlannKdTree);
} }
else if(_ui->odom_bin_nn->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->odom_type->currentIndex() >1) else if(_ui->odom_bin_nn->currentIndex() == VWDictionary::kNNFlannKdTree && _ui->odom_type->currentIndex() >1)
{ {
QMessageBox::warning(this, tr("Parameter warning"), QMessageBox::warning(this, tr("Parameter warning"),
tr("With the selected feature type (ORB, FAST, FREAK or BRIEF), parameter \"Odometry->Nearest Neighbor\" " tr("With the selected feature type (ORB, FAST, FREAK or BRIEF), parameter \"Odometry->Nearest Neighbor\" "
"cannot be KD-Tree (used for float descriptor). BruteForce matching is set instead.")); "cannot be KD-Tree (used for float descriptor). BruteForce matching is set instead for odometry."));
_ui->odom_bin_nn->setCurrentIndex(VWDictionary::kNNBruteForce); _ui->odom_bin_nn->setCurrentIndex(VWDictionary::kNNBruteForce);
} }
@@ -1892,11 +1944,48 @@ void PreferencesDialog::setParameter(const std::string & key, const std::string
} }
else if(combo) else if(combo)
{ {
combo->setCurrentIndex(QString(value.c_str()).toInt(&ok)); int valueInt = QString(value.c_str()).toInt(&ok);
if(!ok) if(!ok)
{ {
UERROR("Conversion failed from \"%s\" for parameter %s", value.c_str(), key.c_str()); UERROR("Conversion failed from \"%s\" for parameter %s", value.c_str(), key.c_str());
} }
else
{
if(RTABMAP_NONFREE == 0)
{
if(valueInt <= 1 &&
(combo->objectName().toStdString().compare(Parameters::kKpDetectorStrategy()) == 0 ||
combo->objectName().toStdString().compare(Parameters::kLccReextractFeatureType()) == 0 ||
combo->objectName().toStdString().compare(Parameters::kOdomFeatureType()) == 0))
{
UWARN("Trying to set \"%s\" to SIFT/SURF but RTAB-Map isn't built "
"with the nonfree module from OpenCV. Keeping default combo value: %s.",
combo->objectName().toStdString().c_str(),
combo->currentText().toStdString().c_str());
}
else if(valueInt==1 &&
(combo->objectName().toStdString().compare(Parameters::kKpNNStrategy()) == 0 ||
combo->objectName().toStdString().compare(Parameters::kLccReextractNNType()) == 0 ||
combo->objectName().toStdString().compare(Parameters::kOdomBowNNType()) == 0))
{
UWARN("Trying to set \"%s\" to KdTree but RTAB-Map isn't built "
"with the nonfree module from OpenCV and kdTree cannot be used "
"with binary descriptors. Keeping default combo value: %s.",
combo->objectName().toStdString().c_str(),
combo->currentText().toStdString().c_str());
}
else
{
combo->setCurrentIndex(valueInt);
}
}
else
{
combo->setCurrentIndex(valueInt);
}
}
} }
else if(check) else if(check)
{ {

View File

@@ -1,10 +1,12 @@
ADD_SUBDIRECTORY( ConsoleApp ) ADD_SUBDIRECTORY( ConsoleApp )
ADD_SUBDIRECTORY( ImagesJoiner ) ADD_SUBDIRECTORY( ImagesJoiner )
ADD_SUBDIRECTORY( VocabularyComparison )
ADD_SUBDIRECTORY( ExtractObject ) ADD_SUBDIRECTORY( ExtractObject )
ADD_SUBDIRECTORY( CameraRGBD ) ADD_SUBDIRECTORY( CameraRGBD )
IF(OPENCV_NONFREE_FOUND)
ADD_SUBDIRECTORY( VocabularyComparison )
ENDIF(OPENCV_NONFREE_FOUND)
IF(TARGET rtabmap_gui) IF(TARGET rtabmap_gui)
ADD_SUBDIRECTORY( DatabaseViewer ) ADD_SUBDIRECTORY( DatabaseViewer )