Added wordID in shown keypoint info, improved fixed vocabulary behavior
This commit is contained in:
@@ -316,7 +316,8 @@ void AddObjectDialog::setState(int state)
|
||||
selectedKeypoints.clear();
|
||||
detector_->detect(imgRoi, selectedKeypoints);
|
||||
}
|
||||
ui_->objectView->setData(selectedKeypoints, cvtCvMat2QImage(imgRoi.clone()));
|
||||
ui_->objectView->updateImage(cvtCvMat2QImage(imgRoi.clone()));
|
||||
ui_->objectView->updateData(selectedKeypoints, QMultiMap<int,int>());
|
||||
ui_->objectView->setMinimumSize(roi_.width, roi_.height);
|
||||
ui_->objectView->update();
|
||||
ui_->pushButton_next->setEnabled(true);
|
||||
@@ -359,7 +360,7 @@ void AddObjectDialog::setState(int state)
|
||||
}
|
||||
objSignature_ = new ObjSignature(0, imgRoi.clone(), "");
|
||||
objSignature_->setData(keypoints, descriptors);
|
||||
objWidget_ = new ObjWidget(0, keypoints, cvtCvMat2QImage(imgRoi.clone()));
|
||||
objWidget_ = new ObjWidget(0, keypoints, QMultiMap<int,int>(), cvtCvMat2QImage(imgRoi.clone()));
|
||||
|
||||
this->accept();
|
||||
}
|
||||
@@ -385,7 +386,8 @@ void AddObjectDialog::update(const cv::Mat & image)
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
detector_->detect(cameraImage_, keypoints);
|
||||
|
||||
ui_->cameraView->setData(keypoints, cvtCvMat2QImage(cameraImage_));
|
||||
ui_->cameraView->updateImage(cvtCvMat2QImage(cameraImage_));
|
||||
ui_->cameraView->updateData(keypoints, QMultiMap<int,int>());
|
||||
ui_->cameraView->update();
|
||||
}
|
||||
else
|
||||
|
||||
+135
-83
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "find_object/FindObject.h"
|
||||
#include "find_object/Settings.h"
|
||||
#include "find_object/utilite/ULogger.h"
|
||||
#include "utilite/UConversion.h"
|
||||
|
||||
#include "ObjSignature.h"
|
||||
#include "utilite/UDirectory.h"
|
||||
@@ -144,12 +145,12 @@ bool FindObject::saveSession(const QString & path)
|
||||
|
||||
int FindObject::loadObjects(const QString & dirPath, bool recursive)
|
||||
{
|
||||
int loadedObjects = 0;
|
||||
QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.');
|
||||
|
||||
QStringList paths;
|
||||
paths.append(dirPath);
|
||||
|
||||
QList<int> idsLoaded;
|
||||
while(paths.size())
|
||||
{
|
||||
QString currentDir = paths.front();
|
||||
@@ -159,9 +160,10 @@ int FindObject::loadObjects(const QString & dirPath, bool recursive)
|
||||
const std::list<std::string> & names = dir.getFileNames(); // sorted in natural order
|
||||
for(std::list<std::string>::const_iterator iter=names.begin(); iter!=names.end(); ++iter)
|
||||
{
|
||||
if(this->addObject((currentDir.toStdString()+dir.separator()+*iter).c_str()))
|
||||
const ObjSignature * s = this->addObject((currentDir.toStdString()+dir.separator()+*iter).c_str());
|
||||
if(s)
|
||||
{
|
||||
++loadedObjects;
|
||||
idsLoaded.push_back(s->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,13 +181,13 @@ int FindObject::loadObjects(const QString & dirPath, bool recursive)
|
||||
}
|
||||
}
|
||||
|
||||
if(loadedObjects)
|
||||
if(idsLoaded.size())
|
||||
{
|
||||
this->updateObjects();
|
||||
this->updateVocabulary();
|
||||
this->updateObjects(idsLoaded);
|
||||
this->updateVocabulary(idsLoaded);
|
||||
}
|
||||
|
||||
return loadedObjects;
|
||||
return idsLoaded.size();
|
||||
}
|
||||
|
||||
const ObjSignature * FindObject::addObject(const QString & filePath)
|
||||
@@ -279,7 +281,7 @@ void FindObject::addObjectAndUpdate(const cv::Mat & image, int id, const QString
|
||||
QList<int> ids;
|
||||
ids.push_back(s->id());
|
||||
updateObjects(ids);
|
||||
updateVocabulary();
|
||||
updateVocabulary(ids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -739,14 +741,38 @@ void FindObject::clearVocabulary()
|
||||
vocabulary_->clear();
|
||||
}
|
||||
|
||||
void FindObject::updateVocabulary()
|
||||
void FindObject::updateVocabulary(const QList<int> & ids)
|
||||
{
|
||||
clearVocabulary();
|
||||
int count = 0;
|
||||
int dim = -1;
|
||||
int type = -1;
|
||||
QList<ObjSignature*> objectsList;
|
||||
if(ids.size())
|
||||
{
|
||||
for(int i=0; i<ids.size(); ++i)
|
||||
{
|
||||
if(objects_.contains(ids[i]))
|
||||
{
|
||||
objectsList.push_back(objects_[ids[i]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
UERROR("Not found object %d!", ids[i]);
|
||||
}
|
||||
}
|
||||
if(vocabulary_->size())
|
||||
{
|
||||
dim = vocabulary_->dim();
|
||||
type = vocabulary_->type();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clearVocabulary();
|
||||
objectsList = objects_.values();
|
||||
}
|
||||
|
||||
// Get the total size and verify descriptors
|
||||
QList<ObjSignature*> objectsList = objects_.values();
|
||||
for(int i=0; i<objectsList.size(); ++i)
|
||||
{
|
||||
if(!objectsList.at(i)->descriptors().empty())
|
||||
@@ -774,94 +800,119 @@ void FindObject::updateVocabulary()
|
||||
{
|
||||
UINFO("Updating global descriptors matrix: Objects=%d, total descriptors=%d, dim=%d, type=%d",
|
||||
(int)objects_.size(), count, dim, type);
|
||||
if(Settings::getGeneral_invertedSearch() || Settings::getGeneral_threads() == 1)
|
||||
if(!Settings::getGeneral_invertedSearch())
|
||||
{
|
||||
// If only one thread, put all descriptors in the same cv::Mat
|
||||
objectsDescriptors_.insert(0, cv::Mat(count, dim, type));
|
||||
int row = 0;
|
||||
for(int i=0; i<objectsList.size(); ++i)
|
||||
if(Settings::getGeneral_threads() == 1)
|
||||
{
|
||||
if(objectsList.at(i)->descriptors().rows)
|
||||
// If only one thread, put all descriptors in the same cv::Mat
|
||||
int row = 0;
|
||||
bool vocabularyEmpty = objectsDescriptors_.size() == 0;
|
||||
if(vocabularyEmpty)
|
||||
{
|
||||
cv::Mat dest(objectsDescriptors_.begin().value(), cv::Range(row, row+objectsList.at(i)->descriptors().rows));
|
||||
objectsList.at(i)->descriptors().copyTo(dest);
|
||||
row += objectsList.at(i)->descriptors().rows;
|
||||
// dataRange contains the upper_bound for each
|
||||
// object (the last descriptors position in the
|
||||
// global object descriptors matrix)
|
||||
UASSERT(objectsDescriptors_.size() == 0);
|
||||
objectsDescriptors_.insert(0, cv::Mat(count, dim, type));
|
||||
}
|
||||
else
|
||||
{
|
||||
row = objectsDescriptors_.begin().value().rows;
|
||||
}
|
||||
for(int i=0; i<objectsList.size(); ++i)
|
||||
{
|
||||
objectsList[i]->setWords(QMultiMap<int,int>());
|
||||
if(objectsList.at(i)->descriptors().rows)
|
||||
{
|
||||
dataRange_.insert(row-1, objectsList.at(i)->id());
|
||||
if(vocabularyEmpty)
|
||||
{
|
||||
cv::Mat dest(objectsDescriptors_.begin().value(), cv::Range(row, row+objectsList.at(i)->descriptors().rows));
|
||||
objectsList.at(i)->descriptors().copyTo(dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
UASSERT_MSG(objectsDescriptors_.begin().value().cols == objectsList.at(i)->descriptors().cols,
|
||||
uFormat("%d vs %d", objectsDescriptors_.begin().value().cols, objectsList.at(i)->descriptors().cols).c_str());
|
||||
UASSERT(objectsDescriptors_.begin().value().type() == objectsList.at(i)->descriptors().type());
|
||||
objectsDescriptors_.begin().value().push_back(objectsList.at(i)->descriptors());
|
||||
}
|
||||
|
||||
row += objectsList.at(i)->descriptors().rows;
|
||||
// dataRange contains the upper_bound for each
|
||||
// object (the last descriptors position in the
|
||||
// global object descriptors matrix)
|
||||
if(objectsList.at(i)->descriptors().rows)
|
||||
{
|
||||
dataRange_.insert(row-1, objectsList.at(i)->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Settings::getGeneral_invertedSearch())
|
||||
else
|
||||
{
|
||||
sessionModified_ = true;
|
||||
QTime time;
|
||||
time.start();
|
||||
bool incremental = Settings::getGeneral_vocabularyIncremental() && !Settings::getGeneral_vocabularyFixed();
|
||||
if(incremental)
|
||||
{
|
||||
UINFO("Creating incremental vocabulary...");
|
||||
}
|
||||
else if(Settings::getGeneral_vocabularyFixed())
|
||||
{
|
||||
UINFO("Updating vocabulary correspondences only (vocabulary is fixed)...");
|
||||
}
|
||||
else
|
||||
{
|
||||
UINFO("Creating vocabulary...");
|
||||
}
|
||||
QTime localTime;
|
||||
localTime.start();
|
||||
int updateVocabularyMinWords = Settings::getGeneral_vocabularyUpdateMinWords();
|
||||
int addedWords = 0;
|
||||
for(int i=0; i<objectsList.size(); ++i)
|
||||
{
|
||||
QMultiMap<int, int> words = vocabulary_->addWords(objectsList[i]->descriptors(), objectsList.at(i)->id());
|
||||
objectsList[i]->setWords(words);
|
||||
addedWords += words.uniqueKeys().size();
|
||||
bool updated = false;
|
||||
if(incremental && addedWords && addedWords >= updateVocabularyMinWords)
|
||||
{
|
||||
vocabulary_->update();
|
||||
addedWords = 0;
|
||||
updated = true;
|
||||
}
|
||||
UINFO("Object %d, %d words from %d descriptors (%d words, %d ms) %s",
|
||||
objectsList[i]->id(),
|
||||
words.uniqueKeys().size(),
|
||||
objectsList[i]->descriptors().rows,
|
||||
vocabulary_->size(),
|
||||
localTime.restart(),
|
||||
updated?"updated":"");
|
||||
}
|
||||
if(addedWords && !Settings::getGeneral_vocabularyFixed())
|
||||
{
|
||||
vocabulary_->update();
|
||||
}
|
||||
|
||||
if(incremental)
|
||||
{
|
||||
UINFO("Creating incremental vocabulary... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed());
|
||||
}
|
||||
else if(Settings::getGeneral_vocabularyFixed())
|
||||
{
|
||||
UINFO("Updating vocabulary correspondences only (vocabulary is fixed)... done! size=%d (%d ms)", time.elapsed());
|
||||
}
|
||||
else
|
||||
{
|
||||
UINFO("Creating vocabulary... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed());
|
||||
objectsList[i]->setWords(QMultiMap<int,int>());
|
||||
objectsDescriptors_.insert(objectsList.at(i)->id(), objectsList.at(i)->descriptors());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inverted index on (vocabulary)
|
||||
sessionModified_ = true;
|
||||
QTime time;
|
||||
time.start();
|
||||
bool incremental = Settings::getGeneral_vocabularyIncremental() && !Settings::getGeneral_vocabularyFixed();
|
||||
if(incremental)
|
||||
{
|
||||
UINFO("Creating incremental vocabulary...");
|
||||
}
|
||||
else if(Settings::getGeneral_vocabularyFixed())
|
||||
{
|
||||
UINFO("Updating vocabulary correspondences only (vocabulary is fixed)...");
|
||||
}
|
||||
else
|
||||
{
|
||||
UINFO("Creating vocabulary...");
|
||||
}
|
||||
QTime localTime;
|
||||
localTime.start();
|
||||
int updateVocabularyMinWords = Settings::getGeneral_vocabularyUpdateMinWords();
|
||||
int addedWords = 0;
|
||||
for(int i=0; i<objectsList.size(); ++i)
|
||||
{
|
||||
objectsDescriptors_.insert(objectsList.at(i)->id(), objectsList.at(i)->descriptors());
|
||||
QMultiMap<int, int> words = vocabulary_->addWords(objectsList[i]->descriptors(), objectsList.at(i)->id());
|
||||
objectsList[i]->setWords(words);
|
||||
addedWords += words.uniqueKeys().size();
|
||||
bool updated = false;
|
||||
if(incremental && addedWords && addedWords >= updateVocabularyMinWords)
|
||||
{
|
||||
vocabulary_->update();
|
||||
addedWords = 0;
|
||||
updated = true;
|
||||
}
|
||||
UINFO("Object %d, %d words from %d descriptors (%d words, %d ms) %s",
|
||||
objectsList[i]->id(),
|
||||
words.uniqueKeys().size(),
|
||||
objectsList[i]->descriptors().rows,
|
||||
vocabulary_->size(),
|
||||
localTime.restart(),
|
||||
updated?"updated":"");
|
||||
}
|
||||
if(addedWords && !Settings::getGeneral_vocabularyFixed())
|
||||
{
|
||||
vocabulary_->update();
|
||||
}
|
||||
|
||||
if(incremental)
|
||||
{
|
||||
UINFO("Creating incremental vocabulary... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed());
|
||||
}
|
||||
else if(Settings::getGeneral_vocabularyFixed())
|
||||
{
|
||||
UINFO("Updating vocabulary correspondences only (vocabulary is fixed)... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed());
|
||||
}
|
||||
else
|
||||
{
|
||||
UINFO("Creating vocabulary... done! size=%d (%d ms)", vocabulary_->size(), time.elapsed());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1202,6 +1253,7 @@ bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info
|
||||
words = vocabulary_->addWords(info.sceneDescriptors_, -1);
|
||||
vocabulary_->update();
|
||||
info.timeStamps_.insert(DetectionInfo::kTimeIndexing, time.restart());
|
||||
info.sceneWords_ = words;
|
||||
}
|
||||
|
||||
for(QMap<int, ObjSignature*>::iterator iter=objects_.begin(); iter!=objects_.end(); ++iter)
|
||||
@@ -1274,9 +1326,10 @@ bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info
|
||||
|
||||
if(matched)
|
||||
{
|
||||
int wordId = results.at<int>(i,0);
|
||||
if(Settings::getGeneral_invertedSearch())
|
||||
{
|
||||
int wordId = results.at<int>(i,0);
|
||||
info.sceneWords_.insertMulti(wordId, i);
|
||||
QList<int> objIds = vocabulary_->wordToObjects().values(wordId);
|
||||
for(int j=0; j<objIds.size(); ++j)
|
||||
{
|
||||
@@ -1294,7 +1347,6 @@ bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info
|
||||
int fisrtObjectDescriptorIndex = (iter == dataRange_.begin())?0:(--iter).key()+1;
|
||||
int objectDescriptorIndex = i - fisrtObjectDescriptorIndex;
|
||||
|
||||
int wordId = results.at<int>(i,0);
|
||||
if(words.count(wordId) == 1)
|
||||
{
|
||||
info.matches_.find(objectId).value().insert(objectDescriptorIndex, words.value(wordId));
|
||||
|
||||
+13
-4
@@ -33,11 +33,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
namespace find_object {
|
||||
|
||||
KeypointItem::KeypointItem(int id, qreal x, qreal y, int r, const QString & info, const QColor & color, QGraphicsItem * parent) :
|
||||
KeypointItem::KeypointItem(int id, qreal x, qreal y, int r, const cv::KeyPoint & kpt, int wordID, const QColor & color, QGraphicsItem * parent) :
|
||||
QGraphicsEllipseItem(x, y, r, r, parent),
|
||||
info_(info),
|
||||
placeHolder_(0),
|
||||
id_(id)
|
||||
id_(id),
|
||||
kpt_(kpt),
|
||||
wordID_(wordID)
|
||||
{
|
||||
this->setPen(QPen(color));
|
||||
this->setBrush(QBrush(color));
|
||||
@@ -70,13 +71,21 @@ void KeypointItem::showDescription()
|
||||
{
|
||||
if(!placeHolder_)
|
||||
{
|
||||
QString info = QString( "Keypoint = %1\n"
|
||||
"Word = %2\n"
|
||||
"Response = %3\n"
|
||||
"Angle = %4\n"
|
||||
"X = %5\n"
|
||||
"Y = %6\n"
|
||||
"Size = %7").arg(id_).arg(wordID_).arg(kpt_.response).arg(kpt_.angle).arg(kpt_.pt.x).arg(kpt_.pt.y).arg(kpt_.size);
|
||||
|
||||
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_);
|
||||
text->setPlainText(info);
|
||||
placeHolder_->setRect(text->boundingRect());
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -32,16 +32,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <QtGui/QGraphicsTextItem>
|
||||
#include <QtGui/QPen>
|
||||
#include <QtGui/QBrush>
|
||||
#include <opencv2/features2d/features2d.hpp>
|
||||
|
||||
namespace find_object {
|
||||
|
||||
class KeypointItem : public QGraphicsEllipseItem
|
||||
{
|
||||
public:
|
||||
KeypointItem(int id, qreal x, qreal y, int r, const QString & info, const QColor & color = Qt::green, QGraphicsItem * parent = 0);
|
||||
KeypointItem(int id, qreal x, qreal y, int r, const cv::KeyPoint & kpt, int wordID = -1, const QColor & color = Qt::green, QGraphicsItem * parent = 0);
|
||||
virtual ~KeypointItem();
|
||||
|
||||
void setColor(const QColor & color);
|
||||
void setWordID(int id) {wordID_ = id;}
|
||||
int id() const {return id_;}
|
||||
|
||||
protected:
|
||||
@@ -55,9 +57,10 @@ private:
|
||||
void hideDescription();
|
||||
|
||||
private:
|
||||
QString info_;
|
||||
QGraphicsRectItem * placeHolder_;
|
||||
int id_;
|
||||
cv::KeyPoint kpt_;
|
||||
int wordID_;
|
||||
};
|
||||
|
||||
} // namespace find_object
|
||||
|
||||
+69
-27
@@ -183,7 +183,7 @@ MainWindow::MainWindow(FindObject * findObject, Camera * camera, QWidget * paren
|
||||
|
||||
//buttons
|
||||
connect(ui_->pushButton_restoreDefaults, SIGNAL(clicked()), ui_->toolBox, SLOT(resetCurrentPage()));
|
||||
connect(ui_->pushButton_updateObjects, SIGNAL(clicked()), this, SLOT(updateObjects()));
|
||||
connect(ui_->pushButton_updateObjects, SIGNAL(clicked()), this, SLOT(updateObjects(const QList<int> &)));
|
||||
connect(ui_->horizontalSlider_objectsSize, SIGNAL(valueChanged(int)), this, SLOT(updateObjectsSize()));
|
||||
|
||||
ui_->actionStop_camera->setEnabled(false);
|
||||
@@ -247,7 +247,7 @@ MainWindow::MainWindow(FindObject * findObject, Camera * camera, QWidget * paren
|
||||
iter!=findObject_->objects().constEnd();
|
||||
++iter)
|
||||
{
|
||||
ObjWidget * obj = new ObjWidget(iter.key(), iter.value()->keypoints(), cvtCvMat2QImage(iter.value()->image()));
|
||||
ObjWidget * obj = new ObjWidget(iter.key(), iter.value()->keypoints(), iter.value()->words(), cvtCvMat2QImage(iter.value()->image()));
|
||||
objWidgets_.insert(obj->id(), obj);
|
||||
this->showObject(obj);
|
||||
}
|
||||
@@ -366,7 +366,7 @@ void MainWindow::loadSession()
|
||||
{
|
||||
if(iter.value())
|
||||
{
|
||||
ObjWidget * obj = new ObjWidget(iter.key(), iter.value()->keypoints(), cvtCvMat2QImage(iter.value()->image()));
|
||||
ObjWidget * obj = new ObjWidget(iter.key(), iter.value()->keypoints(), iter.value()->words(), cvtCvMat2QImage(iter.value()->image()));
|
||||
objWidgets_.insert(obj->id(), obj);
|
||||
ui_->actionSave_objects->setEnabled(true);
|
||||
ui_->actionSave_session->setEnabled(true);
|
||||
@@ -714,7 +714,9 @@ void MainWindow::addObjectFromScene()
|
||||
ui_->actionSave_objects->setEnabled(true);
|
||||
ui_->actionSave_session->setEnabled(true);
|
||||
showObject(obj);
|
||||
updateVocabulary();
|
||||
QList<int> ids;
|
||||
ids.push_back(obj->id());
|
||||
updateVocabulary(ids);
|
||||
objectsModified_ = true;
|
||||
}
|
||||
if(resumeCamera || sceneImage_.empty())
|
||||
@@ -764,7 +766,7 @@ int MainWindow::addObjectFromFile(const QString & filePath)
|
||||
const ObjSignature * s = findObject_->addObject(filePath);
|
||||
if(s)
|
||||
{
|
||||
ObjWidget * obj = new ObjWidget(s->id(), std::vector<cv::KeyPoint>(), cvtCvMat2QImage(s->image()));
|
||||
ObjWidget * obj = new ObjWidget(s->id(), std::vector<cv::KeyPoint>(), QMultiMap<int,int>(), cvtCvMat2QImage(s->image()));
|
||||
objWidgets_.insert(obj->id(), obj);
|
||||
ui_->actionSave_objects->setEnabled(true);
|
||||
ui_->actionSave_session->setEnabled(true);
|
||||
@@ -787,7 +789,7 @@ void MainWindow::addObjectFromTcp(const cv::Mat & image, int id, const QString &
|
||||
const ObjSignature * s = findObject_->addObject(image, id, filePath);
|
||||
if(s)
|
||||
{
|
||||
ObjWidget * obj = new ObjWidget(s->id(), std::vector<cv::KeyPoint>(), cvtCvMat2QImage(s->image()));
|
||||
ObjWidget * obj = new ObjWidget(s->id(), std::vector<cv::KeyPoint>(), QMultiMap<int,int>(), cvtCvMat2QImage(s->image()));
|
||||
objWidgets_.insert(obj->id(), obj);
|
||||
ui_->actionSave_objects->setEnabled(true);
|
||||
ui_->actionSave_session->setEnabled(true);
|
||||
@@ -977,21 +979,24 @@ void MainWindow::showObject(ObjWidget * obj)
|
||||
|
||||
void MainWindow::updateObjects(const QList<int> & ids)
|
||||
{
|
||||
if(ids.size())
|
||||
if(objWidgets_.size())
|
||||
{
|
||||
this->statusBar()->showMessage(tr("Updating %1 objects...").arg(ids.size()));
|
||||
this->statusBar()->showMessage(tr("Updating %1 objects...").arg(ids.size()==0?objWidgets_.size():ids.size()));
|
||||
|
||||
findObject_->updateObjects(ids);
|
||||
|
||||
updateVocabulary();
|
||||
QList<int> idsTmp = ids;
|
||||
if(idsTmp.size() == 0)
|
||||
{
|
||||
idsTmp = objWidgets_.keys();
|
||||
}
|
||||
|
||||
QList<ObjSignature*> signatures = findObject_->objects().values();
|
||||
for(int i=0; i<signatures.size(); ++i)
|
||||
{
|
||||
if(ids.contains(signatures[i]->id()))
|
||||
if(idsTmp.contains(signatures[i]->id()))
|
||||
{
|
||||
QImage qtImage = cvtCvMat2QImage(signatures[i]->image());
|
||||
objWidgets_.value(signatures[i]->id())->setData(signatures[i]->keypoints(), qtImage, signatures[i]->rect());
|
||||
objWidgets_.value(signatures[i]->id())->updateData(signatures[i]->keypoints());
|
||||
|
||||
//update object labels
|
||||
QLabel * title = qFindChild<QLabel*>(this, QString("%1title").arg(signatures[i]->id()));
|
||||
@@ -999,6 +1004,8 @@ void MainWindow::updateObjects(const QList<int> & ids)
|
||||
}
|
||||
}
|
||||
|
||||
updateVocabulary(ids);
|
||||
|
||||
if(!camera_->isRunning() && !sceneImage_.empty())
|
||||
{
|
||||
this->update(sceneImage_);
|
||||
@@ -1007,23 +1014,34 @@ void MainWindow::updateObjects(const QList<int> & ids)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateObjects()
|
||||
{
|
||||
updateObjects(objWidgets_.keys());
|
||||
}
|
||||
|
||||
void MainWindow::updateVocabulary()
|
||||
void MainWindow::updateVocabulary(const QList<int> & ids)
|
||||
{
|
||||
this->statusBar()->showMessage(tr("Updating vocabulary..."));
|
||||
|
||||
QTime time;
|
||||
time.start();
|
||||
findObject_->updateVocabulary();
|
||||
findObject_->updateVocabulary(ids);
|
||||
|
||||
if(findObject_->vocabulary()->size())
|
||||
QList<int> idsTmp = ids;
|
||||
if(idsTmp.size() == 0)
|
||||
{
|
||||
ui_->label_timeIndexing->setNum(time.elapsed());
|
||||
ui_->label_vocabularySize->setNum(findObject_->vocabulary()->size());
|
||||
idsTmp = objWidgets_.keys();
|
||||
}
|
||||
QList<ObjSignature*> signatures = findObject_->objects().values();
|
||||
for(int i=0; i<signatures.size(); ++i)
|
||||
{
|
||||
if(idsTmp.contains(signatures[i]->id()))
|
||||
{
|
||||
objWidgets_.value(signatures[i]->id())->updateWords(signatures[i]->words());
|
||||
}
|
||||
}
|
||||
|
||||
ui_->label_timeIndexing->setNum(time.elapsed());
|
||||
ui_->label_vocabularySize->setNum(findObject_->vocabulary()->size());
|
||||
if(ids.size() && findObject_->vocabulary()->size() == 0 && Settings::getGeneral_vocabularyFixed() && Settings::getGeneral_invertedSearch())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Vocabulary update"), tr("\"General/VocabularyFixed=true\" and the "
|
||||
"vocabulary is empty. New features cannot be matched to any words in the vocabulary."));
|
||||
}
|
||||
lastObjectsUpdateParameters_ = Settings::getParameters();
|
||||
this->statusBar()->clearMessage();
|
||||
@@ -1172,6 +1190,10 @@ void MainWindow::update(const cv::Mat & image)
|
||||
for(QMap<int, ObjWidget*>::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter)
|
||||
{
|
||||
iter.value()->resetKptsColor();
|
||||
if(!Settings::getGeneral_invertedSearch())
|
||||
{
|
||||
iter.value()->resetKptsWordID();
|
||||
}
|
||||
}
|
||||
|
||||
QTime guiRefreshTime;
|
||||
@@ -1184,7 +1206,8 @@ void MainWindow::update(const cv::Mat & image)
|
||||
ui_->label_timeSkewAffine->setNum(info.timeStamps_.value(DetectionInfo::kTimeSkewAffine, 0));
|
||||
ui_->label_timeExtraction->setNum(info.timeStamps_.value(DetectionInfo::kTimeDescriptorExtraction, 0));
|
||||
ui_->label_timeSubPix->setNum(info.timeStamps_.value(DetectionInfo::kTimeSubPixelRefining, 0));
|
||||
ui_->imageView_source->setData(info.sceneKeypoints_, cvtCvMat2QImage(sceneImage_));
|
||||
ui_->imageView_source->updateImage(cvtCvMat2QImage(sceneImage_));
|
||||
ui_->imageView_source->updateData(info.sceneKeypoints_, info.sceneWords_);
|
||||
if(!findObject_->vocabulary()->size())
|
||||
{
|
||||
ui_->label_timeIndexing->setNum(info.timeStamps_.value(DetectionInfo::kTimeIndexing, 0));
|
||||
@@ -1221,6 +1244,10 @@ void MainWindow::update(const cv::Mat & image)
|
||||
{
|
||||
obj->setKptColor(iter.key(), obj->color());
|
||||
ui_->imageView_source->setKptColor(iter.value(), obj->color());
|
||||
if(!Settings::getGeneral_invertedSearch())
|
||||
{
|
||||
obj->setKptWordID(iter.key(), ui_->imageView_source->words().value(iter.value(), -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!info.objDetected_.contains(id))
|
||||
@@ -1263,6 +1290,8 @@ void MainWindow::update(const cv::Mat & image)
|
||||
}
|
||||
|
||||
// Add homography rectangles when homographies are computed
|
||||
int maxHomographyScoreId = -1;
|
||||
int maxHomographyScore = 0;
|
||||
QMultiMap<int, QMultiMap<int,int> >::const_iterator inliersIter = info.objDetectedInliers_.constBegin();
|
||||
QMultiMap<int, QMultiMap<int,int> >::const_iterator outliersIter = info.objDetectedOutliers_.constBegin();
|
||||
for(QMultiMap<int,QTransform>::iterator iter = info.objDetected_.begin();
|
||||
@@ -1270,6 +1299,13 @@ void MainWindow::update(const cv::Mat & image)
|
||||
++iter, ++inliersIter, ++outliersIter)
|
||||
{
|
||||
int id = iter.key();
|
||||
|
||||
if(maxHomographyScoreId == -1 || maxHomographyScore < inliersIter.value().size())
|
||||
{
|
||||
maxHomographyScoreId = id;
|
||||
maxHomographyScore = inliersIter.value().size();
|
||||
}
|
||||
|
||||
ObjWidget * obj = objWidgets_.value(id);
|
||||
UASSERT(obj != 0);
|
||||
|
||||
@@ -1294,6 +1330,10 @@ void MainWindow::update(const cv::Mat & image)
|
||||
{
|
||||
obj->setKptColor(iter.key(), obj->color());
|
||||
ui_->imageView_source->setKptColor(iter.value(), obj->color());
|
||||
if(!Settings::getGeneral_invertedSearch())
|
||||
{
|
||||
obj->setKptWordID(iter.key(), ui_->imageView_source->words().value(iter.value(), -1));
|
||||
}
|
||||
}
|
||||
|
||||
QLabel * label = ui_->dockWidget_objects->findChild<QLabel*>(QString("%1detection").arg(id));
|
||||
@@ -1339,9 +1379,9 @@ void MainWindow::update(const cv::Mat & image)
|
||||
ui_->label_maxMatchedDistance->setNum(info.maxMatchedDistance_);
|
||||
|
||||
//Scroll objects slider to the best score
|
||||
if(maxScoreId>=0 && Settings::getGeneral_autoScroll())
|
||||
if((maxScoreId>=0 || maxHomographyScoreId>=0) && Settings::getGeneral_autoScroll())
|
||||
{
|
||||
QLabel * label = ui_->dockWidget_objects->findChild<QLabel*>(QString("%1title").arg(maxScoreId));
|
||||
QLabel * label = ui_->dockWidget_objects->findChild<QLabel*>(QString("%1title").arg(maxHomographyScoreId>=0?maxHomographyScoreId:maxScoreId));
|
||||
if(label)
|
||||
{
|
||||
ui_->objects_area->verticalScrollBar()->setValue(label->pos().y());
|
||||
@@ -1385,7 +1425,8 @@ void MainWindow::update(const cv::Mat & image)
|
||||
ui_->label_timeSkewAffine->setNum(info.timeStamps_.value(DetectionInfo::kTimeSkewAffine, 0));
|
||||
ui_->label_timeExtraction->setNum(info.timeStamps_.value(DetectionInfo::kTimeDescriptorExtraction, 0));
|
||||
ui_->label_timeSubPix->setNum(info.timeStamps_.value(DetectionInfo::kTimeSubPixelRefining, 0));
|
||||
ui_->imageView_source->setData(info.sceneKeypoints_, cvtCvMat2QImage(sceneImage_));
|
||||
ui_->imageView_source->updateImage(cvtCvMat2QImage(sceneImage_));
|
||||
ui_->imageView_source->updateData(info.sceneKeypoints_, info.sceneWords_);
|
||||
}
|
||||
|
||||
|
||||
@@ -1454,6 +1495,7 @@ void MainWindow::notifyParametersChanged(const QStringList & paramChanged)
|
||||
else if( (iter->contains("NearestNeighbor") && Settings::getGeneral_invertedSearch()) ||
|
||||
iter->compare(Settings::kGeneral_invertedSearch()) == 0 ||
|
||||
(iter->compare(Settings::kGeneral_vocabularyIncremental()) == 0 && Settings::getGeneral_invertedSearch()) ||
|
||||
(iter->compare(Settings::kGeneral_vocabularyFixed()) == 0 && Settings::getGeneral_invertedSearch()) ||
|
||||
(iter->compare(Settings::kGeneral_threads()) == 0 && !Settings::getGeneral_invertedSearch()) )
|
||||
{
|
||||
nearestNeighborParamsChanged = true;
|
||||
@@ -1478,7 +1520,7 @@ void MainWindow::notifyParametersChanged(const QStringList & paramChanged)
|
||||
{
|
||||
if(detectorDescriptorParamsChanged)
|
||||
{
|
||||
this->updateObjects(objWidgets_.keys());
|
||||
this->updateObjects();
|
||||
}
|
||||
else if(nearestNeighborParamsChanged)
|
||||
{
|
||||
|
||||
+44
-18
@@ -65,7 +65,7 @@ ObjWidget::ObjWidget(QWidget * parent) :
|
||||
{
|
||||
setupUi();
|
||||
}
|
||||
ObjWidget::ObjWidget(int id, const std::vector<cv::KeyPoint> & keypoints, const QImage & image, QWidget * parent) :
|
||||
ObjWidget::ObjWidget(int id, const std::vector<cv::KeyPoint> & keypoints, const QMultiMap<int,int> & words, const QImage & image, QWidget * parent) :
|
||||
QWidget(parent),
|
||||
id_(id),
|
||||
graphicsView_(0),
|
||||
@@ -74,7 +74,8 @@ ObjWidget::ObjWidget(int id, const std::vector<cv::KeyPoint> & keypoints, const
|
||||
color_(QColor((Qt::GlobalColor)((id % 11 + 7)==Qt::yellow?Qt::gray:(id % 11 + 7))))
|
||||
{
|
||||
setupUi();
|
||||
this->setData(keypoints, image, image.rect());
|
||||
this->updateImage(image);
|
||||
this->updateData(keypoints, words);
|
||||
}
|
||||
ObjWidget::~ObjWidget()
|
||||
{
|
||||
@@ -264,29 +265,42 @@ void ObjWidget::setTextLabel(const QString & text)
|
||||
label_->setText(text);
|
||||
}
|
||||
|
||||
void ObjWidget::setData(const std::vector<cv::KeyPoint> & keypoints, const QImage & image, const QRect & rect)
|
||||
void ObjWidget::updateImage(const QImage & image)
|
||||
{
|
||||
pixmap_ = QPixmap::fromImage(image);
|
||||
rect_ = pixmap_.rect();
|
||||
label_->setVisible(image.isNull());
|
||||
}
|
||||
void ObjWidget::updateData(const std::vector<cv::KeyPoint> & keypoints, const QMultiMap<int, int> & words)
|
||||
{
|
||||
keypoints_ = keypoints;
|
||||
kptColors_ = QVector<QColor>((int)keypoints.size(), defaultColor());
|
||||
keypointItems_.clear();
|
||||
rectItems_.clear();
|
||||
this->updateWords(words);
|
||||
graphicsView_->scene()->clear();
|
||||
graphicsViewInitialized_ = false;
|
||||
mouseCurrentPos_ = mousePressedPos_; // this will reset roi selection
|
||||
|
||||
pixmap_ = QPixmap::fromImage(image);
|
||||
rect_ = rect;
|
||||
if(rect_.isNull())
|
||||
{
|
||||
rect_ = pixmap_.rect();
|
||||
}
|
||||
//this->setMinimumSize(image_.size());
|
||||
|
||||
if(graphicsViewMode_->isChecked())
|
||||
{
|
||||
this->setupGraphicsView();
|
||||
}
|
||||
label_->setVisible(image.isNull());
|
||||
}
|
||||
|
||||
void ObjWidget::updateWords(const QMultiMap<int,int> & words)
|
||||
{
|
||||
words_.clear();
|
||||
for(QMultiMap<int,int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
|
||||
{
|
||||
words_.insert(iter.value(), iter.key());
|
||||
}
|
||||
for(int i=0; i<keypointItems_.size(); ++i)
|
||||
{
|
||||
keypointItems_[i]->setWordID(words_.value(i,-1));
|
||||
}
|
||||
}
|
||||
|
||||
void ObjWidget::resetKptsColor()
|
||||
@@ -303,6 +317,15 @@ void ObjWidget::resetKptsColor()
|
||||
rectItems_.clear();
|
||||
}
|
||||
|
||||
void ObjWidget::resetKptsWordID()
|
||||
{
|
||||
words_.clear();
|
||||
for(int i=0; i<keypointItems_.size(); ++i)
|
||||
{
|
||||
keypointItems_[i]->setWordID(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjWidget::setKptColor(int index, const QColor & color)
|
||||
{
|
||||
if(index < kptColors_.size())
|
||||
@@ -325,6 +348,15 @@ void ObjWidget::setKptColor(int index, const QColor & color)
|
||||
}
|
||||
}
|
||||
|
||||
void ObjWidget::setKptWordID(int index, int wordID)
|
||||
{
|
||||
words_.insert(index, wordID);
|
||||
if(index < keypointItems_.size())
|
||||
{
|
||||
keypointItems_.at(index)->setWordID(wordID);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjWidget::addRect(QGraphicsRectItem * rect)
|
||||
{
|
||||
if(graphicsViewInitialized_)
|
||||
@@ -701,14 +733,8 @@ void ObjWidget::drawKeypoints(QPainter * painter)
|
||||
QColor color(kptColors_.at(i).red(), kptColors_.at(i).green(), kptColors_.at(i).blue(), alpha_);
|
||||
if(graphicsViewMode_->isChecked())
|
||||
{
|
||||
QString info = QString( "ID = %1\n"
|
||||
"Response = %2\n"
|
||||
"Angle = %3\n"
|
||||
"X = %4\n"
|
||||
"Y = %5\n"
|
||||
"Size = %6").arg(i+1).arg(r.response).arg(r.angle).arg(r.pt.x).arg(r.pt.y).arg(r.size);
|
||||
// YELLOW = NEW and multiple times
|
||||
item = new KeypointItem(i+1, r.pt.x-radius, r.pt.y-radius, radius*2, info, color);
|
||||
item = new KeypointItem(i, r.pt.x-radius, r.pt.y-radius, radius*2, r, words_.value(i, -1), color);
|
||||
item->setVisible(this->isFeaturesShown());
|
||||
item->setZValue(2);
|
||||
graphicsView_->scene()->addItem(item);
|
||||
@@ -743,7 +769,7 @@ std::vector<cv::KeyPoint> ObjWidget::selectedKeypoints() const
|
||||
{
|
||||
if(qgraphicsitem_cast<KeypointItem*>(items.at(i)))
|
||||
{
|
||||
selected.push_back(keypoints_.at(((KeypointItem*)items.at(i))->id()-1)); // ids start at 1
|
||||
selected.push_back(keypoints_.at(((KeypointItem*)items.at(i))->id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ public:
|
||||
void update();
|
||||
void search(const cv::Mat & descriptors, cv::Mat & results, cv::Mat & dists, int k);
|
||||
int size() const {return indexedDescriptors_.rows + notIndexedDescriptors_.rows;}
|
||||
int dim() const {return !indexedDescriptors_.empty()?indexedDescriptors_.cols:notIndexedDescriptors_.cols;}
|
||||
int type() const {return !indexedDescriptors_.empty()?indexedDescriptors_.type():notIndexedDescriptors_.type();}
|
||||
const QMultiMap<int, int> & wordToObjects() const {return wordToObjects_;}
|
||||
const cv::Mat & indexedDescriptors() const {return indexedDescriptors_;}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user