From 195f6147ad5918a373e7e40644395b7aa2247117 Mon Sep 17 00:00:00 2001 From: matlabbe Date: Fri, 26 Apr 2019 19:20:35 -0400 Subject: [PATCH] DBViewer: added feature/line color menu option. CameraImages/DBReader: added maxFrames parameter --- corelib/include/rtabmap/core/DBReader.h | 8 +- .../rtabmap/core/camera/CameraImages.h | 3 + .../rtabmap/core/camera/CameraRGBDImages.h | 1 + .../rtabmap/core/camera/CameraStereoImages.h | 1 + corelib/src/DBReader.cpp | 22 ++- corelib/src/camera/CameraImages.cpp | 167 +++++++++--------- guilib/include/rtabmap/gui/ImageView.h | 14 ++ guilib/src/DatabaseViewer.cpp | 13 +- guilib/src/ImageView.cpp | 102 ++++++++++- guilib/src/MainWindow.cpp | 4 +- guilib/src/PreferencesDialog.cpp | 24 ++- guilib/src/ui/preferencesDialog.ui | 143 +++++++++++---- 12 files changed, 373 insertions(+), 129 deletions(-) diff --git a/corelib/include/rtabmap/core/DBReader.h b/corelib/include/rtabmap/core/DBReader.h index ede1c208..8cd563bb 100644 --- a/corelib/include/rtabmap/core/DBReader.h +++ b/corelib/include/rtabmap/core/DBReader.h @@ -51,14 +51,16 @@ public: bool ignoreGoalDelay = false, bool goalsIgnored = false, int startIndex = 0, - int cameraIndex = -1); + int cameraIndex = -1, + int maxFrames = 0); DBReader(const std::list & databasePaths, float frameRate = 0.0f, // -1 = use Database stamps, 0 = inf bool odometryIgnored = false, bool ignoreGoalDelay = false, bool goalsIgnored = false, int startIndex = 0, - int cameraIndex = -1); + int cameraIndex = -1, + int maxFrames = 0); virtual ~DBReader(); virtual bool init( @@ -81,6 +83,7 @@ private: bool _ignoreGoalDelay; bool _goalsIgnored; int _startIndex; + int _maxFrames; int _cameraIndex; DBDriver * _dbDriver; @@ -92,6 +95,7 @@ private: double _previousStamp; int _previousMapID; bool _calibrated; + int _framesPublished; }; } /* namespace rtabmap */ diff --git a/corelib/include/rtabmap/core/camera/CameraImages.h b/corelib/include/rtabmap/core/camera/CameraImages.h index bfd4dbea..11c815e4 100644 --- a/corelib/include/rtabmap/core/camera/CameraImages.h +++ b/corelib/include/rtabmap/core/camera/CameraImages.h @@ -62,6 +62,7 @@ public: void setPath(const std::string & dir) {_path=dir;} virtual void setStartIndex(int index) {_startAt = index;} // negative means last + virtual void setMaxFrames(int value) {_maxFrames = value;} void setDirRefreshed(bool enabled) {_refreshDir = enabled;} void setImagesRectified(bool enabled) {_rectifyImages = enabled;} void setBayerMode(int mode) {_bayerMode = mode;} // -1=disabled (default) 0=BayerBG, 1=BayerGB, 2=BayerRG, 3=BayerGR @@ -125,6 +126,7 @@ protected: private: std::string _path; int _startAt; + int _maxFrames; // If the list of files in the directory is refreshed // on each call of takeImage() bool _refreshDir; @@ -133,6 +135,7 @@ private: bool _isDepth; float _depthScaleFactor; int _count; + int _framesPublished; UDirectory * _dir; std::string _lastFileName; diff --git a/corelib/include/rtabmap/core/camera/CameraRGBDImages.h b/corelib/include/rtabmap/core/camera/CameraRGBDImages.h index 2274b0cf..16afaa39 100644 --- a/corelib/include/rtabmap/core/camera/CameraRGBDImages.h +++ b/corelib/include/rtabmap/core/camera/CameraRGBDImages.h @@ -52,6 +52,7 @@ public: virtual std::string getSerial() const; virtual void setStartIndex(int index) {CameraImages::setStartIndex(index);cameraDepth_.setStartIndex(index);} // negative means last + virtual void setMaxFrames(int value) {CameraImages::setMaxFrames(value);cameraDepth_.setMaxFrames(value);} protected: virtual SensorData captureImage(CameraInfo * info = 0); diff --git a/corelib/include/rtabmap/core/camera/CameraStereoImages.h b/corelib/include/rtabmap/core/camera/CameraStereoImages.h index 438aba0e..a71b7595 100644 --- a/corelib/include/rtabmap/core/camera/CameraStereoImages.h +++ b/corelib/include/rtabmap/core/camera/CameraStereoImages.h @@ -62,6 +62,7 @@ public: virtual std::string getSerial() const; virtual void setStartIndex(int index) {CameraImages::setStartIndex(index);camera2_->setStartIndex(index);} // negative means last + virtual void setMaxFrames(int value) {CameraImages::setMaxFrames(value);camera2_->setMaxFrames(value);} protected: virtual SensorData captureImage(CameraInfo * info = 0); diff --git a/corelib/src/DBReader.cpp b/corelib/src/DBReader.cpp index 2e9d7ef6..78c18eee 100644 --- a/corelib/src/DBReader.cpp +++ b/corelib/src/DBReader.cpp @@ -48,20 +48,23 @@ DBReader::DBReader(const std::string & databasePath, bool ignoreGoalDelay, bool goalsIgnored, int startIndex, - int cameraIndex) : + int cameraIndex, + int maxFrames) : Camera(frameRate), _paths(uSplit(databasePath, ';')), _odometryIgnored(odometryIgnored), _ignoreGoalDelay(ignoreGoalDelay), _goalsIgnored(goalsIgnored), _startIndex(startIndex), + _maxFrames(maxFrames), _cameraIndex(cameraIndex), _dbDriver(0), _currentId(_ids.end()), _previousMapId(-1), _previousStamp(0), _previousMapID(0), - _calibrated(false) + _calibrated(false), + _framesPublished(0) { } @@ -71,20 +74,23 @@ DBReader::DBReader(const std::list & databasePaths, bool ignoreGoalDelay, bool goalsIgnored, int startIndex, - int cameraIndex) : + int cameraIndex, + int maxFrames) : Camera(frameRate), _paths(databasePaths), _odometryIgnored(odometryIgnored), _ignoreGoalDelay(ignoreGoalDelay), _goalsIgnored(goalsIgnored), _startIndex(startIndex), + _maxFrames(maxFrames), _cameraIndex(cameraIndex), _dbDriver(0), _currentId(_ids.end()), _previousMapId(-1), _previousStamp(0), _previousMapID(0), - _calibrated(false) + _calibrated(false), + _framesPublished(0) { } @@ -114,6 +120,7 @@ bool DBReader::init( _previousStamp = 0; _previousMapID = 0; _calibrated = false; + _framesPublished = 0; if(_paths.size() == 0) { @@ -212,6 +219,12 @@ std::string DBReader::getSerial() const SensorData DBReader::captureImage(CameraInfo * info) { + if(_maxFrames>0 && ++_framesPublished > _maxFrames) + { + UINFO("Maximum frames (%d) reached!", _maxFrames); + return SensorData(); + } + SensorData data = this->getNextData(info); if(data.id() == 0) { @@ -231,6 +244,7 @@ SensorData DBReader::captureImage(CameraInfo * info) } } } + if(data.id()) { std::string goalId; diff --git a/corelib/src/camera/CameraImages.cpp b/corelib/src/camera/CameraImages.cpp index de3d0167..8cae7881 100644 --- a/corelib/src/camera/CameraImages.cpp +++ b/corelib/src/camera/CameraImages.cpp @@ -41,12 +41,14 @@ namespace rtabmap CameraImages::CameraImages() : _startAt(0), + _maxFrames(0), _refreshDir(false), _rectifyImages(false), _bayerMode(-1), _isDepth(false), _depthScaleFactor(1.0f), _count(0), + _framesPublished(0), _dir(0), _countScan(0), _scanDir(0), @@ -68,12 +70,14 @@ CameraImages::CameraImages(const std::string & path, Camera(imageRate, localTransform), _path(path), _startAt(0), + _maxFrames(0), _refreshDir(false), _rectifyImages(false), _bayerMode(-1), _isDepth(false), _depthScaleFactor(1.0f), _count(0), + _framesPublished(0), _dir(0), _countScan(0), _scanDir(0), @@ -106,6 +110,7 @@ bool CameraImages::init(const std::string & calibrationFolder, const std::string _count = 0; _countScan = 0; _captureDelay = 0.0; + _framesPublished=0; UDEBUG(""); if(_dir) @@ -617,7 +622,7 @@ SensorData CameraImages::captureImage(CameraInfo * info) if(!fileName.empty()) { scanFilePath = _scanPath + fileName; - while(++_countScan < _startAt && (fileName = _scanDir->getNextFileName()).size()) + while(_countScan++ < _startAt && (fileName = _scanDir->getNextFileName()).size()) { scanFilePath = _scanPath + fileName; } @@ -625,99 +630,103 @@ SensorData CameraImages::captureImage(CameraInfo * info) } } - if(!imageFilePath.empty()) + if(_maxFrames <=0 || ++_framesPublished <= _maxFrames) { - ULOGGER_DEBUG("Loading image : %s", imageFilePath.c_str()); + + if(!imageFilePath.empty()) + { + ULOGGER_DEBUG("Loading image : %s", imageFilePath.c_str()); #if CV_MAJOR_VERSION >2 || (CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4) - img = cv::imread(imageFilePath.c_str(), cv::IMREAD_UNCHANGED); + img = cv::imread(imageFilePath.c_str(), cv::IMREAD_UNCHANGED); #else - img = cv::imread(imageFilePath.c_str(), -1); + img = cv::imread(imageFilePath.c_str(), -1); #endif - UDEBUG("width=%d, height=%d, channels=%d, elementSize=%d, total=%d", - img.cols, img.rows, img.channels(), img.elemSize(), img.total()); + UDEBUG("width=%d, height=%d, channels=%d, elementSize=%d, total=%d", + img.cols, img.rows, img.channels(), img.elemSize(), img.total()); - if(_isDepth) - { - if(img.type() != CV_16UC1 && img.type() != CV_32FC1) + if(_isDepth) { - UERROR("Depth is on and the loaded image has not a format supported (file = \"%s\", type=%d). " - "Formats supported are 16 bits 1 channel (mm) and 32 bits 1 channel (m).", - imageFilePath.c_str(), img.type()); - img = cv::Mat(); - } - - if(_depthScaleFactor > 1.0f) - { - img /= _depthScaleFactor; - } - } - else - { -#if CV_MAJOR_VERSION < 3 - // FIXME : it seems that some png are incorrectly loaded with opencv c++ interface, where c interface works... - if(img.depth() != CV_8U) - { - // The depth should be 8U - UWARN("Cannot read the image correctly, falling back to old OpenCV C interface..."); - IplImage * i = cvLoadImage(imageFilePath.c_str()); - img = cv::Mat(i, true); - cvReleaseImage(&i); - } -#endif - if(img.channels()>3) - { - UWARN("Conversion from 4 channels to 3 channels (file=%s)", imageFilePath.c_str()); - cv::Mat out; - cv::cvtColor(img, out, CV_BGRA2BGR); - img = out; - } - else if(_bayerMode >= 0 && _bayerMode <=3) - { - cv::Mat debayeredImg; - try + if(img.type() != CV_16UC1 && img.type() != CV_32FC1) { - cv::cvtColor(img, debayeredImg, CV_BayerBG2BGR + _bayerMode); - img = debayeredImg; + UERROR("Depth is on and the loaded image has not a format supported (file = \"%s\", type=%d). " + "Formats supported are 16 bits 1 channel (mm) and 32 bits 1 channel (m).", + imageFilePath.c_str(), img.type()); + img = cv::Mat(); } - catch(const cv::Exception & e) + + if(_depthScaleFactor > 1.0f) { - UWARN("Error debayering images: \"%s\". Please set bayer mode to -1 if images are not bayered!", e.what()); + img /= _depthScaleFactor; } } - - } - - if(!img.empty() && _model.isValidForRectification() && _rectifyImages) - { - img = _model.rectifyImage(img); - } - } - - if(!scanFilePath.empty()) - { - // load without filtering - scan = util3d::loadScan(scanFilePath); - scan = LaserScan(scan.data(), _scanMaxPts, 0.0f, scan.format(), _scanLocalTransform); - UDEBUG("Loaded scan=%d points", (int)scan.size()); - if(_depthFromScan && !img.empty()) - { - UDEBUG("Computing depth from scan..."); - if(!_model.isValidForProjection()) - { - UWARN("Depth from laser scan: Camera model should be valid."); - } - else if(_isDepth) - { - UWARN("Depth from laser scan: Loading already a depth image."); - } else { - pcl::PointCloud::Ptr cloud = util3d::laserScanToPointCloud(scan, scan.localTransform()); - depthFromScan = util3d::projectCloudToCamera(img.size(), _model.K(), cloud, _model.localTransform()); - if(_depthFromScanFillHoles!=0) +#if CV_MAJOR_VERSION < 3 + // FIXME : it seems that some png are incorrectly loaded with opencv c++ interface, where c interface works... + if(img.depth() != CV_8U) { - util3d::fillProjectedCloudHoles(depthFromScan, _depthFromScanFillHoles>0, _depthFromScanFillHolesFromBorder); + // The depth should be 8U + UWARN("Cannot read the image correctly, falling back to old OpenCV C interface..."); + IplImage * i = cvLoadImage(imageFilePath.c_str()); + img = cv::Mat(i, true); + cvReleaseImage(&i); + } +#endif + if(img.channels()>3) + { + UWARN("Conversion from 4 channels to 3 channels (file=%s)", imageFilePath.c_str()); + cv::Mat out; + cv::cvtColor(img, out, CV_BGRA2BGR); + img = out; + } + else if(_bayerMode >= 0 && _bayerMode <=3) + { + cv::Mat debayeredImg; + try + { + cv::cvtColor(img, debayeredImg, CV_BayerBG2BGR + _bayerMode); + img = debayeredImg; + } + catch(const cv::Exception & e) + { + UWARN("Error debayering images: \"%s\". Please set bayer mode to -1 if images are not bayered!", e.what()); + } + } + + } + + if(!img.empty() && _model.isValidForRectification() && _rectifyImages) + { + img = _model.rectifyImage(img); + } + } + + if(!scanFilePath.empty()) + { + // load without filtering + scan = util3d::loadScan(scanFilePath); + scan = LaserScan(scan.data(), _scanMaxPts, 0.0f, scan.format(), _scanLocalTransform); + UDEBUG("Loaded scan=%d points", (int)scan.size()); + if(_depthFromScan && !img.empty()) + { + UDEBUG("Computing depth from scan..."); + if(!_model.isValidForProjection()) + { + UWARN("Depth from laser scan: Camera model should be valid."); + } + else if(_isDepth) + { + UWARN("Depth from laser scan: Loading already a depth image."); + } + else + { + pcl::PointCloud::Ptr cloud = util3d::laserScanToPointCloud(scan, scan.localTransform()); + depthFromScan = util3d::projectCloudToCamera(img.size(), _model.K(), cloud, _model.localTransform()); + if(_depthFromScanFillHoles!=0) + { + util3d::fillProjectedCloudHoles(depthFromScan, _depthFromScanFillHoles>0, _depthFromScanFillHolesFromBorder); + } } } } diff --git a/guilib/include/rtabmap/gui/ImageView.h b/guilib/include/rtabmap/gui/ImageView.h index c647d197..e665c3bb 100644 --- a/guilib/include/rtabmap/gui/ImageView.h +++ b/guilib/include/rtabmap/gui/ImageView.h @@ -67,6 +67,9 @@ public: bool isGraphicsViewScaled() const; bool isGraphicsViewScaledToHeight() const; const QColor & getDefaultBackgroundColor() const; + const QColor & getDefaultFeatureColor() const; + const QColor & getDefaultMatchingFeatureColor() const; + const QColor & getDefaultMatchingLineColor() const; const QColor & getBackgroundColor() const; uCvQtDepthColorMap getDepthColorMap() const; @@ -80,6 +83,9 @@ public: void setGraphicsViewScaled(bool scaled); void setGraphicsViewScaledToHeight(bool scaled); void setDefaultBackgroundColor(const QColor & color); + void setDefaultFeatureColor(const QColor & color); + void setDefaultMatchingFeatureColor(const QColor & color); + void setDefaultMatchingLineColor(const QColor & color); void setBackgroundColor(const QColor & color); void setFeatures(const std::multimap & refWords, const cv::Mat & depth = cv::Mat(), const QColor & color = Qt::yellow); @@ -117,18 +123,25 @@ private Q_SLOTS: private: void updateOpacity(); void computeScaleOffsets(const QRect & targetRect, float & scale, float & offsetX, float & offsetY) const; + QIcon createIcon(const QColor & color); private: QString _savedFileName; int _alpha; int _featuresSize; QColor _defaultBgColor; + QColor _defaultFeatureColor; + QColor _defaultMatchingFeatureColor; + QColor _defaultMatchingLineColor; QMenu * _menu; QAction * _showImage; QAction * _showImageDepth; QAction * _showFeatures; QAction * _showLines; + QAction * _setFeatureColor; + QAction * _setMatchingFeatureColor; + QAction * _setMatchingLineColor; QAction * _saveImage; QAction * _setAlpha; QAction * _setFeaturesSize; @@ -140,6 +153,7 @@ private: QAction * _colorMapBlackToWhite; QAction * _colorMapRedToBlue; QAction * _colorMapBlueToRed; + QMenu * _featureMenu; QMenu * _scaleMenu; QGraphicsView * _graphicsView; diff --git a/guilib/src/DatabaseViewer.cpp b/guilib/src/DatabaseViewer.cpp index 576b6c21..9e1d20f7 100644 --- a/guilib/src/DatabaseViewer.cpp +++ b/guilib/src/DatabaseViewer.cpp @@ -4820,11 +4820,10 @@ void DatabaseViewer::updateWordsMatching() int to = ids_.at(ui_->horizontalSlider_B->value()); if(from && to) { - int alpha = 70; ui_->graphicsView_A->clearLines(); - ui_->graphicsView_A->setFeaturesColor(QColor(255, 255, 0, alpha)); // yellow + ui_->graphicsView_A->setFeaturesColor(ui_->graphicsView_A->getDefaultFeatureColor()); ui_->graphicsView_B->clearLines(); - ui_->graphicsView_B->setFeaturesColor(QColor(255, 255, 0, alpha)); // yellow + ui_->graphicsView_B->setFeaturesColor(ui_->graphicsView_B->getDefaultFeatureColor()); const QMultiMap & wordsA = ui_->graphicsView_A->getFeatures(); const QMultiMap & wordsB = ui_->graphicsView_B->getFeatures(); @@ -4836,8 +4835,8 @@ void DatabaseViewer::updateWordsMatching() if(ids[i] > 0 && wordsA.count(ids[i]) == 1 && wordsB.count(ids[i]) == 1) { // PINK features - ui_->graphicsView_A->setFeatureColor(ids[i], Qt::magenta); - ui_->graphicsView_B->setFeatureColor(ids[i], Qt::magenta); + ui_->graphicsView_A->setFeatureColor(ids[i], ui_->graphicsView_A->getDefaultMatchingFeatureColor()); + ui_->graphicsView_B->setFeatureColor(ids[i], ui_->graphicsView_B->getDefaultMatchingFeatureColor()); // Add lines // Draw lines between corresponding features... @@ -4861,14 +4860,14 @@ void DatabaseViewer::updateWordsMatching() kptA->rect().y()+kptA->rect().height()/2, kptB->rect().x()+kptB->rect().width()/2+deltaX, kptB->rect().y()+kptB->rect().height()/2+deltaY, - Qt::cyan); + ui_->graphicsView_A->getDefaultMatchingLineColor()); ui_->graphicsView_B->addLine( kptA->rect().x()+kptA->rect().width()/2-deltaX, kptA->rect().y()+kptA->rect().height()/2-deltaY, kptB->rect().x()+kptB->rect().width()/2, kptB->rect().y()+kptB->rect().height()/2, - Qt::cyan); + ui_->graphicsView_B->getDefaultMatchingLineColor()); } } ui_->graphicsView_A->update(); diff --git a/guilib/src/ImageView.cpp b/guilib/src/ImageView.cpp index 10cdb32b..1611e6f5 100644 --- a/guilib/src/ImageView.cpp +++ b/guilib/src/ImageView.cpp @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include "rtabmap/utilite/ULogger.h" #include "rtabmap/gui/KeypointItem.h" @@ -148,12 +149,22 @@ private: int _width; }; +QIcon ImageView::createIcon(const QColor & color) +{ + QPixmap pixmap(50, 50); + pixmap.fill(color); + return QIcon(pixmap); +} + ImageView::ImageView(QWidget * parent) : QWidget(parent), _savedFileName((QDir::homePath()+ "/") + "picture" + ".png"), _alpha(50), _featuresSize(0.0f), _defaultBgColor(Qt::black), + _defaultFeatureColor(Qt::yellow), + _defaultMatchingFeatureColor(Qt::magenta), + _defaultMatchingLineColor(Qt::cyan), _imageItem(0), _imageDepthItem(0) { @@ -173,13 +184,24 @@ ImageView::ImageView(QWidget * parent) : _showImageDepth = _menu->addAction(tr("Show image depth")); _showImageDepth->setCheckable(true); _showImageDepth->setChecked(false); - _showFeatures = _menu->addAction(tr("Show features")); + _featureMenu = _menu->addMenu("Features"); + _showFeatures = _featureMenu->addAction(tr("Show features")); _showFeatures->setCheckable(true); _showFeatures->setChecked(true); - _setFeaturesSize = _menu->addAction(tr("Set features size...")); - _showLines = _menu->addAction(tr("Show lines")); + _setFeaturesSize = _featureMenu->addAction(tr("Set features size...")); + _showLines = _featureMenu->addAction(tr("Show lines")); _showLines->setCheckable(true); _showLines->setChecked(true); + _setFeatureColor = _featureMenu->addAction(tr("Set default feature color")); + _setFeatureColor->setIcon(createIcon(_defaultFeatureColor)); + _setFeatureColor->setIconVisibleInMenu(true); + _setMatchingFeatureColor = _featureMenu->addAction(tr("Set default correspondence color")); + _setMatchingFeatureColor->setIcon(createIcon(_defaultMatchingFeatureColor)); + _setMatchingFeatureColor->setIconVisibleInMenu(true); + _setMatchingLineColor = _featureMenu->addAction(tr("Set default line color")); + _setMatchingLineColor->setIcon(createIcon(_defaultMatchingLineColor)); + _setMatchingLineColor->setIconVisibleInMenu(true); + _setAlpha = _featureMenu->addAction(tr("Set transparency...")); _graphicsViewMode = _menu->addAction(tr("Graphics view")); _graphicsViewMode->setCheckable(true); _graphicsViewMode->setChecked(false); @@ -216,7 +238,6 @@ ImageView::ImageView(QWidget * parent) : group->addAction(_colorMapBlackToWhite); group->addAction(_colorMapRedToBlue); group->addAction(_colorMapBlueToRed); - _setAlpha = _menu->addAction(tr("Set transparency...")); _saveImage = _menu->addAction(tr("Save picture...")); _saveImage->setEnabled(false); @@ -240,6 +261,9 @@ void ImageView::saveSettings(QSettings & settings, const QString & group) const settings.setValue("lines_shown", this->isLinesShown()); settings.setValue("alpha", this->getAlpha()); settings.setValue("bg_color", this->getDefaultBackgroundColor()); + settings.setValue("feature_color", this->getDefaultFeatureColor()); + settings.setValue("matching_feature_color", this->getDefaultMatchingFeatureColor()); + settings.setValue("matching_line_color", this->getDefaultMatchingLineColor()); settings.setValue("graphics_view", this->isGraphicsViewMode()); settings.setValue("graphics_view_scale", this->isGraphicsViewScaled()); settings.setValue("graphics_view_scale_to_height", this->isGraphicsViewScaledToHeight()); @@ -263,6 +287,9 @@ void ImageView::loadSettings(QSettings & settings, const QString & group) this->setLinesShown(settings.value("lines_shown", this->isLinesShown()).toBool()); this->setAlpha(settings.value("alpha", this->getAlpha()).toInt()); this->setDefaultBackgroundColor(settings.value("bg_color", this->getDefaultBackgroundColor()).value()); + this->setDefaultFeatureColor(settings.value("feature_color", this->getDefaultFeatureColor()).value()); + this->setDefaultMatchingFeatureColor(settings.value("matching_feature_color", this->getDefaultMatchingFeatureColor()).value()); + this->setDefaultMatchingLineColor(settings.value("matching_line_color", this->getDefaultMatchingLineColor()).value()); this->setGraphicsViewMode(settings.value("graphics_view", this->isGraphicsViewMode()).toBool()); this->setGraphicsViewScaled(settings.value("graphics_view_scale", this->isGraphicsViewScaled()).toBool()); this->setGraphicsViewScaledToHeight(settings.value("graphics_view_scale_to_height", this->isGraphicsViewScaledToHeight()).toBool()); @@ -316,6 +343,18 @@ const QColor & ImageView::getDefaultBackgroundColor() const { return _defaultBgColor; } +const QColor & ImageView::getDefaultFeatureColor() const +{ + return _defaultFeatureColor; +} +const QColor & ImageView::getDefaultMatchingFeatureColor() const +{ + return _defaultMatchingFeatureColor; +} +const QColor & ImageView::getDefaultMatchingLineColor() const +{ + return _defaultMatchingLineColor; +} const QColor & ImageView::getBackgroundColor() const { @@ -525,6 +564,19 @@ void ImageView::setDefaultBackgroundColor(const QColor & color) setBackgroundColor(color); } +void ImageView::setDefaultFeatureColor(const QColor & color) +{ + _defaultFeatureColor = color; +} +void ImageView::setDefaultMatchingFeatureColor(const QColor & color) +{ + _defaultMatchingFeatureColor = color; +} +void ImageView::setDefaultMatchingLineColor(const QColor & color) +{ + _defaultMatchingLineColor = color; +} + void ImageView::setBackgroundColor(const QColor & color) { _graphicsView->setBackgroundBrush(QBrush(color)); @@ -670,6 +722,13 @@ void ImageView::resizeEvent(QResizeEvent* event) void ImageView::contextMenuEvent(QContextMenuEvent * e) { + _setFeatureColor->setIcon(createIcon(_defaultFeatureColor)); + _setMatchingFeatureColor->setIcon(createIcon(_defaultMatchingFeatureColor)); + _setMatchingLineColor->setIcon(createIcon(_defaultMatchingLineColor)); + _setFeatureColor->setIconVisibleInMenu(true); + _setMatchingFeatureColor->setIconVisibleInMenu(true); + _setMatchingLineColor->setIconVisibleInMenu(true); + QAction * action = _menu->exec(e->globalPos()); if(action == _saveImage) { @@ -709,6 +768,41 @@ void ImageView::contextMenuEvent(QContextMenuEvent * e) this->setFeaturesShown(_showFeatures->isChecked()); Q_EMIT configChanged(); } + else if(action == _setFeatureColor || + action == _setMatchingFeatureColor || + action == _setMatchingLineColor) + { + QColor color; + if(action == _setMatchingFeatureColor) + { + color = _defaultMatchingFeatureColor; + } + else if(action == _setMatchingLineColor) + { + color = _defaultMatchingLineColor; + } + else //if(action == _setFeatureColor) + { + color = _defaultFeatureColor; + } + color = QColorDialog::getColor(color, this); + if(color.isValid()) + { + + if(action == _setMatchingFeatureColor) + { + this->setDefaultMatchingFeatureColor(color); + } + else if(action == _setMatchingLineColor) + { + this->setDefaultMatchingLineColor(color); + } + else //if(action == _setFeatureColor) + { + this->setDefaultFeatureColor(color); + } + } + } else if(action == _showImage) { this->setImageShown(_showImage->isChecked()); diff --git a/guilib/src/MainWindow.cpp b/guilib/src/MainWindow.cpp index 10eab73d..2a021917 100644 --- a/guilib/src/MainWindow.cpp +++ b/guilib/src/MainWindow.cpp @@ -4313,14 +4313,14 @@ void MainWindow::drawKeypoints(const std::multimap & refWords iter->first.y, (iter->second.x*scaleLoop+loopMarginX+deltaX-sourceMarginX)/scaleSource, (iter->second.y*scaleLoop+loopMarginY+deltaY-sourceMarginY)/scaleSource, - Qt::cyan); + _ui->imageView_source->getDefaultMatchingLineColor()); _ui->imageView_loopClosure->addLine( (iter->first.x*scaleSource+sourceMarginX-deltaX-loopMarginX)/scaleLoop, (iter->first.y*scaleSource+sourceMarginY-deltaY-loopMarginY)/scaleLoop, iter->second.x, iter->second.y, - Qt::cyan); + _ui->imageView_loopClosure->getDefaultMatchingLineColor()); } _ui->imageView_source->update(); _ui->imageView_loopClosure->update(); diff --git a/guilib/src/PreferencesDialog.cpp b/guilib/src/PreferencesDialog.cpp index 624ad465..98e64c71 100644 --- a/guilib/src/PreferencesDialog.cpp +++ b/guilib/src/PreferencesDialog.cpp @@ -560,6 +560,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : connect(_ui->source_images_toolButton_selectSource, SIGNAL(clicked()), this, SLOT(selectSourceImagesPath())); connect(_ui->source_images_lineEdit_path, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->source_images_spinBox_startPos, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); + connect(_ui->source_images_spinBox_maxFrames, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_cameraImages_bayerMode, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); //video group connect(_ui->source_video_toolButton_selectSource, SIGNAL(clicked()), this, SLOT(selectSourceVideoPath())); @@ -573,6 +574,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : connect(_ui->source_checkBox_ignoreGoalDelay, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->source_checkBox_ignoreGoals, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->source_spinBox_databaseStartPos, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); + connect(_ui->source_spinBox_databaseMaxFrames, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->source_checkBox_useDbStamps, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->source_spinBox_database_cameraIndex, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); @@ -621,6 +623,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : connect(_ui->checkBox_cameraImages_syncTimeStamps, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->doubleSpinBox_cameraRGBDImages_scale, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->spinBox_cameraRGBDImages_startIndex, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); + connect(_ui->spinBox_cameraRGBDImages_maxFrames, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->lineEdit_cameraImages_path_scans, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->lineEdit_cameraImages_laser_transform, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->spinBox_cameraImages_max_scan_pts, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); @@ -644,6 +647,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) : connect(_ui->lineEdit_cameraStereoImages_path_right, SIGNAL(textChanged(const QString &)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkBox_stereo_rectify, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->spinBox_cameraStereoImages_startIndex, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); + connect(_ui->spinBox_cameraStereoImages_maxFrames, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->toolButton_cameraStereoVideo_path, SIGNAL(clicked()), this, SLOT(selectSourceStereoVideoPath())); connect(_ui->toolButton_cameraStereoVideo_path_2, SIGNAL(clicked()), this, SLOT(selectSourceStereoVideoPath2())); @@ -1671,6 +1675,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox) _ui->source_comboBox_image_type->setCurrentIndex(kSrcUsbDevice-kSrcUsbDevice); _ui->source_images_spinBox_startPos->setValue(0); + _ui->source_images_spinBox_maxFrames->setValue(0); _ui->checkBox_rgb_rectify->setChecked(false); _ui->comboBox_cameraImages_bayerMode->setCurrentIndex(0); @@ -1678,6 +1683,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox) _ui->source_checkBox_ignoreGoalDelay->setChecked(true); _ui->source_checkBox_ignoreGoals->setChecked(true); _ui->source_spinBox_databaseStartPos->setValue(0); + _ui->source_spinBox_databaseMaxFrames->setValue(0); _ui->source_spinBox_database_cameraIndex->setValue(-1); _ui->source_checkBox_useDbStamps->setChecked(true); @@ -1743,6 +1749,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox) _ui->lineEdit_cameraRGBDImages_path_depth->setText(""); _ui->doubleSpinBox_cameraRGBDImages_scale->setValue(1.0); _ui->spinBox_cameraRGBDImages_startIndex->setValue(0); + _ui->spinBox_cameraRGBDImages_maxFrames->setValue(0); _ui->lineEdit_source_distortionModel->setText(""); _ui->groupBox_bilateral->setChecked(false); _ui->doubleSpinBox_bilateral_sigmaS->setValue(10.0); @@ -1753,6 +1760,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox) _ui->lineEdit_cameraStereoImages_path_right->setText(""); _ui->checkBox_stereo_rectify->setChecked(false); _ui->spinBox_cameraStereoImages_startIndex->setValue(0); + _ui->spinBox_cameraStereoImages_maxFrames->setValue(0); _ui->lineEdit_cameraStereoVideo_path->setText(""); _ui->lineEdit_cameraStereoVideo_path_2->setText(""); _ui->spinBox_stereo_right_device->setValue(-1); @@ -2148,6 +2156,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath) _ui->lineEdit_cameraRGBDImages_path_depth->setText(settings.value("path_depth", _ui->lineEdit_cameraRGBDImages_path_depth->text()).toString()); _ui->doubleSpinBox_cameraRGBDImages_scale->setValue(settings.value("scale", _ui->doubleSpinBox_cameraRGBDImages_scale->value()).toDouble()); _ui->spinBox_cameraRGBDImages_startIndex->setValue(settings.value("start_index", _ui->spinBox_cameraRGBDImages_startIndex->value()).toInt()); + _ui->spinBox_cameraRGBDImages_maxFrames->setValue(settings.value("max_frames", _ui->spinBox_cameraRGBDImages_maxFrames->value()).toInt()); settings.endGroup(); // RGBDImages settings.beginGroup("StereoImages"); @@ -2155,6 +2164,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath) _ui->lineEdit_cameraStereoImages_path_right->setText(settings.value("path_right", _ui->lineEdit_cameraStereoImages_path_right->text()).toString()); _ui->checkBox_stereo_rectify->setChecked(settings.value("rectify",_ui->checkBox_stereo_rectify->isChecked()).toBool()); _ui->spinBox_cameraStereoImages_startIndex->setValue(settings.value("start_index",_ui->spinBox_cameraStereoImages_startIndex->value()).toInt()); + _ui->spinBox_cameraStereoImages_maxFrames->setValue(settings.value("max_frames",_ui->spinBox_cameraStereoImages_maxFrames->value()).toInt()); settings.endGroup(); // StereoImages settings.beginGroup("StereoVideo"); @@ -2177,6 +2187,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath) settings.beginGroup("Images"); _ui->source_images_lineEdit_path->setText(settings.value("path", _ui->source_images_lineEdit_path->text()).toString()); _ui->source_images_spinBox_startPos->setValue(settings.value("startPos",_ui->source_images_spinBox_startPos->value()).toInt()); + _ui->source_images_spinBox_maxFrames->setValue(settings.value("maxFrames",_ui->source_images_spinBox_maxFrames->value()).toInt()); _ui->comboBox_cameraImages_bayerMode->setCurrentIndex(settings.value("bayerMode",_ui->comboBox_cameraImages_bayerMode->currentIndex()).toInt()); _ui->checkBox_cameraImages_timestamps->setChecked(settings.value("filenames_as_stamps",_ui->checkBox_cameraImages_timestamps->isChecked()).toBool()); @@ -2225,6 +2236,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath) _ui->source_checkBox_ignoreGoalDelay->setChecked(settings.value("ignoreGoalDelay", _ui->source_checkBox_ignoreGoalDelay->isChecked()).toBool()); _ui->source_checkBox_ignoreGoals->setChecked(settings.value("ignoreGoals", _ui->source_checkBox_ignoreGoals->isChecked()).toBool()); _ui->source_spinBox_databaseStartPos->setValue(settings.value("startPos", _ui->source_spinBox_databaseStartPos->value()).toInt()); + _ui->source_spinBox_databaseMaxFrames->setValue(settings.value("maxFrames", _ui->source_spinBox_databaseMaxFrames->value()).toInt()); _ui->source_spinBox_database_cameraIndex->setValue(settings.value("cameraIndex", _ui->source_spinBox_database_cameraIndex->value()).toInt()); _ui->source_checkBox_useDbStamps->setChecked(settings.value("useDatabaseStamps", _ui->source_checkBox_useDbStamps->isChecked()).toBool()); settings.endGroup(); // Database @@ -2573,6 +2585,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const settings.setValue("path_depth", _ui->lineEdit_cameraRGBDImages_path_depth->text()); settings.setValue("scale", _ui->doubleSpinBox_cameraRGBDImages_scale->value()); settings.setValue("start_index", _ui->spinBox_cameraRGBDImages_startIndex->value()); + settings.setValue("max_frames", _ui->spinBox_cameraRGBDImages_maxFrames->value()); settings.endGroup(); // RGBDImages settings.beginGroup("StereoImages"); @@ -2580,6 +2593,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const settings.setValue("path_right", _ui->lineEdit_cameraStereoImages_path_right->text()); settings.setValue("rectify", _ui->checkBox_stereo_rectify->isChecked()); settings.setValue("start_index", _ui->spinBox_cameraStereoImages_startIndex->value()); + settings.setValue("max_frames", _ui->spinBox_cameraStereoImages_maxFrames->value()); settings.endGroup(); // StereoImages settings.beginGroup("StereoVideo"); @@ -2603,6 +2617,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const settings.beginGroup("Images"); settings.setValue("path", _ui->source_images_lineEdit_path->text()); settings.setValue("startPos", _ui->source_images_spinBox_startPos->value()); + settings.setValue("maxFrames", _ui->source_images_spinBox_maxFrames->value()); settings.setValue("bayerMode", _ui->comboBox_cameraImages_bayerMode->currentIndex()); settings.setValue("filenames_as_stamps", _ui->checkBox_cameraImages_timestamps->isChecked()); settings.setValue("sync_stamps", _ui->checkBox_cameraImages_syncTimeStamps->isChecked()); @@ -2649,6 +2664,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const settings.setValue("ignoreGoalDelay", _ui->source_checkBox_ignoreGoalDelay->isChecked()); settings.setValue("ignoreGoals", _ui->source_checkBox_ignoreGoals->isChecked()); settings.setValue("startPos", _ui->source_spinBox_databaseStartPos->value()); + settings.setValue("maxFrames", _ui->source_spinBox_databaseMaxFrames->value()); settings.setValue("cameraIndex", _ui->source_spinBox_database_cameraIndex->value()); settings.setValue("useDatabaseStamps", _ui->source_checkBox_useDbStamps->isChecked()); settings.endGroup(); // Database @@ -3450,6 +3466,7 @@ void PreferencesDialog::selectSourceDatabase() _ui->source_database_lineEdit_path->setText(paths.size()==1?paths.front():paths.join(";")); _ui->source_spinBox_databaseStartPos->setValue(0); + _ui->source_spinBox_databaseMaxFrames->setValue(0); _ui->source_spinBox_database_cameraIndex->setValue(-1); } } @@ -3673,6 +3690,7 @@ void PreferencesDialog::selectSourceImagesPath() { _ui->source_images_lineEdit_path->setText(path); _ui->source_images_spinBox_startPos->setValue(0); + _ui->source_images_spinBox_maxFrames->setValue(0); } } @@ -5212,6 +5230,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor) this->getGeneralInputRate(), this->getSourceLocalTransform()); ((CameraRGBDImages*)camera)->setStartIndex(_ui->spinBox_cameraRGBDImages_startIndex->value()); + ((CameraRGBDImages*)camera)->setMaxFrames(_ui->spinBox_cameraRGBDImages_maxFrames->value()); ((CameraRGBDImages*)camera)->setBayerMode(_ui->comboBox_cameraImages_bayerMode->currentIndex()-1); ((CameraRGBDImages*)camera)->setOdometryPath(_ui->lineEdit_cameraImages_odom->text().toStdString(), _ui->comboBox_cameraImages_odomFormat->currentIndex()); ((CameraRGBDImages*)camera)->setGroundTruthPath(_ui->lineEdit_cameraImages_gt->text().toStdString(), _ui->comboBox_cameraImages_gtFormat->currentIndex()); @@ -5256,6 +5275,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor) this->getGeneralInputRate(), this->getSourceLocalTransform()); ((CameraStereoImages*)camera)->setStartIndex(_ui->spinBox_cameraStereoImages_startIndex->value()); + ((CameraStereoImages*)camera)->setMaxFrames(_ui->spinBox_cameraStereoImages_maxFrames->value()); ((CameraStereoImages*)camera)->setBayerMode(_ui->comboBox_cameraImages_bayerMode->currentIndex()-1); ((CameraStereoImages*)camera)->setOdometryPath(_ui->lineEdit_cameraImages_odom->text().toStdString(), _ui->comboBox_cameraImages_odomFormat->currentIndex()); ((CameraStereoImages*)camera)->setGroundTruthPath(_ui->lineEdit_cameraImages_gt->text().toStdString(), _ui->comboBox_cameraImages_gtFormat->currentIndex()); @@ -5379,6 +5399,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor) this->getSourceLocalTransform()); ((CameraImages*)camera)->setStartIndex(_ui->source_images_spinBox_startPos->value()); + ((CameraImages*)camera)->setMaxFrames(_ui->source_images_spinBox_maxFrames->value()); ((CameraImages*)camera)->setImagesRectified(_ui->checkBox_rgb_rectify->isChecked() && !useRawImages); ((CameraImages*)camera)->setBayerMode(_ui->comboBox_cameraImages_bayerMode->currentIndex()-1); @@ -5410,7 +5431,8 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor) _ui->source_checkBox_ignoreGoalDelay->isChecked(), _ui->source_checkBox_ignoreGoals->isChecked(), _ui->source_spinBox_databaseStartPos->value(), - _ui->source_spinBox_database_cameraIndex->value()); + _ui->source_spinBox_database_cameraIndex->value(), + _ui->source_spinBox_databaseMaxFrames->value()); } else { diff --git a/guilib/src/ui/preferencesDialog.ui b/guilib/src/ui/preferencesDialog.ui index 7e10328d..c29b8dec 100644 --- a/guilib/src/ui/preferencesDialog.ui +++ b/guilib/src/ui/preferencesDialog.ui @@ -94,7 +94,7 @@ 0 - -1219 + -234 680 3082 @@ -126,7 +126,7 @@ QFrame::Raised - 1 + 5 @@ -3936,7 +3936,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki - + Qt::Vertical @@ -3969,6 +3969,26 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki + + + + Maximum frames after start position. 0 means publishing all frames. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + 9999999 + + + @@ -4295,7 +4315,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki - 6 + 2 @@ -4352,7 +4372,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki - + Qt::Vertical @@ -4432,6 +4452,26 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki + + + + Maximum frames after start position. 0 means publishing all frames. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + 9999999 + + + @@ -4904,7 +4944,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki - 2 + 1 @@ -4968,6 +5008,29 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki + + + + Maximum frames after start position. 0 means publishing all frames. + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + 0 + + + 999999999 + + + @@ -5081,19 +5144,6 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki - - - - Qt::Vertical - - - - 20 - 0 - - - - @@ -5111,6 +5161,19 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki + + + + Qt::Vertical + + + + 20 + 0 + + + + @@ -5164,6 +5227,16 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki + + + + -1 + + + 9999 + + + @@ -5184,17 +5257,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki - - - - -1 - - - 9999 - - - - + Camera index. If the database contains multi-camera data, you can choose which camera to use. -1 means that all cameras are streamed. @@ -5207,6 +5270,26 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki + + + + Maximum frames after start position. 0 means publishing all frames. + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + 0 + + + 99999 + + +