38 #include <opencv2/core/core.hpp>
43 #define GENERATED_GT_NAME "GroundTruth_generated.bmp"
48 "rtabmap-console [options] \"path\"\n"
49 " path For images, use the directory path. For videos or databases, use full\n "
52 " -quiet Don't show log for every images.\n"
53 " -rate #.## Acquisition time (seconds)\n"
54 " -rateHz #.## Acquisition rate (Hz), for convenience\n"
55 " -repeat # Repeat the process on the data set # times (minimum of 1)\n"
56 " -createGT Generate a ground truth file\n"
57 " -gt \"path\" Compute precision/recall with ground truth matrix.\n"
58 " -start_at # When \"path\" is a directory of images, set this parameter\n"
59 " to start processing at image # (default 0).\n"
60 " -skip # Skip X images while reading directory (default 0).\n"
61 " -v Get version of RTAB-Map\n"
62 " -input \"path\" Load previous database if it exists.\n"
64 "Example (generating LogI.txt and LogF.txt for rtabmap/archive/2010-LoopClosure/ShowLogs script, and with 2013 paper parameters):\n\n"
65 " $ rtabmap-console \\\n"
66 " --Rtabmap/StatisticLogged true\\\n"
67 " --Rtabmap/StatisticLoggedHeaders false\\\n"
68 " --Kp/DetectorStrategy 0\\\n"
69 " --SURF/HessianThreshold 150\\\n"
70 " --Rtabmap/MemoryThr 300\\\n"
71 " --Rtabmap/LoopRatio 0.9\\\n"
72 " --Mem/STMSize 30\\\n"
73 " --Vis/MaxFeatures 400\\\n"
74 " --Kp/TfIdfLikelihoodUsed false\\\n"
75 " --Kp/MaxFeatures 400\\\n"
76 " --Kp/BadSignRatio 0.25\\\n"
77 " --Mem/BadSignaturesIgnored true\\\n"
78 " --Mem/RehearsalSimilarity 0.20\\\n"
79 " --Mem/RecentWmRatio 0.20\\\n"
80 " -gt \"~/Downloads/UdeS_1Hz.png\"\\\n"
89 printf(
"\nSignal %d caught...\n", sig);
109 else if(argc == 2 && strcmp(
argv[1],
"-v") == 0)
120 bool createGT =
false;
121 std::string inputDbPath;
127 for(
int i=1;
i<argc; ++
i)
135 printf(
"Path not valid : %s\n",
path.c_str());
141 if(strcmp(
argv[
i],
"-rate") == 0)
158 if(strcmp(
argv[
i],
"-rateHz") == 0)
179 if(strcmp(
argv[
i],
"-repeat") == 0)
196 if(strcmp(
argv[
i],
"-start_at") == 0)
201 startAt = std::atoi(
argv[
i]);
213 if (strcmp(
argv[
i],
"-skip") == 0)
218 skip = std::atoi(
argv[
i]);
230 if(strcmp(
argv[
i],
"-quiet") == 0)
235 if(strcmp(
argv[
i],
"-createGT") == 0)
240 if(strcmp(
argv[
i],
"-gt") == 0)
253 if(strcmp(
argv[
i],
"-input") == 0)
258 inputDbPath =
argv[
i];
266 if(strcmp(
argv[
i],
"-help") == 0 || strcmp(
argv[
i],
"--help") == 0)
274 printf(
"Cannot create a Ground truth if repeat is on.\n");
280 std::queue<double> iterationMeanTime;
296 printf(
"Camera init failed, using path \"%s\"\n",
path.c_str());
303 std::map<int, int> generatedGroundTruth;
307 if(inputDbPath.empty())
309 inputDbPath =
"rtabmapconsole.db";
312 printf(
"Deleted database \"%s\".\n", inputDbPath.c_str());
317 printf(
"Loading database \"%s\".\n", inputDbPath.c_str());
326 cv::Mat tmp = cv::Mat::zeros(640,480,CV_8UC1);
339 printf(
"rtabmap init time = %fs\n",
timer.ticks());
344 int countLoopDetected=0;
345 printf(
"\nParameters : \n");
346 printf(
" Data set : %s\n",
path.c_str());
347 printf(
" Time threshold = %1.2f ms\n",
rtabmap.getTimeThreshold());
348 printf(
" Memory threshold = %d nodes\n",
rtabmap.getMemoryThreshold());
349 printf(
" Image rate = %1.2f s (%1.2f Hz)\n", rate, 1/rate);
350 printf(
" Repeating data set = %s\n",
repeat?
"true":
"false");
351 printf(
" Camera starts at image %d (default 0)\n", startAt);
352 printf(
" Skip image = %d\n", skip);
356 if(startAt != 0 ||
repeat || skip>0)
358 printf(
" Cannot input ground truth if startAt,repeat,skip options are used.\n");
361 inputGT = cv::imread(gtPath, cv::IMREAD_GRAYSCALE);
362 printf(
" Input ground truth : %s (%dx%d)\n", gtPath.c_str(), inputGT.cols, inputGT.rows);
363 UASSERT(inputGT.cols == inputGT.rows);
364 UASSERT(totalImages == 0 || totalImages == inputGT.cols);
368 printf(
" Creating the ground truth matrix.\n");
370 printf(
" INFO: All other parameters are set to defaults\n");
373 printf(
" Overwritten parameters :\n");
376 printf(
" %s=%s\n",
iter->first.c_str(),
iter->second.c_str());
381 printf(
"[Warning] RTAB-Map database is not empty (%s)\n", inputDbPath.c_str());
383 printf(
"\nProcessing images...\n");
387 int imagesProcessed = 0;
388 std::list<std::vector<float> > teleopActions;
389 std::map<float, bool> loopClosureStats;
394 double maxIterationTime = 0.0;
395 int maxIterationTimeId = 0;
399 iterationTimer.
start();
400 rtabmapTimer.
start();
402 double rtabmapTime = rtabmapTimer.
elapsed();
403 loopClosureId =
rtabmap.getLoopClosureId();
409 if(!gtPath.empty() &&
rtabmap.getHighestHypothesisValue() > 0.0f)
412 rtabmap.getHighestHypothesisId()-1 > inputGT.cols)
414 printf(
"ERROR: Incompatible ground truth file (size=%dx%d, current image index=%d, loop index=%d)!", inputGT.cols, inputGT.rows,
i,
rtabmap.getHighestHypothesisId()-1);
417 bool rejectedHypothesis =
uValue(
rtabmap.getStatistics().data(), Statistics::kLoopRejectedHypothesis(), 0.0f) != 0.0f;
418 unsigned char gtValue = inputGT.at<
unsigned char>(
i,
rtabmap.getHighestHypothesisId()-1);
419 if((gtValue==0 || gtValue == 255) && !rejectedHypothesis)
421 loopClosureStats.insert(std::make_pair(
rtabmap.getHighestHypothesisValue(), gtValue==255));
425 for(
int j=0;
j<=skip; ++
j)
429 if(!quiet && ++
count % 100 == 0)
431 printf(
" count = %d, loop closures = %d, max time (at %d) = %fs\n",
432 count, countLoopDetected, maxIterationTimeId, maxIterationTime);
433 maxIterationTime = 0.0;
434 maxIterationTimeId = 0;
435 std::map<int, int> wm =
rtabmap.getWeights();
436 printf(
" WM(%d)=[", (
int)wm.size());
437 for(std::map<int, int>::iterator
iter=wm.begin();
iter!=wm.end();++
iter)
439 if(
iter != wm.begin())
443 printf(
"%d,%d",
iter->first,
iter->second);
451 if(loopClosureId > 0)
453 generatedGroundTruth.insert(std::make_pair(
i, loopClosureId-1));
459 double iterationTime = iterationTimer.
ticks();
461 if(rtabmapTime > maxIterationTime)
463 maxIterationTime = rtabmapTime;
464 maxIterationTimeId =
count;
473 printf(
" iteration(%d) loop(%d) hyp(%.2f) time=%fs/%fs *\n",
474 count,
rtabmap.getLoopClosureId(),
rtabmap.getLoopClosureValue(), rtabmapTime, iterationTime);
476 else if(
rtabmap.getHighestHypothesisId())
478 printf(
" iteration(%d) high(%d) hyp(%.2f) time=%fs/%fs\n",
479 count,
rtabmap.getHighestHypothesisId(),
rtabmap.getHighestHypothesisValue(), rtabmapTime, iterationTime);
483 printf(
" iteration(%d) time=%fs/%fs\n",
count, rtabmapTime, iterationTime);
486 if(
rtabmap.getTimeThreshold() && rtabmapTime >
rtabmap.getTimeThreshold()*100.0f)
488 printf(
" ERROR, there is problem, too much time taken... %fs", rtabmapTime);
492 else if(totalImages>0 &&
i % (totalImages/10) == 0)
502 printf(
" Beginning loop %d...\n", loopDataset);
505 printf(
"Processing images completed. Loop closures found = %d\n", countLoopDetected);
506 printf(
" Total time = %fs\n",
timer.ticks());
508 if(!loopClosureStats.empty())
510 int totalGoodLoopClosures = 0;
511 float loopThr = 0.0f;
512 for(std::map<float, bool>::reverse_iterator
iter=loopClosureStats.rbegin();
iter!=loopClosureStats.rend(); ++
iter)
518 loopThr =
iter->first;
519 ++totalGoodLoopClosures;
521 int totalGtLoopClosures = 0;
522 for(
int i=0;
i<inputGT.rows; ++
i)
524 for(
int j=0;
j<inputGT.cols; ++
j)
526 if(inputGT.at<
unsigned char>(
i,
j) == 255)
528 ++totalGtLoopClosures;
534 printf(
" Recall (100%% Precision): %.2f%% (with %s=%f, accepted=%d/%d)\n",
535 float(totalGoodLoopClosures)/
float(totalGtLoopClosures)*100.0
f,
536 Parameters::kRtabmapLoopThr().
c_str(),
538 totalGoodLoopClosures,
539 totalGtLoopClosures);
542 if(imagesProcessed && createGT)
544 cv::Mat generatedGroundTruthMat = cv::Mat::zeros(imagesProcessed, imagesProcessed, CV_8U);
546 for(std::map<int, int>::iterator
iter = generatedGroundTruth.begin();
iter!=generatedGroundTruth.end(); ++
iter)
548 generatedGroundTruthMat.at<
unsigned char>(
iter->first,
iter->second) = 255;
552 printf(
"Generate ground truth to file %s, size of %d\n",
GENERATED_GT_NAME, generatedGroundTruthMat.rows);
554 printf(
" Creating ground truth file = %fs\n",
timer.ticks());
565 printf(
" Cleanup time = %fs\n",
timer.ticks());
567 printf(
"Database (\"%s\") and log files saved to current directory.\n", inputDbPath.c_str());