diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index dbd5cc7c..273255c5 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -9,6 +9,7 @@ SET(headers_ui ../src/ParametersToolBox.h ../src/AboutDialog.h ../src/TcpServer.h + ../src/RectItem.h ../src/utilite/UPlot.h ../src/rtabmap/PdfPlot.h ) @@ -39,6 +40,7 @@ SET(SRC_FILES ../src/MainWindow.cpp ../src/AddObjectDialog.cpp ../src/KeypointItem.cpp + ../src/RectItem.cpp ../src/QtOpenCV.cpp ../src/Camera.cpp ../src/ParametersToolBox.cpp diff --git a/src/KeypointItem.cpp b/src/KeypointItem.cpp index 86b76a3b..c49393b7 100644 --- a/src/KeypointItem.cpp +++ b/src/KeypointItem.cpp @@ -19,15 +19,10 @@ KeypointItem::KeypointItem(int id, qreal x, qreal y, int r, const QString & info this->setAcceptsHoverEvents(true); this->setFlag(QGraphicsItem::ItemIsFocusable, true); this->setFlag(QGraphicsItem::ItemIsSelectable, true); - width_ = pen().width(); } KeypointItem::~KeypointItem() { - /*if(placeHolder_) - { - delete placeHolder_; - }*/ } void KeypointItem::setColor(const QColor & color) @@ -46,46 +41,41 @@ void KeypointItem::setColor(const QColor & color) void KeypointItem::showDescription() { - if(!placeHolder_) + if(!placeHolder_ || !placeHolder_->isVisible()) { - placeHolder_ = new QGraphicsRectItem(); - placeHolder_->setVisible(false); - this->scene()->addItem(placeHolder_); - placeHolder_->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background - QGraphicsTextItem * text = new QGraphicsTextItem(placeHolder_); - text->setDefaultTextColor(this->pen().color().rgb()); - text->setPlainText(info_); - placeHolder_->setRect(text->boundingRect()); + if(!placeHolder_) + { + placeHolder_ = new QGraphicsRectItem(); + placeHolder_->setVisible(false); + this->scene()->addItem(placeHolder_); + placeHolder_->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background + QGraphicsTextItem * text = new QGraphicsTextItem(placeHolder_); + text->setDefaultTextColor(this->pen().color().rgb()); + text->setPlainText(info_); + placeHolder_->setRect(text->boundingRect()); + } + + + QPen pen = this->pen(); + this->setPen(QPen(pen.color(), pen.width()+2)); + placeHolder_->setZValue(this->zValue()+1); + placeHolder_->setPos(this->mapToScene(0,0)); + placeHolder_->setVisible(true); } - - - QPen pen = this->pen(); - this->setPen(QPen(pen.color(), width_+2)); - placeHolder_->setZValue(this->zValue()+1); - placeHolder_->setPos(this->mapToScene(0,0)); - placeHolder_->setVisible(true); } void KeypointItem::hideDescription() { - if(placeHolder_) + if(placeHolder_ && placeHolder_->isVisible()) { placeHolder_->setVisible(false); + this->setPen(QPen(pen().color(), pen().width()-2)); } - this->setPen(QPen(pen().color(), width_)); } void KeypointItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) { - QGraphicsScene * scene = this->scene(); - if(scene && scene->focusItem() == 0) - { - this->showDescription(); - } - else - { - this->setPen(QPen(pen().color(), width_+2)); - } + this->showDescription(); QGraphicsEllipseItem::hoverEnterEvent(event); } diff --git a/src/KeypointItem.h b/src/KeypointItem.h index 60a312a2..1c4e5eca 100644 --- a/src/KeypointItem.h +++ b/src/KeypointItem.h @@ -32,7 +32,6 @@ private: private: QString info_; QGraphicsRectItem * placeHolder_; - int width_; int id_; }; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 0dd2e4c3..81672d92 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -7,6 +7,7 @@ #include "ui_mainWindow.h" #include "QtOpenCV.h" #include "KeypointItem.h" +#include "RectItem.h" #include "ObjWidget.h" #include "Camera.h" #include "Settings.h" @@ -634,6 +635,34 @@ void MainWindow::showObject(ObjWidget * obj) } } +std::vector limitKeypoints(const std::vector & keypoints, int maxKeypoints) +{ + std::vector kptsKept; + if(maxKeypoints > 0 && (int)keypoints.size() > maxKeypoints) + { + // Sort words by response + std::multimap reponseMap; // + for(unsigned int i = 0; i (fabs(keypoints[i].response), i)); + } + + // Remove them + std::multimap::reverse_iterator iter = reponseMap.rbegin(); + kptsKept.resize(maxKeypoints); + for(unsigned int k=0; k < kptsKept.size() && iter!=reponseMap.rend(); ++k, ++iter) + { + kptsKept[k] = keypoints[iter->second]; + } + } + else + { + kptsKept = keypoints; + } + return kptsKept; +} + class ExtractFeaturesThread : public QThread { public: @@ -663,6 +692,14 @@ protected: if(keypoints_.size()) { + int maxFeatures = Settings::getFeature2D_3MaxFeatures(); + if(maxFeatures > 0 && (int)keypoints_.size() > maxFeatures) + { + int previousCount = keypoints_.size(); + keypoints_ = limitKeypoints(keypoints_, maxFeatures); + printf("obj=%d, %d keypoints removed, (kept %d), min/max response=%f/%f\n", objectId_, previousCount-(int)keypoints_.size(), (int)keypoints_.size(), keypoints_.size()?keypoints_.back().response:0.0f, keypoints_.size()?keypoints_.front().response:0.0f); + } + cv::DescriptorExtractor * extractor = Settings::createDescriptorsExtractor(); extractor->compute(image_, keypoints_, descriptors_); delete extractor; @@ -839,7 +876,7 @@ void MainWindow::updateData() objects_[i]->setWords(words); addedWords += words.uniqueKeys().size(); bool updated = false; - if(incremental && addedWords > updateVocabularyMinWords) + if(incremental && addedWords && addedWords >= updateVocabularyMinWords) { vocabulary_.update(); addedWords = 0; @@ -984,6 +1021,18 @@ void MainWindow::moveCameraFrame(int frame) } } +void MainWindow::rectHovered(int objId) +{ + if(objId>=0 && Settings::getGeneral_autoScroll()) + { + QLabel * label = ui_->dockWidget_objects->findChild(QString("%1title").arg(objId)); + if(label) + { + ui_->objects_area->verticalScrollBar()->setValue(label->pos().y()); + } + } +} + class SearchThread: public QThread { public: @@ -1209,6 +1258,14 @@ void MainWindow::update(const cv::Mat & image) cv::Mat descriptors; if(keypoints.size()) { + int maxFeatures = Settings::getFeature2D_3MaxFeatures(); + if(maxFeatures > 0 && (int)keypoints.size() > maxFeatures) + { + //int previousCount = (int)keypoints.size(); + keypoints = limitKeypoints(keypoints, maxFeatures); + //printf("%d keypoints removed, (kept %d), min/max response=%f/%f\n", previousCount-(int)keypoints.size(), (int)keypoints.size(), keypoints.size()?keypoints.back().response:0.0f, keypoints.size()?keypoints.front().response:0.0f); + } + // EXTRACT DESCRIPTORS cv::DescriptorExtractor * extractor = Settings::createDescriptorsExtractor(); extractor->compute(grayscaleImg, keypoints, descriptors); @@ -1502,7 +1559,8 @@ void MainWindow::update(const cv::Mat & image) } QPen rectPen(color); rectPen.setWidth(4); - QGraphicsRectItem * rectItemScene = new QGraphicsRectItem(rect); + RectItem * rectItemScene = new RectItem(objects_.at(index)->id(), rect); + connect(rectItemScene, SIGNAL(hovered(int)), this, SLOT(rectHovered(int))); rectItemScene->setPen(rectPen); rectItemScene->setTransform(hTransform); ui_->imageView_source->addRect(rectItemScene); diff --git a/src/MainWindow.h b/src/MainWindow.h index 67bc464a..171e98d4 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -75,6 +75,7 @@ private slots: void updateObjects(); void notifyParametersChanged(const QStringList & param); void moveCameraFrame(int frame); + void rectHovered(int objId); signals: void objectsFound(const QMultiMap > &); diff --git a/src/ObjWidget.cpp b/src/ObjWidget.cpp index cc97d9b6..bfdf93bf 100644 --- a/src/ObjWidget.cpp +++ b/src/ObjWidget.cpp @@ -315,7 +315,7 @@ void ObjWidget::addRect(QGraphicsRectItem * rect) { graphicsView_->scene()->addItem(rect); } - rect->setZValue(2); + rect->setZValue(1); QPen pen = rect->pen(); QColor color = pen.color(); color.setAlpha(alpha_); @@ -723,7 +723,7 @@ void ObjWidget::drawKeypoints(QPainter * painter) // YELLOW = NEW and multiple times item = new KeypointItem(i+1, r.pt.x-radius, r.pt.y-radius, radius*2, info, color); item->setVisible(this->isFeaturesShown()); - item->setZValue(1); + item->setZValue(2); graphicsView_->scene()->addItem(item); keypointItems_.append(item); } diff --git a/src/RectItem.cpp b/src/RectItem.cpp new file mode 100644 index 00000000..524e676c --- /dev/null +++ b/src/RectItem.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke + */ + +#include "RectItem.h" + +#include +#include +#include + +RectItem::RectItem(int id, const QRectF &rect, QGraphicsItem * parent) : + QGraphicsRectItem(rect, parent), + placeHolder_(0), + id_(id) +{ + this->setAcceptsHoverEvents(true); + this->setFlag(QGraphicsItem::ItemIsFocusable, true); + this->setFlag(QGraphicsItem::ItemIsSelectable, true); +} + +RectItem::~RectItem() +{ +} + +void RectItem::setColor(const QColor & color) +{ + this->setPen(QPen(color)); + this->setBrush(QBrush(color)); + if(placeHolder_) + { + QList items = placeHolder_->children(); + if(items.size()) + { + ((QGraphicsTextItem *)items.front())->setDefaultTextColor(this->pen().color().rgb()); + } + } +} + +void RectItem::showDescription() +{ + if(!placeHolder_ || !placeHolder_->isVisible()) + { + if(!placeHolder_) + { + placeHolder_ = new QGraphicsRectItem(); + placeHolder_->setVisible(false); + this->scene()->addItem(placeHolder_); + placeHolder_->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background + QGraphicsTextItem * text = new QGraphicsTextItem(placeHolder_); + text->setDefaultTextColor(this->pen().color().rgb()); + text->setPlainText(tr("Object=%1").arg(id_)); + placeHolder_->setRect(text->boundingRect()); + } + + + QPen pen = this->pen(); + this->setPen(QPen(pen.color(), pen.width()+2)); + placeHolder_->setZValue(this->zValue()+1); + placeHolder_->setPos(0,0); + placeHolder_->setVisible(true); + + emit hovered(id_); + } +} + +void RectItem::hideDescription() +{ + if(placeHolder_ && placeHolder_->isVisible()) + { + placeHolder_->setVisible(false); + this->setPen(QPen(pen().color(), pen().width()-2)); + } +} + +void RectItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) +{ + this->showDescription(); + QGraphicsRectItem::hoverEnterEvent(event); +} + +void RectItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) +{ + if(!this->hasFocus()) + { + this->hideDescription(); + } + QGraphicsRectItem::hoverEnterEvent(event); +} + +void RectItem::focusInEvent ( QFocusEvent * event ) +{ + this->showDescription(); + QGraphicsRectItem::focusInEvent(event); +} + +void RectItem::focusOutEvent ( QFocusEvent * event ) +{ + this->hideDescription(); + QGraphicsRectItem::focusOutEvent(event); +} diff --git a/src/RectItem.h b/src/RectItem.h new file mode 100644 index 00000000..d1798edb --- /dev/null +++ b/src/RectItem.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke + */ + +#ifndef RECTITEM_H_ +#define RECTITEM_H_ + +#include +#include +#include +#include + +class RectItem : public QObject, public QGraphicsRectItem +{ + Q_OBJECT; + +public: + RectItem(int id, const QRectF &rect, QGraphicsItem * parent = 0); + virtual ~RectItem(); + + void setColor(const QColor & color); + int id() const {return id_;} + +signals: + void hovered(int); + +protected: + virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); + virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); + virtual void focusInEvent ( QFocusEvent * event ); + virtual void focusOutEvent ( QFocusEvent * event ); + +private: + void showDescription(); + void hideDescription(); + +private: + QGraphicsRectItem * placeHolder_; + int id_; +}; + + +#endif /* RECTITEM_H_ */ diff --git a/src/Settings.h b/src/Settings.h index a4f7f746..75772575 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -64,6 +64,7 @@ class Settings //List format : [Index:item0;item1;item3;...] PARAMETER(Feature2D, 1Detector, QString, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK" , "Keypoint detector."); PARAMETER(Feature2D, 2Descriptor, QString, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK", "Keypoint descriptor."); + PARAMETER(Feature2D, 3MaxFeatures, int, 0, "Maximum features per image. If the number of features extracted is over this threshold, only X features with the highest response are kept. 0 means all features are kept."); PARAMETER(Feature2D, Brief_bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes."); @@ -178,7 +179,7 @@ class Settings PARAMETER(General, port, int, 0, "Port on objects detected are published. If port=0, a port is chosen automatically.") PARAMETER(General, autoScroll, bool, true, "Auto scroll to detected object in Objects panel."); PARAMETER(General, vocabularyIncremental, bool, false, "The vocabulary is created incrementally. When new objects are added, their descriptors are compared to those already in vocabulary to find if the visual word already exist or not. \"NearestNeighbor/nndrRatio\" is used to compare descriptors."); - PARAMETER(General, vocabularyUpdateMinWords, int, 2000, "When the vocabulary is incremental (see \"General/vocabularyIncremental\"), after X words added to vocabulary, the internal index is updated with new words. This parameter lets avoiding to reconstruct the whole nearest neighbor index after each time descriptors of an object are added to vocabulary."); + PARAMETER(General, vocabularyUpdateMinWords, int, 2000, "When the vocabulary is incremental (see \"General/vocabularyIncremental\"), after X words added to vocabulary, the internal index is updated with new words. This parameter lets avoiding to reconstruct the whole nearest neighbor index after each time descriptors of an object are added to vocabulary. 0 means no incremental update."); PARAMETER(Homography, homographyComputed, bool, true, "Compute homography? On ROS, this is required to publish objects detected."); PARAMETER(Homography, method, QString, "1:LMEDS;RANSAC", "Type of the robust estimation algorithm: least-median algorithm or RANSAC algorithm.");