diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index bb9e8b40..97d10aa0 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "utilite/UDirectory.h" @@ -48,8 +49,8 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) : aboutDialog_ = new AboutDialog(this); this->setStatusBar(new QStatusBar()); - likelihoodCurve_ = new rtabmap::PdfPlotCurve("Likelihood", &imagesMap_); - ui_->likelihoodPlot->addCurve(likelihoodCurve_); // ownership transfered + likelihoodCurve_ = new rtabmap::PdfPlotCurve("Likelihood", &imagesMap_, this); + ui_->likelihoodPlot->addCurve(likelihoodCurve_, false); ui_->likelihoodPlot->setGraphicsView(true); if(!camera_) @@ -79,7 +80,7 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) : ui_->menuView->addAction(ui_->dockWidget_parameters->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_objects->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_plot->toggleViewAction()); - connect(ui_->toolBox, SIGNAL(parametersChanged()), this, SLOT(notifyParametersChanged())); +connect(ui_->toolBox, SIGNAL(parametersChanged(const QStringList &)), this, SLOT(notifyParametersChanged(const QStringList &))); ui_->imageView_source->setGraphicsViewMode(false); ui_->imageView_source->setTextLabel(tr("Press \"space\" to start camera...")); @@ -637,7 +638,7 @@ void MainWindow::updateData() if(count) { objectsDescriptors_ = cv::Mat(count, dim, type); - printf("Total descriptors=%d, dim=%d, type=%d\n",count, dim, type); + printf("Updating global descriptors matrix: Total descriptors=%d, dim=%d, type=%d\n",count, dim, type); int row = 0; for(int i=0; ilabel_timeIndexing->setNum(time.restart()); + ui_->label_timeIndexing->setNum(time.elapsed()); ui_->label_vocabularySize->setNum(objectsDescriptors_.rows); + printf("Creating FLANN index (%s) with objects' descriptors... done! (%d ms)\n", Settings::currentNearestNeighborType().toStdString().c_str(), time.elapsed()); } } } @@ -839,6 +842,7 @@ void MainWindow::update(const cv::Mat & image) if(!Settings::getGeneral_invertedSearch()) { // CREATE INDEX + //printf("Creating FLANN index (%s)\n", Settings::currentNearestNeighborType().toStdString().c_str()); cv::flann::IndexParams * params = Settings::createFlannIndexParams(); flannIndex_.build(descriptors, *params, Settings::getFlannDistanceType()); delete params; @@ -933,6 +937,8 @@ void MainWindow::update(const cv::Mat & image) } QMap scores; + int maxScoreId = -1; + int maxScore = 0; // For each object for(int i=0; iid(), matches[i].size()); + if(maxScoreId == -1 || maxScore < matches[i].size()) + { + maxScoreId = objects_.at(i)->id(); + maxScore = matches[i].size(); + } } //update likelihood plot @@ -1064,6 +1075,17 @@ void MainWindow::update(const cv::Mat & image) ui_->label_minMatchedDistance->setNum(minMatchedDistance); ui_->label_maxMatchedDistance->setNum(maxMatchedDistance); + //Scroll objects slider to the best score + if(maxScoreId>=0) + { + QLabel * label = ui_->dockWidget_objects->findChild(QString("%1title").arg(maxScoreId)); + if(label) + { + ui_->objects_area->verticalScrollBar()->setValue(label->pos().y()); + } + } + + // Emit homographies if(objectsDetected.size()) { emit objectsFound(objectsDetected); @@ -1120,12 +1142,48 @@ void MainWindow::update(const cv::Mat & image) } } -void MainWindow::notifyParametersChanged() +void MainWindow::notifyParametersChanged(const QStringList & paramChanged) { - printf("Parameters changed...\n"); + + //Selective update (to not update all objects for a simple camera's parameter modification) + bool detectorDescriptorParamsChanged = false; + bool nearestNeighborParamsChanged = false; + QString currentDetectorType = Settings::currentDetectorType(); + QString currentDescriptorType = Settings::currentDescriptorType(); + QString currentNNType = Settings::currentNearestNeighborType(); + //printf("currentDescriptorType: %s\n", currentDescriptorType.toStdString().c_str()); + //printf("currentNNType: %s\n", currentNNType.toStdString().c_str()); + for(QStringList::const_iterator iter = paramChanged.begin(); iter!=paramChanged.end(); ++iter) + { + printf("Parameter changed: %s\n", iter->toStdString().c_str()); + if(!detectorDescriptorParamsChanged && + ( iter->contains(currentDetectorType) || + iter->contains(currentDescriptorType) || + iter->compare(Settings::kDetector_Descriptor_1Detector()) == 0 || + iter->compare(Settings::kDetector_Descriptor_2Descriptor()) == 0 )) + { + detectorDescriptorParamsChanged = true; + } + else if(!nearestNeighborParamsChanged && + ( iter->contains(currentNNType) || + iter->compare(Settings::kGeneral_invertedSearch()) == 0 || + iter->compare(Settings::kNearestNeighbor_1Strategy()) == 0 || + iter->compare(Settings::kNearestNeighbor_2Distance_type()) == 0)) + { + nearestNeighborParamsChanged = true; + } + } + if(Settings::getGeneral_autoUpdateObjects()) { - this->updateObjects(); + if(detectorDescriptorParamsChanged) + { + this->updateObjects(); + } + else if(nearestNeighborParamsChanged) + { + this->updateData(); + } } else if(objects_.size()) { diff --git a/src/MainWindow.h b/src/MainWindow.h index 054ff1a7..e9828c85 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -65,7 +65,7 @@ private slots: void showHideControls(); void update(const cv::Mat & image); void updateObjects(); - void notifyParametersChanged(); + void notifyParametersChanged(const QStringList & param); void moveCameraFrame(int frame); signals: diff --git a/src/ParametersToolBox.cpp b/src/ParametersToolBox.cpp index 39b1d875..e0166aaf 100644 --- a/src/ParametersToolBox.cpp +++ b/src/ParametersToolBox.cpp @@ -28,8 +28,9 @@ QWidget * ParametersToolBox::getParameterWidget(const QString & key) return this->findChild(key); } -void ParametersToolBox::resetPage(int index) +QStringList ParametersToolBox::resetPage(int index) { + QStringList paramChanged; const QObjectList & children = this->widget(index)->children(); for(int j=0; j(children.at(j))) { - ((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt()); + if(((QComboBox*)children.at(j))->currentIndex() != value.toString().split(':').first().toInt()) + { + ((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt()); + paramChanged.append(key); + } } else if(qobject_cast(children.at(j))) { - ((QSpinBox*)children.at(j))->setValue(value.toInt()); + if(((QSpinBox*)children.at(j))->value() != value.toInt()) + { + ((QSpinBox*)children.at(j))->setValue(value.toInt()); + paramChanged.append(key); + } } else if(qobject_cast(children.at(j))) { - ((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble()); + if(((QDoubleSpinBox*)children.at(j))->value() != value.toDouble()) + { + ((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble()); + paramChanged.append(key); + } } else if(qobject_cast(children.at(j))) { - ((QCheckBox*)children.at(j))->setChecked(value.toBool()); + if(((QCheckBox*)children.at(j))->isChecked() != value.toBool()) + { + ((QCheckBox*)children.at(j))->setChecked(value.toBool()); + paramChanged.append(key); + } } else if(qobject_cast(children.at(j))) { - ((QLineEdit*)children.at(j))->setText(value.toString()); + if(((QLineEdit*)children.at(j))->text().compare(value.toString()) != 0) + { + ((QLineEdit*)children.at(j))->setText(value.toString()); + paramChanged.append(key); + } } - Settings::setParameter(key, value); } } } + return paramChanged; } void ParametersToolBox::resetCurrentPage() { this->blockSignals(true); - this->resetPage(this->currentIndex()); + QStringList paramChanged = this->resetPage(this->currentIndex()); this->blockSignals(false); - emit parametersChanged(); + emit parametersChanged(paramChanged); } void ParametersToolBox::resetAllPages() { + QStringList paramChanged; this->blockSignals(true); for(int i=0; i< this->count(); ++i) { - this->resetPage(i); + paramChanged.append(this->resetPage(i)); } this->blockSignals(false); - emit parametersChanged(); + emit parametersChanged(paramChanged); } void ParametersToolBox::setupUi() @@ -300,7 +324,9 @@ void ParametersToolBox::changeParameter(const QString & value) if(sender()) { Settings::setParameter(sender()->objectName(), value); - emit parametersChanged(); + QStringList paramChanged; + paramChanged.append(sender()->objectName()); + emit parametersChanged(paramChanged); } } void ParametersToolBox::changeParameter() @@ -322,21 +348,25 @@ void ParametersToolBox::changeParameter() { Settings::setParameter(sender()->objectName(), lineEdit->text()); } - emit parametersChanged(); + QStringList paramChanged; + paramChanged.append(sender()->objectName()); + emit parametersChanged(paramChanged); } } void ParametersToolBox::changeParameter(const int & value) { if(sender()) { + QStringList paramChanged; QComboBox * comboBox = qobject_cast(sender()); QCheckBox * checkBox = qobject_cast(sender()); if(comboBox) { + bool nnStrategyChanged = false; + //verify binary issue with nearest neighbor strategy if(comboBox->objectName().compare(Settings::kDetector_Descriptor_2Descriptor()) == 0 || comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0) { - //verify binary issue QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kDetector_Descriptor_2Descriptor()); QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy()); bool isBinaryDescriptor = descriptorBox->currentText().compare("ORB") == 0 || descriptorBox->currentText().compare("Brief") == 0; @@ -351,12 +381,15 @@ void ParametersToolBox::changeParameter(const int & value) QString tmp = Settings::getNearestNeighbor_1Strategy(); *tmp.begin() = '5'; // set index Settings::setNearestNeighbor_1Strategy(tmp); + nnBox->blockSignals(true); this->updateParameter(Settings::kNearestNeighbor_1Strategy()); + nnBox->blockSignals(false); if(sender() == nnBox) { return; } - + nnStrategyChanged = true; + paramChanged.append(Settings::kNearestNeighbor_1Strategy()); } else if(!isBinaryDescriptor && nnBox->currentText().compare("Lsh") == 0) { @@ -369,11 +402,44 @@ void ParametersToolBox::changeParameter(const int & value) QString tmp = Settings::getNearestNeighbor_1Strategy(); *tmp.begin() = '1'; // set index Settings::setNearestNeighbor_1Strategy(tmp); + nnBox->blockSignals(true); this->updateParameter(Settings::kNearestNeighbor_1Strategy()); + nnBox->blockSignals(false); if(sender() == nnBox) { return; } + nnStrategyChanged = true; + paramChanged.append(Settings::kNearestNeighbor_1Strategy()); + } + } + + // Distance issue when using nearest neighbor strategy using CV_32F type, though Lsh support all type (doesn't crash at least) + if(nnStrategyChanged || + comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0 || + comboBox->objectName().compare(Settings::kNearestNeighbor_2Distance_type()) == 0) + { + QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy()); + QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type()); + if(nnBox->currentText().compare("Lsh") != 0 && distBox->currentIndex() > 1) + { + QMessageBox::warning(this, + tr("Error"), + tr("Current selected nearest neighbor strategy type (\"%1\") cannot handle distance strategy (\"%2\").\n" + "Falling back to \"EUCLIDEAN_L2\" distance strategy (by default).") + .arg(nnBox->currentText()) + .arg(distBox->currentText())); + QString tmp = Settings::getNearestNeighbor_2Distance_type(); + *tmp.begin() = '0'; // set index + Settings::setNearestNeighbor_2Distance_type(tmp); + distBox->blockSignals(true); + this->updateParameter(Settings::kNearestNeighbor_2Distance_type()); + distBox->blockSignals(false); + if(sender() == distBox) + { + return; + } + paramChanged.append(Settings::kNearestNeighbor_2Distance_type()); } } @@ -389,6 +455,7 @@ void ParametersToolBox::changeParameter(const int & value) { Settings::setParameter(sender()->objectName(), value==Qt::Checked?true:false); } - emit parametersChanged(); + paramChanged.append(sender()->objectName()); + emit parametersChanged(paramChanged); } } diff --git a/src/ParametersToolBox.h b/src/ParametersToolBox.h index bf0b97da..8450bb32 100644 --- a/src/ParametersToolBox.h +++ b/src/ParametersToolBox.h @@ -31,7 +31,7 @@ private: void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget); signals: - void parametersChanged(); + void parametersChanged(const QStringList & name); private slots: void changeParameter(); @@ -41,7 +41,7 @@ private slots: void resetAllPages(); private: - void resetPage(int index); + QStringList resetPage(int index); }; #endif /* PARAMETERSTOOLBOX_H_ */ diff --git a/src/rtabmap/PdfPlot.cpp b/src/rtabmap/PdfPlot.cpp index 2703d846..578382b3 100644 --- a/src/rtabmap/PdfPlot.cpp +++ b/src/rtabmap/PdfPlot.cpp @@ -1,4 +1,4 @@ -// Taken from RTAB-Map library r605 [www.rtabmap.googlecode.com] +// Taken from RTAB-Map library r606 [www.rtabmap.googlecode.com] /* * Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke diff --git a/src/rtabmap/PdfPlot.h b/src/rtabmap/PdfPlot.h index 042f2c6b..323b66c5 100644 --- a/src/rtabmap/PdfPlot.h +++ b/src/rtabmap/PdfPlot.h @@ -1,4 +1,4 @@ -// Taken from RTAB-Map library r605 [www.rtabmap.googlecode.com] +// Taken from RTAB-Map library r606 [www.rtabmap.googlecode.com] /* * Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke diff --git a/src/ui/mainWindow.ui b/src/ui/mainWindow.ui index d2544cd0..37b0c901 100644 --- a/src/ui/mainWindow.ui +++ b/src/ui/mainWindow.ui @@ -223,14 +223,13 @@ + + - - - @@ -665,7 +664,7 @@ - Load scene from file... + Camera from single file... diff --git a/src/utilite/UPlot.cpp b/src/utilite/UPlot.cpp index df0d87aa..bd6e8a55 100644 --- a/src/utilite/UPlot.cpp +++ b/src/utilite/UPlot.cpp @@ -1,4 +1,4 @@ -// Taken from UtiLite library r185 [www.utilite.googlecode.com] +// Taken from UtiLite library r186 [www.utilite.googlecode.com] /* * utilite is a cross-platform library with @@ -296,7 +296,6 @@ void UPlotCurve::attach(UPlot * plot) { return; } - this->setParent(plot); if(_plot) { _plot->removeCurve(this); @@ -1738,7 +1737,7 @@ UPlotCurve * UPlot::addCurve(const QString & curveName, const QColor & color) return curve; } -bool UPlot::addCurve(UPlotCurve * curve) +bool UPlot::addCurve(UPlotCurve * curve, bool ownershipTransferred) { if(curve) { @@ -1757,7 +1756,11 @@ bool UPlot::addCurve(UPlotCurve * curve) // add curve _curves.append(curve); - curve->attach(this); // ownership is transferred + curve->attach(this); + if(ownershipTransferred) + { + curve->setParent(this); + } this->updateAxis(curve); curve->setXStart(_axisMaximums[1]); diff --git a/src/utilite/UPlot.h b/src/utilite/UPlot.h index 8df2baad..555c12ef 100644 --- a/src/utilite/UPlot.h +++ b/src/utilite/UPlot.h @@ -1,4 +1,4 @@ -// Taken from UtiLite library r185 [www.utilite.googlecode.com] +// Taken from UtiLite library r186 [www.utilite.googlecode.com] /* * utilite is a cross-platform library with @@ -141,7 +141,6 @@ public: void setData(const std::vector & y); void getData(QVector & x, QVector & y) const; // only call in Qt MainThread void draw(QPainter * painter); - const QVector & getMinMax() const {return _minMax;} public slots: /** @@ -225,6 +224,7 @@ protected: void attach(UPlot * plot); void detach(UPlot * plot); void updateMinMax(); + const QVector & getMinMax() const {return _minMax;} int removeItem(int index); void _addValue(UPlotItem * data);; virtual bool isMinMaxValid() const {return _minMax.size();} @@ -475,11 +475,9 @@ public: */ UPlotCurve * addCurve(const QString & curveName, const QColor & color = QColor()); /** - * Add a curve. Ownership is transferred to UPlot. - * If you add the curve to more than one UPlot, the ownership is transferred - * to the last UPlot. + * Add a curve. Ownership is transferred to UPlot if ownershipTransferred=true. */ - bool addCurve(UPlotCurve * curve); + bool addCurve(UPlotCurve * curve, bool ownershipTransferred = true); /** * Get all curve names. */