Added "save/load session" menu actions.
git-svn-id: http://find-object.googlecode.com/svn/trunk/find_object@418 620bd6b2-0a58-f614-fd9a-1bd335dccda9
This commit is contained in:
parent
84166e6ddc
commit
02e31c2e69
@ -65,6 +65,9 @@ public:
|
|||||||
FindObject(QObject * parent = 0);
|
FindObject(QObject * parent = 0);
|
||||||
virtual ~FindObject();
|
virtual ~FindObject();
|
||||||
|
|
||||||
|
bool loadSession(const QString & path);
|
||||||
|
bool saveSession(const QString & path) const;
|
||||||
|
|
||||||
int loadObjects(const QString & dirPath); // call updateObjects()
|
int loadObjects(const QString & dirPath); // call updateObjects()
|
||||||
const ObjSignature * addObject(const QString & filePath);
|
const ObjSignature * addObject(const QString & filePath);
|
||||||
const ObjSignature * addObject(const cv::Mat & image, int id=0, const QString & filename = QString());
|
const ObjSignature * addObject(const cv::Mat & image, int id=0, const QString & filename = QString());
|
||||||
|
|||||||
@ -81,6 +81,8 @@ public Q_SLOTS:
|
|||||||
void update(const cv::Mat & image);
|
void update(const cv::Mat & image);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
void loadSession();
|
||||||
|
void saveSession();
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
void loadObjects();
|
void loadObjects();
|
||||||
@ -110,7 +112,7 @@ Q_SIGNALS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool loadSettings(const QString & path);
|
bool loadSettings(const QString & path);
|
||||||
bool saveSettings(const QString & path);
|
bool saveSettings(const QString & path) const;
|
||||||
int loadObjects(const QString & dirPath);
|
int loadObjects(const QString & dirPath);
|
||||||
int saveObjects(const QString & dirPath);
|
int saveObjects(const QString & dirPath);
|
||||||
void setupTCPServer();
|
void setupTCPServer();
|
||||||
|
|||||||
@ -358,7 +358,7 @@ void AddObjectDialog::setState(int state)
|
|||||||
objSignature_ = 0;
|
objSignature_ = 0;
|
||||||
}
|
}
|
||||||
objSignature_ = new ObjSignature(0, imgRoi.clone(), "");
|
objSignature_ = new ObjSignature(0, imgRoi.clone(), "");
|
||||||
objSignature_->setData(keypoints, descriptors, Settings::currentDetectorType(), Settings::currentDescriptorType());
|
objSignature_->setData(keypoints, descriptors);
|
||||||
objWidget_ = new ObjWidget(0, keypoints, cvtCvMat2QImage(imgRoi.clone()));
|
objWidget_ = new ObjWidget(0, keypoints, cvtCvMat2QImage(imgRoi.clone()));
|
||||||
|
|
||||||
this->accept();
|
this->accept();
|
||||||
|
|||||||
@ -59,6 +59,85 @@ FindObject::~FindObject() {
|
|||||||
objectsDescriptors_.clear();
|
objectsDescriptors_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FindObject::loadSession(const QString & path)
|
||||||
|
{
|
||||||
|
if(QFile::exists(path) && !path.isEmpty() && QFileInfo(path).suffix().compare("bin") == 0)
|
||||||
|
{
|
||||||
|
QFile file(path);
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
QDataStream in(&file);
|
||||||
|
|
||||||
|
ParametersMap parameters;
|
||||||
|
|
||||||
|
// load parameters
|
||||||
|
in >> parameters;
|
||||||
|
for(QMap<QString, QVariant>::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
|
||||||
|
{
|
||||||
|
Settings::setParameter(iter.key(), iter.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// save vocabulary
|
||||||
|
vocabulary_->load(in);
|
||||||
|
|
||||||
|
// load objects
|
||||||
|
while(!in.atEnd())
|
||||||
|
{
|
||||||
|
ObjSignature * obj = new ObjSignature();
|
||||||
|
obj->load(in);
|
||||||
|
if(obj->id() >= 0)
|
||||||
|
{
|
||||||
|
objects_.insert(obj->id(), obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("Failed to load and object!");
|
||||||
|
delete obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if(!Settings::getGeneral_invertedSearch())
|
||||||
|
{
|
||||||
|
// this will fill objectsDescriptors_ matrix
|
||||||
|
updateVocabulary();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("Invalid session file (should be *.bin): \"%s\"", path.toStdString().c_str());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindObject::saveSession(const QString & path) const
|
||||||
|
{
|
||||||
|
if(!path.isEmpty() && QFileInfo(path).suffix().compare("bin") == 0)
|
||||||
|
{
|
||||||
|
QFile file(path);
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
QDataStream out(&file);
|
||||||
|
|
||||||
|
// save parameters
|
||||||
|
out << Settings::getParameters();
|
||||||
|
|
||||||
|
// save vocabulary
|
||||||
|
vocabulary_->save(out);
|
||||||
|
|
||||||
|
// save objects
|
||||||
|
for(QMultiMap<int, ObjSignature*>::const_iterator iter=objects_.constBegin(); iter!=objects_.constEnd(); ++iter)
|
||||||
|
{
|
||||||
|
iter.value()->save(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
UERROR("Path \"%s\" not valid (should be *.bin)", path.toStdString().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int FindObject::loadObjects(const QString & dirPath)
|
int FindObject::loadObjects(const QString & dirPath)
|
||||||
{
|
{
|
||||||
int loadedObjects = 0;
|
int loadedObjects = 0;
|
||||||
@ -143,7 +222,6 @@ bool FindObject::addObject(ObjSignature * obj)
|
|||||||
Settings::setGeneral_nextObjID(obj->id()+1);
|
Settings::setGeneral_nextObjID(obj->id()+1);
|
||||||
|
|
||||||
objects_.insert(obj->id(), obj);
|
objects_.insert(obj->id(), obj);
|
||||||
clearVocabulary();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -512,11 +590,7 @@ void FindObject::updateObjects()
|
|||||||
|
|
||||||
int id = threads[j]->objectId();
|
int id = threads[j]->objectId();
|
||||||
|
|
||||||
objects_.value(id)->setData(
|
objects_.value(id)->setData(threads[j]->keypoints(), threads[j]->descriptors());
|
||||||
threads[j]->keypoints(),
|
|
||||||
threads[j]->descriptors(),
|
|
||||||
Settings::currentDetectorType(),
|
|
||||||
Settings::currentDescriptorType());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UINFO("Features extraction from %d objects... done! (%d ms)", objects_.size(), time.elapsed());
|
UINFO("Features extraction from %d objects... done! (%d ms)", objects_.size(), time.elapsed());
|
||||||
@ -915,13 +989,22 @@ bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info
|
|||||||
bool consistentNNData = (vocabulary_->size()!=0 && vocabulary_->wordToObjects().begin().value()!=-1 && Settings::getGeneral_invertedSearch()) ||
|
bool consistentNNData = (vocabulary_->size()!=0 && vocabulary_->wordToObjects().begin().value()!=-1 && Settings::getGeneral_invertedSearch()) ||
|
||||||
((vocabulary_->size()==0 || vocabulary_->wordToObjects().begin().value()==-1) && !Settings::getGeneral_invertedSearch());
|
((vocabulary_->size()==0 || vocabulary_->wordToObjects().begin().value()==-1) && !Settings::getGeneral_invertedSearch());
|
||||||
|
|
||||||
|
bool descriptorsValid = !Settings::getGeneral_invertedSearch() &&
|
||||||
|
!objectsDescriptors_.empty() &&
|
||||||
|
objectsDescriptors_.begin().value().cols == info.sceneDescriptors_.cols &&
|
||||||
|
objectsDescriptors_.begin().value().type() == info.sceneDescriptors_.type();
|
||||||
|
|
||||||
|
bool vocabularyValid = Settings::getGeneral_invertedSearch() &&
|
||||||
|
vocabulary_->size() &&
|
||||||
|
!vocabulary_->indexedDescriptors().empty() &&
|
||||||
|
vocabulary_->indexedDescriptors().cols == info.sceneDescriptors_.cols &&
|
||||||
|
vocabulary_->indexedDescriptors().type() == info.sceneDescriptors_.type();
|
||||||
|
|
||||||
// COMPARE
|
// COMPARE
|
||||||
UDEBUG("COMPARE");
|
UDEBUG("COMPARE");
|
||||||
if(!objectsDescriptors_.empty() &&
|
if((descriptorsValid || vocabularyValid) &&
|
||||||
info.sceneKeypoints_.size() &&
|
info.sceneKeypoints_.size() &&
|
||||||
consistentNNData &&
|
consistentNNData)
|
||||||
objectsDescriptors_.begin().value().cols == info.sceneDescriptors_.cols &&
|
|
||||||
objectsDescriptors_.begin().value().type() == info.sceneDescriptors_.type()) // binary descriptor issue, if the dataTree is not yet updated with modified settings
|
|
||||||
{
|
{
|
||||||
success = true;
|
success = true;
|
||||||
QTime time;
|
QTime time;
|
||||||
@ -1243,7 +1326,7 @@ bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info
|
|||||||
info.timeStamps_.insert(DetectionInfo::kTimeHomography, time.restart());
|
info.timeStamps_.insert(DetectionInfo::kTimeHomography, time.restart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!objectsDescriptors_.empty() && info.sceneKeypoints_.size())
|
else if((descriptorsValid || vocabularyValid) && info.sceneKeypoints_.size())
|
||||||
{
|
{
|
||||||
UWARN("Cannot search, objects must be updated");
|
UWARN("Cannot search, objects must be updated");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -181,6 +181,7 @@ MainWindow::MainWindow(FindObject * findObject, Camera * camera, QWidget * paren
|
|||||||
ui_->actionStop_camera->setEnabled(false);
|
ui_->actionStop_camera->setEnabled(false);
|
||||||
ui_->actionPause_camera->setEnabled(false);
|
ui_->actionPause_camera->setEnabled(false);
|
||||||
ui_->actionSave_objects->setEnabled(false);
|
ui_->actionSave_objects->setEnabled(false);
|
||||||
|
ui_->actionSave_session->setEnabled(false);
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
connect(ui_->actionAdd_object_from_scene, SIGNAL(triggered()), this, SLOT(addObjectFromScene()));
|
connect(ui_->actionAdd_object_from_scene, SIGNAL(triggered()), this, SLOT(addObjectFromScene()));
|
||||||
@ -200,6 +201,8 @@ MainWindow::MainWindow(FindObject * findObject, Camera * camera, QWidget * paren
|
|||||||
connect(ui_->actionRemove_all_objects, SIGNAL(triggered()), this, SLOT(removeAllObjects()));
|
connect(ui_->actionRemove_all_objects, SIGNAL(triggered()), this, SLOT(removeAllObjects()));
|
||||||
connect(ui_->actionSave_settings, SIGNAL(triggered()), this, SLOT(saveSettings()));
|
connect(ui_->actionSave_settings, SIGNAL(triggered()), this, SLOT(saveSettings()));
|
||||||
connect(ui_->actionLoad_settings, SIGNAL(triggered()), this, SLOT(loadSettings()));
|
connect(ui_->actionLoad_settings, SIGNAL(triggered()), this, SLOT(loadSettings()));
|
||||||
|
connect(ui_->actionSave_session, SIGNAL(triggered()), this, SLOT(saveSession()));
|
||||||
|
connect(ui_->actionLoad_session, SIGNAL(triggered()), this, SLOT(loadSession()));
|
||||||
connect(ui_->actionShow_objects_features, SIGNAL(triggered()), this, SLOT(showObjectsFeatures()));
|
connect(ui_->actionShow_objects_features, SIGNAL(triggered()), this, SLOT(showObjectsFeatures()));
|
||||||
connect(ui_->actionHide_objects_features, SIGNAL(triggered()), this, SLOT(hideObjectsFeatures()));
|
connect(ui_->actionHide_objects_features, SIGNAL(triggered()), this, SLOT(hideObjectsFeatures()));
|
||||||
|
|
||||||
@ -315,6 +318,84 @@ void MainWindow::setSourceImageText(const QString & text)
|
|||||||
ui_->imageView_source->setTextLabel(text);
|
ui_->imageView_source->setTextLabel(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::loadSession()
|
||||||
|
{
|
||||||
|
if(objWidgets_.size())
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton b = QMessageBox::question(this, tr("Loading session..."),
|
||||||
|
tr("There are some objects (%1) already loaded, they will be "
|
||||||
|
"deleted when loading the session. Do you want to continue?").arg(objWidgets_.size()),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton);
|
||||||
|
if(b != QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString path = QFileDialog::getOpenFileName(this, tr("Load session..."), Settings::workingDirectory(), "*.bin");
|
||||||
|
if(!path.isEmpty())
|
||||||
|
{
|
||||||
|
qDeleteAll(objWidgets_);
|
||||||
|
objWidgets_.clear();
|
||||||
|
ui_->actionSave_objects->setEnabled(false);
|
||||||
|
findObject_->removeAllObjects();
|
||||||
|
|
||||||
|
if(findObject_->loadSession(path))
|
||||||
|
{
|
||||||
|
//update parameters tool box
|
||||||
|
const ParametersMap & parameters = Settings::getParameters();
|
||||||
|
for(ParametersMap::const_iterator iter = parameters.begin(); iter!= parameters.constEnd(); ++iter)
|
||||||
|
{
|
||||||
|
ui_->toolBox->updateParameter(iter.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
//update object widgets
|
||||||
|
for(QMap<int, ObjSignature *>::const_iterator iter=findObject_->objects().constBegin(); iter!=findObject_->objects().constEnd();++iter)
|
||||||
|
{
|
||||||
|
if(iter.value())
|
||||||
|
{
|
||||||
|
ObjWidget * obj = new ObjWidget(iter.key(), iter.value()->keypoints(), cvtCvMat2QImage(iter.value()->image()));
|
||||||
|
objWidgets_.insert(obj->id(), obj);
|
||||||
|
ui_->actionSave_objects->setEnabled(true);
|
||||||
|
ui_->actionSave_session->setEnabled(true);
|
||||||
|
this->showObject(obj);
|
||||||
|
|
||||||
|
//update object labels
|
||||||
|
QLabel * title = qFindChild<QLabel*>(this, QString("%1title").arg(iter.value()->id()));
|
||||||
|
title->setText(QString("%1 (%2)").arg(iter.value()->id()).arg(QString::number(iter.value()->keypoints().size())));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::information(this, tr("Session loaded!"), tr("Session \"%1\" successfully loaded (%2 objects)!").arg(path).arg(objWidgets_.size()));
|
||||||
|
|
||||||
|
if(!camera_->isRunning() && !sceneImage_.empty())
|
||||||
|
{
|
||||||
|
this->update(sceneImage_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void MainWindow::saveSession()
|
||||||
|
{
|
||||||
|
if(objWidgets_.size())
|
||||||
|
{
|
||||||
|
QString path = QFileDialog::getSaveFileName(this, tr("Save session..."), Settings::workingDirectory(), "*.bin");
|
||||||
|
if(!path.isEmpty())
|
||||||
|
{
|
||||||
|
if(QFileInfo(path).suffix().compare("bin") != 0)
|
||||||
|
{
|
||||||
|
path.append(".bin");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(findObject_->saveSession(path))
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, tr("Session saved!"), tr("Session \"%1\" successfully saved (%2 objects)!").arg(path).arg(objWidgets_.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::loadSettings()
|
void MainWindow::loadSettings()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Load settings..."), Settings::workingDirectory(), "*.ini");
|
QString path = QFileDialog::getOpenFileName(this, tr("Load settings..."), Settings::workingDirectory(), "*.ini");
|
||||||
@ -360,11 +441,11 @@ bool MainWindow::loadSettings(const QString & path)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UINFO("Path \"%s\" not valid (should be *.ini)", path.toStdString().c_str());
|
UERROR("Path \"%s\" not valid (should be *.ini)", path.toStdString().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::saveSettings(const QString & path)
|
bool MainWindow::saveSettings(const QString & path) const
|
||||||
{
|
{
|
||||||
if(!path.isEmpty() && QFileInfo(path).suffix().compare("ini") == 0)
|
if(!path.isEmpty() && QFileInfo(path).suffix().compare("ini") == 0)
|
||||||
{
|
{
|
||||||
@ -372,7 +453,7 @@ bool MainWindow::saveSettings(const QString & path)
|
|||||||
Settings::saveWindowSettings(this->saveGeometry(), this->saveState(), path);
|
Settings::saveWindowSettings(this->saveGeometry(), this->saveState(), path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UINFO("Path \"%s\" not valid (should be *.ini)", path.toStdString().c_str());
|
UERROR("Path \"%s\" not valid (should be *.ini)", path.toStdString().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +486,7 @@ int MainWindow::saveObjects(const QString & dirPath)
|
|||||||
QDir dir(dirPath);
|
QDir dir(dirPath);
|
||||||
if(dir.exists())
|
if(dir.exists())
|
||||||
{
|
{
|
||||||
for(QMap<int, ObjWidget*>::iterator iter=objWidgets_.begin(); iter!=objWidgets_.end(); ++iter)
|
for(QMap<int, ObjWidget*>::const_iterator iter=objWidgets_.constBegin(); iter!=objWidgets_.constEnd(); ++iter)
|
||||||
{
|
{
|
||||||
if(iter.value()->pixmap().save(QString("%1/%2.png").arg(dirPath).arg(iter.key())))
|
if(iter.value()->pixmap().save(QString("%1/%2.png").arg(dirPath).arg(iter.key())))
|
||||||
{
|
{
|
||||||
@ -464,6 +545,7 @@ void MainWindow::removeObject(find_object::ObjWidget * object)
|
|||||||
if(objWidgets_.size() == 0)
|
if(objWidgets_.size() == 0)
|
||||||
{
|
{
|
||||||
ui_->actionSave_objects->setEnabled(false);
|
ui_->actionSave_objects->setEnabled(false);
|
||||||
|
ui_->actionSave_session->setEnabled(false);
|
||||||
}
|
}
|
||||||
findObject_->removeObject(object->id());
|
findObject_->removeObject(object->id());
|
||||||
object->deleteLater();
|
object->deleteLater();
|
||||||
@ -570,6 +652,7 @@ void MainWindow::addObjectFromScene()
|
|||||||
obj->setId(signature->id());
|
obj->setId(signature->id());
|
||||||
objWidgets_.insert(obj->id(), obj);
|
objWidgets_.insert(obj->id(), obj);
|
||||||
ui_->actionSave_objects->setEnabled(true);
|
ui_->actionSave_objects->setEnabled(true);
|
||||||
|
ui_->actionSave_session->setEnabled(true);
|
||||||
showObject(obj);
|
showObject(obj);
|
||||||
updateVocabulary();
|
updateVocabulary();
|
||||||
objectsModified_ = true;
|
objectsModified_ = true;
|
||||||
@ -616,6 +699,7 @@ bool MainWindow::addObjectFromFile(const QString & filePath)
|
|||||||
ObjWidget * obj = new ObjWidget(s->id(), std::vector<cv::KeyPoint>(), cvtCvMat2QImage(s->image()));
|
ObjWidget * obj = new ObjWidget(s->id(), std::vector<cv::KeyPoint>(), cvtCvMat2QImage(s->image()));
|
||||||
objWidgets_.insert(obj->id(), obj);
|
objWidgets_.insert(obj->id(), obj);
|
||||||
ui_->actionSave_objects->setEnabled(true);
|
ui_->actionSave_objects->setEnabled(true);
|
||||||
|
ui_->actionSave_session->setEnabled(true);
|
||||||
this->showObject(obj);
|
this->showObject(obj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,11 +32,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <QtCore/QString>
|
#include <QtCore/QString>
|
||||||
#include <QtCore/QMultiMap>
|
#include <QtCore/QMultiMap>
|
||||||
#include <QtCore/QRect>
|
#include <QtCore/QRect>
|
||||||
|
#include <QtCore/QDataStream>
|
||||||
|
#include <QtCore/QByteArray>
|
||||||
|
|
||||||
namespace find_object {
|
namespace find_object {
|
||||||
|
|
||||||
class ObjSignature {
|
class ObjSignature {
|
||||||
public:
|
public:
|
||||||
|
ObjSignature() :
|
||||||
|
id_(-1)
|
||||||
|
{}
|
||||||
ObjSignature(int id, const cv::Mat & image, const QString & filename) :
|
ObjSignature(int id, const cv::Mat & image, const QString & filename) :
|
||||||
id_(id),
|
id_(id),
|
||||||
image_(image),
|
image_(image),
|
||||||
@ -44,15 +49,10 @@ public:
|
|||||||
{}
|
{}
|
||||||
virtual ~ObjSignature() {}
|
virtual ~ObjSignature() {}
|
||||||
|
|
||||||
void setData(const std::vector<cv::KeyPoint> & keypoints,
|
void setData(const std::vector<cv::KeyPoint> & keypoints, const cv::Mat & descriptors)
|
||||||
const cv::Mat & descriptors,
|
|
||||||
const QString & detectorType,
|
|
||||||
const QString & descriptorType)
|
|
||||||
{
|
{
|
||||||
keypoints_ = keypoints;
|
keypoints_ = keypoints;
|
||||||
descriptors_ = descriptors;
|
descriptors_ = descriptors;
|
||||||
detectorType_ = detectorType;
|
|
||||||
descriptorType_ = descriptorType;
|
|
||||||
}
|
}
|
||||||
void setWords(const QMultiMap<int, int> & words) {words_ = words;}
|
void setWords(const QMultiMap<int, int> & words) {words_ = words;}
|
||||||
void setId(int id) {id_ = id;}
|
void setId(int id) {id_ = id;}
|
||||||
@ -65,8 +65,69 @@ public:
|
|||||||
const std::vector<cv::KeyPoint> & keypoints() const {return keypoints_;}
|
const std::vector<cv::KeyPoint> & keypoints() const {return keypoints_;}
|
||||||
const cv::Mat & descriptors() const {return descriptors_;}
|
const cv::Mat & descriptors() const {return descriptors_;}
|
||||||
const QMultiMap<int, int> & words() const {return words_;}
|
const QMultiMap<int, int> & words() const {return words_;}
|
||||||
const QString & detectorType() const {return detectorType_;}
|
|
||||||
const QString & descriptorType() const {return descriptorType_;}
|
void save(QDataStream & streamPtr) const
|
||||||
|
{
|
||||||
|
streamPtr << id_;
|
||||||
|
streamPtr << filename_;
|
||||||
|
streamPtr << (int)keypoints_.size();
|
||||||
|
for(unsigned int j=0; j<keypoints_.size(); ++j)
|
||||||
|
{
|
||||||
|
streamPtr << keypoints_.at(j).angle <<
|
||||||
|
keypoints_.at(j).class_id <<
|
||||||
|
keypoints_.at(j).octave <<
|
||||||
|
keypoints_.at(j).pt.x <<
|
||||||
|
keypoints_.at(j).pt.y <<
|
||||||
|
keypoints_.at(j).response <<
|
||||||
|
keypoints_.at(j).size;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 dataSize = descriptors_.elemSize()*descriptors_.cols*descriptors_.rows;
|
||||||
|
streamPtr << descriptors_.rows <<
|
||||||
|
descriptors_.cols <<
|
||||||
|
descriptors_.type() <<
|
||||||
|
dataSize;
|
||||||
|
streamPtr << QByteArray((char*)descriptors_.data, dataSize);
|
||||||
|
|
||||||
|
streamPtr << words_;
|
||||||
|
|
||||||
|
std::vector<unsigned char> bytes;
|
||||||
|
cv::imencode(".png", image_, bytes);
|
||||||
|
streamPtr << QByteArray((char*)bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(QDataStream & streamPtr)
|
||||||
|
{
|
||||||
|
int nKpts;
|
||||||
|
streamPtr >> id_ >> filename_ >> nKpts;
|
||||||
|
keypoints_.resize(nKpts);
|
||||||
|
for(int i=0;i<nKpts;++i)
|
||||||
|
{
|
||||||
|
streamPtr >>
|
||||||
|
keypoints_[i].angle >>
|
||||||
|
keypoints_[i].class_id >>
|
||||||
|
keypoints_[i].octave >>
|
||||||
|
keypoints_[i].pt.x >>
|
||||||
|
keypoints_[i].pt.y >>
|
||||||
|
keypoints_[i].response >>
|
||||||
|
keypoints_[i].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rows,cols,type;
|
||||||
|
qint64 dataSize;
|
||||||
|
streamPtr >> rows >> cols >> type >> dataSize;
|
||||||
|
QByteArray data;
|
||||||
|
streamPtr >> data;
|
||||||
|
descriptors_ = cv::Mat(rows, cols, type, data.data()).clone();
|
||||||
|
|
||||||
|
streamPtr >> words_;
|
||||||
|
|
||||||
|
QByteArray image;
|
||||||
|
streamPtr >> image;
|
||||||
|
std::vector<unsigned char> bytes(image.size());
|
||||||
|
memcpy(bytes.data(), image.data(), image.size());
|
||||||
|
image_ = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int id_;
|
int id_;
|
||||||
@ -75,8 +136,6 @@ private:
|
|||||||
std::vector<cv::KeyPoint> keypoints_;
|
std::vector<cv::KeyPoint> keypoints_;
|
||||||
cv::Mat descriptors_;
|
cv::Mat descriptors_;
|
||||||
QMultiMap<int, int> words_; // <word id, keypoint indexes>
|
QMultiMap<int, int> words_; // <word id, keypoint indexes>
|
||||||
QString detectorType_;
|
|
||||||
QString descriptorType_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace find_object
|
} // namespace find_object
|
||||||
|
|||||||
@ -51,6 +51,41 @@ void Vocabulary::clear()
|
|||||||
notIndexedWordIds_.clear();
|
notIndexedWordIds_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Vocabulary::save(QDataStream & streamPtr) const
|
||||||
|
{
|
||||||
|
if(!indexedDescriptors_.empty() && !wordToObjects_.empty())
|
||||||
|
{
|
||||||
|
UASSERT(notIndexedDescriptors_.empty() && notIndexedWordIds_.empty());
|
||||||
|
|
||||||
|
// save index
|
||||||
|
streamPtr << wordToObjects_;
|
||||||
|
|
||||||
|
// save words
|
||||||
|
qint64 dataSize = indexedDescriptors_.elemSize()*indexedDescriptors_.cols*indexedDescriptors_.rows;
|
||||||
|
streamPtr << indexedDescriptors_.rows <<
|
||||||
|
indexedDescriptors_.cols <<
|
||||||
|
indexedDescriptors_.type() <<
|
||||||
|
dataSize;
|
||||||
|
streamPtr << QByteArray((char*)indexedDescriptors_.data, dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vocabulary::load(QDataStream & streamPtr)
|
||||||
|
{
|
||||||
|
// load index
|
||||||
|
streamPtr >> wordToObjects_;
|
||||||
|
|
||||||
|
// load words
|
||||||
|
int rows,cols,type;
|
||||||
|
qint64 dataSize;
|
||||||
|
streamPtr >> rows >> cols >> type >> dataSize;
|
||||||
|
QByteArray data;
|
||||||
|
streamPtr >> data;
|
||||||
|
indexedDescriptors_ = cv::Mat(rows, cols, type, data.data()).clone();
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
QMultiMap<int, int> Vocabulary::addWords(const cv::Mat & descriptors, int objectId, bool incremental)
|
QMultiMap<int, int> Vocabulary::addWords(const cv::Mat & descriptors, int objectId, bool incremental)
|
||||||
{
|
{
|
||||||
QMultiMap<int, int> words;
|
QMultiMap<int, int> words;
|
||||||
|
|||||||
@ -45,6 +45,10 @@ public:
|
|||||||
void search(const cv::Mat & descriptors, cv::Mat & results, cv::Mat & dists, int k);
|
void search(const cv::Mat & descriptors, cv::Mat & results, cv::Mat & dists, int k);
|
||||||
int size() const {return indexedDescriptors_.rows + notIndexedDescriptors_.rows;}
|
int size() const {return indexedDescriptors_.rows + notIndexedDescriptors_.rows;}
|
||||||
const QMultiMap<int, int> & wordToObjects() const {return wordToObjects_;}
|
const QMultiMap<int, int> & wordToObjects() const {return wordToObjects_;}
|
||||||
|
const cv::Mat & indexedDescriptors() const {return indexedDescriptors_;}
|
||||||
|
|
||||||
|
void save(QDataStream & streamPtr) const;
|
||||||
|
void load(QDataStream & streamPtr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cv::flann::Index flannIndex_;
|
cv::flann::Index flannIndex_;
|
||||||
|
|||||||
@ -219,6 +219,9 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>File</string>
|
<string>File</string>
|
||||||
</property>
|
</property>
|
||||||
|
<addaction name="actionLoad_session"/>
|
||||||
|
<addaction name="actionSave_session"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="actionLoad_objects"/>
|
<addaction name="actionLoad_objects"/>
|
||||||
<addaction name="actionSave_objects"/>
|
<addaction name="actionSave_objects"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@ -850,6 +853,16 @@
|
|||||||
<string>Camera from TCP/IP...</string>
|
<string>Camera from TCP/IP...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionLoad_session">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load session...</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionSave_session">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save session...</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionHide_objects_features">
|
<action name="actionHide_objects_features">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Hide objects features</string>
|
<string>Hide objects features</string>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user