From e800662bac9d9543966ea15c5a7dff3092e92d8e Mon Sep 17 00:00:00 2001 From: matlabbe Date: Thu, 2 Jul 2020 16:29:23 -0400 Subject: [PATCH] Fixed build with OpenCV >= 3.4.11 --- CMakeLists.txt | 10 -- Version.h.in | 1 - corelib/include/rtabmap/core/Features2d.h | 6 +- corelib/src/Features2d.cpp | 8 +- guilib/src/PreferencesDialog.cpp | 6 +- tools/Report/main.cpp | 201 ++++++++++++++++++++-- 6 files changed, 192 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 359ff715f9..947501f048 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -689,16 +689,6 @@ ELSEIF(OpenCV_VERSION VERSION_GREATER "3.4.2") ENDIF(${matchres} EQUAL -1) ENDIF() -# check if version status is "-dev" (SIFT compatibility issue between 4.3.0 vs 4.3.0-dev) -FIND_FILE(OpenCV_VERSION_HPP opencv2/core/version.hpp - PATHS ${OpenCV_INCLUDE_DIRS} - NO_DEFAULT_PATH) -FILE(READ ${OpenCV_VERSION_HPP} TMPTXT) -STRING(FIND "${TMPTXT}" "-dev" matchres) -IF(${matchres} EQUAL -1) - SET(OPENCV_DEV "//") -ENDIF(${matchres} EQUAL -1) - IF(NOT G2O_FOUND) SET(G2O "//") ELSE() diff --git a/Version.h.in b/Version.h.in index 56332a5407..78994dc264 100644 --- a/Version.h.in +++ b/Version.h.in @@ -38,7 +38,6 @@ 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@)) @NONFREE@#define RTABMAP_NONFREE -@OPENCV_DEV@#define RTABMAP_OPENCV_DEV @TORO@#define RTABMAP_TORO @G2O@#define RTABMAP_G2O @G2O_CPP_CONF@#define RTABMAP_G2O_CPP11 diff --git a/corelib/include/rtabmap/core/Features2d.h b/corelib/include/rtabmap/core/Features2d.h index 0dc767a405..9731bdccae 100644 --- a/corelib/include/rtabmap/core/Features2d.h +++ b/corelib/include/rtabmap/core/Features2d.h @@ -62,7 +62,7 @@ namespace cv{ namespace xfeatures2d { class FREAK; class BriefDescriptorExtractor; -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(RTABMAP_OPENCV_DEV)))) +#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) class SIFT; #endif class SURF; @@ -73,10 +73,10 @@ class ORB; class SURF_CUDA; } } -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(RTABMAP_OPENCV_DEV)))) +#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) typedef cv::xfeatures2d::SIFT CV_SIFT; #else -typedef cv::SIFT CV_SIFT; // SIFT is back in features2d since 4.3.0-dev +typedef cv::SIFT CV_SIFT; // SIFT is back in features2d since 4.4.0 / 3.4.11 #endif typedef cv::xfeatures2d::SURF CV_SURF; typedef cv::FastFeatureDetector CV_FAST; diff --git a/corelib/src/Features2d.cpp b/corelib/src/Features2d.cpp index 3ca4316531..e4048eefbf 100644 --- a/corelib/src/Features2d.cpp +++ b/corelib/src/Features2d.cpp @@ -509,7 +509,7 @@ Feature2D * Feature2D::create(const ParametersMap & parameters) Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parameters) { -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(RTABMAP_OPENCV_DEV)))) +#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) #ifndef RTABMAP_NONFREE if(type == Feature2D::kFeatureSurf || type == Feature2D::kFeatureSift) { @@ -532,7 +532,7 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame #endif #endif -#else // >= 4.3.0-dev +#else // >= 4.4.0 >= 3.4.11 #ifndef RTABMAP_NONFREE if(type == Feature2D::kFeatureSurf) @@ -542,7 +542,7 @@ Feature2D * Feature2D::create(Feature2D::Type type, const ParametersMap & parame } #endif -#endif // 4.3.0-dev +#endif // >= 4.4.0 >= 3.4.11 #if CV_MAJOR_VERSION < 3 if(type == Feature2D::kFeatureKaze) @@ -963,7 +963,7 @@ void SIFT::parseParameters(const ParametersMap & parameters) Parameters::parse(parameters, Parameters::kSIFTSigma(), sigma_); Parameters::parse(parameters, Parameters::kSIFTRootSIFT(), rootSIFT_); -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(RTABMAP_OPENCV_DEV)))) +#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) #ifdef RTABMAP_NONFREE #if CV_MAJOR_VERSION < 3 _sift = cv::Ptr(new CV_SIFT(this->getMaxFeatures(), nOctaveLayers_, contrastThreshold_, edgeThreshold_, sigma_)); diff --git a/guilib/src/PreferencesDialog.cpp b/guilib/src/PreferencesDialog.cpp index de5324b36e..3cb7d38755 100644 --- a/guilib/src/PreferencesDialog.cpp +++ b/guilib/src/PreferencesDialog.cpp @@ -198,7 +198,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : #endif // SIFT -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(RTABMAP_OPENCV_DEV)))) +#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) #ifndef RTABMAP_NONFREE _ui->comboBox_detector_strategy->setItemData(1, 0, Qt::UserRole - 1); _ui->vis_feature_detector->setItemData(1, 0, Qt::UserRole - 1); @@ -2957,7 +2957,7 @@ void PreferencesDialog::writeCoreSettings(const QString & filePath) const bool PreferencesDialog::validateForm() { -#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(RTABMAP_OPENCV_DEV)))) +#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11))) #ifndef RTABMAP_NONFREE // verify that SURF/SIFT cannot be selected if not built with OpenCV nonfree module // BOW dictionary type @@ -2978,7 +2978,7 @@ bool PreferencesDialog::validateForm() _ui->vis_feature_detector->setCurrentIndex(Feature2D::kFeatureFastBrief); } #endif -#else //>= 4.3.0-dev +#else //>= 4.4.0 >= 3.4.11 #ifndef RTABMAP_NONFREE // verify that SURF cannot be selected if not built with OpenCV nonfree module // BOW dictionary type diff --git a/tools/Report/main.cpp b/tools/Report/main.cpp index eed943e5ff..b6e934c9f6 100644 --- a/tools/Report/main.cpp +++ b/tools/Report/main.cpp @@ -47,10 +47,8 @@ using namespace rtabmap; void showUsage() { printf("\nUsage:\n" -#ifdef WITH_QT "rtabmap-report [\"Statistic/Id\"] [options] path\n" -#else - "rtabmap-report [options] path\n" +#ifdef WITH_QT "[Not built with Qt, statistics cannot be plotted]\n" #endif " path Directory containing rtabmap databases or path of a database.\n" @@ -63,8 +61,8 @@ void showUsage() " and compute error based on the scaled path.\n" " --poses Export poses to [path]_poses.txt, ground truth to [path]_gt.txt\n" " and valid ground truth indices to [path]_indices.txt \n" + " --stats Show available statistics \"Statistic/Id\" to plot or get localization statistics (if path is a file). \n" #ifdef WITH_QT - " --stats Show available statistics to plot (if path is a file). \n" " --invert When reading many databases, put all curves from a same \n" " database in same figure, instead of all same curves from \n" " different database in same figure. When reading a single \n" @@ -72,11 +70,45 @@ void showUsage() " --ids Use IDs for x axis instead of time in the figures. \n" " --start # Start from this node ID for the figures.\n" #endif - " --report Export all statistics values in report.txt \n" + " --report Export all evaluation statistics values in report.txt \n" + " --loc # Show localization statistics for each \"Statistic/Id\" per " + " session for 1=min,2=max,4=mean,8=stddev,16=total,32=nonnull%% " + " (it is a mask, we can combine those numbers, e.g., 63 for all) \n" " --help Show usage\n\n"); exit(1); } +struct LocStats +{ + static LocStats from(const std::vector & array) + { + LocStats values; + values.mean = uMean(array); + values.stddev = std::sqrt(uVariance(array, values.mean)); + uMinMax(array, values.min, values.max); + values.total = array.size(); + values.nonNull = 0.0f; + if(!array.empty()) + { + for(size_t j=0; j statsToShow; #ifdef WITH_QT std::map figures; @@ -151,7 +184,20 @@ int main(int argc, char * argv[]) { useIds = true; } -#ifdef WITH_QT + else if(strcmp(argv[i],"--loc") == 0) + { + ++i; + if(i > > localizationMultiStats; //> > + for(size_t i=0; iresize(QSize(640,480)); @@ -200,10 +246,17 @@ int main(int argc, char * argv[]) fig->setXLabel("Time (s)"); } figures.insert(std::make_pair(figureTitle, fig)); +#endif + } + if(showLoc & 0b111111) + { + localizationMultiStats.insert(std::make_pair(figureTitle, std::map >())); } + } + if(!invertFigures) + { statsToShow.clear(); } -#endif std::string fileName; std::list paths; @@ -223,6 +276,7 @@ int main(int argc, char * argv[]) if(UFile::getExtension(currentPath).compare("db") == 0) { currentPathIsDatabase=true; + localizationMultiStats.clear(); printf("Database: %s\n", currentPath.c_str()); } else @@ -255,6 +309,7 @@ int main(int argc, char * argv[]) } } + // For all databases in currentDir while(currentPathIsDatabase || !(fileName = currentDir.getNextFileName()).empty()) { if(currentPathIsDatabase || UFile::getExtension(fileName).compare("db") == 0) @@ -327,6 +382,8 @@ int main(int argc, char * argv[]) for(std::map::iterator iter=figures.begin(); iter!=figures.end(); ++iter) { curves.insert(std::make_pair(iter->first, iter->second->addCurve(filePath.c_str()))); + if(!localizationMultiStats.empty()) + localizationMultiStats.at(iter->first).insert(std::make_pair(fileName, std::vector())); } } else @@ -351,11 +408,31 @@ int main(int argc, char * argv[]) for(size_t i=0; iaddCurve(statsToShow[i].c_str()))); + if(!localizationMultiStats.empty()) + localizationMultiStats.at(statsToShow[i]).insert(std::make_pair(fileName, std::vector())); } } } +#else + for(size_t i=0; i())); + } #endif + // Find localization sessions and adjust startId + if(!localizationMultiStats.empty() && startId ==0) + { + std::map poses = driver->loadOptimizedPoses(); + if(!poses.empty()) + { + startId = poses.rbegin()->first+1; + } + } + + std::map > localizationSessionStats; + double previousStamp = 0.0; for(std::set::iterator iter=ids.begin(); iter!=ids.end(); ++iter) { Transform p, gt; @@ -432,22 +509,63 @@ int main(int argc, char * argv[]) #ifdef WITH_QT for(std::map::iterator jter=curves.begin(); jter!=curves.end(); ++jter) { - if(uContains(stat, jter->first) && *iter >= startId) +#else + for(std::map > >::iterator jter=localizationMultiStats.begin(); + jter!=localizationMultiStats.end(); + ++jter) + { +#endif + if(*iter >= startId) { - double x = s; - if(useIds) + if(uContains(stat, jter->first)) { - x = *iter; + double y = stat.at(jter->first); +#ifdef WITH_QT + double x = s; + if(useIds) + { + x = *iter; + } + jter->second->addValue(x,y); +#endif + + if(!localizationMultiStats.empty()) + { + if(previousStamp > 0 && s - previousStamp > 10 && uContains(localizationSessionStats, jter->first)) + { + // changed session + LocStats values = LocStats::from(localizationSessionStats.at(jter->first)); + localizationMultiStats.at(jter->first).rbegin()->second.push_back(values); + localizationSessionStats.at(jter->first).clear(); + } + + if(!uContains(localizationSessionStats, jter->first)) + { + localizationSessionStats.insert(std::make_pair(jter->first, std::vector())); + } + localizationSessionStats.at(jter->first).push_back(y); + } } - double y = stat.at(jter->first); - jter->second->addValue(x,y); } } -#endif + previousStamp = s; } } } + for(std::map > >::iterator jter=localizationMultiStats.begin(); + jter!=localizationMultiStats.end(); + ++jter) + { + if(uContains(localizationSessionStats, jter->first) && + !localizationSessionStats.at(jter->first).empty()) + { + // changed session + LocStats values = LocStats::from(localizationSessionStats.at(jter->first)); + localizationMultiStats.at(jter->first).rbegin()->second.push_back(values); + } + } + std::multimap links; std::multimap allLinks; driver->getAllLinks(allLinks, true, true); @@ -823,6 +941,51 @@ int main(int argc, char * argv[]) currentPathIsDatabase = false; } + for(std::map > >::iterator iter=localizationMultiStats.begin(); + iter!=localizationMultiStats.end(); + ++iter) + { + printf("%s\n", iter->first.c_str()); + for(int k=0; k<6; ++k) + { + if(showLoc & (0x1 << k)) + { + printf(" %s:\n", + k==0?"min": + k==1?"max": + k==2?"mean": + k==3?"stddev": + k==4?"total": + "nonnull%"); + for(std::map >::iterator jter=iter->second.begin(); jter!=iter->second.end(); ++jter) + { + printf(" %s ", jter->first.c_str()); + for(size_t j=0; jsecond.size(); ++j) + { + if(k<4) + { + printf("%f ", + k==0?jter->second[j].min: + k==1?jter->second[j].max: + k==2?jter->second[j].mean: + jter->second[j].stddev); + } + else if(k==4) + { + printf("%d ",jter->second[j].total); + } + else if(k==5) + { + printf("%.2f ", (jter->second[j].nonNull*100)); + } + } + printf("\n"); + } + } + } + iter->second.clear(); + } + for(std::list::iterator iter=subDirs.begin(); iter!=subDirs.end(); ++iter) { paths.push_front(*iter);