diff --git a/include/find_object/DetectionInfo.h b/include/find_object/DetectionInfo.h index c11e7853..9ce34057 100644 --- a/include/find_object/DetectionInfo.h +++ b/include/find_object/DetectionInfo.h @@ -70,7 +70,7 @@ public: // Those maps have the same size QMultiMap objDetected_; QMultiMap objDetectedSizes_; // Object ID match the number of detected objects - QMultiMap objDetectedFilenames_; // Object ID match the number of detected objects + QMultiMap objDetectedFilePaths_; // Object ID match the number of detected objects QMultiMap objDetectedInliersCount_; // ObjectID match the number of detected objects QMultiMap objDetectedOutliersCount_; // ObjectID match the number of detected objects QMultiMap > objDetectedInliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of detected objects @@ -98,7 +98,7 @@ inline QDataStream & operator<<(QDataStream &out, const DetectionInfo & info) QMultiMap::const_iterator iterInliers = info.objDetectedInliersCount_.constBegin(); QMultiMap::const_iterator iterOutliers = info.objDetectedOutliersCount_.constBegin(); QMultiMap::const_iterator iterSizes = info.objDetectedSizes_.constBegin(); - QMultiMap::const_iterator iterFilenames = info.objDetectedFilenames_.constBegin(); + QMultiMap::const_iterator iterFilenames = info.objDetectedFilePaths_.constBegin(); for(QMultiMap::const_iterator iter=info.objDetected_.constBegin(); iter!=info.objDetected_.constEnd(); ++iter) @@ -148,7 +148,7 @@ inline QDataStream & operator>>(QDataStream &in, DetectionInfo & info) in >> id >> size >> homography >> filename >> inliers >> outliers; info.objDetected_.insert(id, homography); info.objDetectedSizes_.insert(id, size); - info.objDetectedFilenames_.insert(id, filename); + info.objDetectedFilePaths_.insert(id, filename); info.objDetectedInliersCount_.insert(id, inliers); info.objDetectedOutliersCount_.insert(id, outliers); } diff --git a/include/find_object/FindObject.h b/include/find_object/FindObject.h index 1df6aab2..16084003 100644 --- a/include/find_object/FindObject.h +++ b/include/find_object/FindObject.h @@ -69,9 +69,9 @@ public: bool saveSession(const QString & path); bool isSessionModified() const {return sessionModified_;} - int loadObjects(const QString & dirPath); // call updateObjects() + int loadObjects(const QString & dirPath, bool recursive = false); // call updateObjects() 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 & filePath = QString()); bool addObject(ObjSignature * obj); // take ownership when true is returned void removeObject(int id); void removeAllObjects(); @@ -86,7 +86,7 @@ public: const Vocabulary * vocabulary() const {return vocabulary_;} public Q_SLOTS: - void addObjectAndUpdate(const cv::Mat & image, int id=0, const QString & filename = QString()); + void addObjectAndUpdate(const cv::Mat & image, int id=0, const QString & filePath = QString()); void removeObjectAndUpdate(int id); void detect(const cv::Mat & image); // emit objectsFound() diff --git a/include/find_object/MainWindow.h b/include/find_object/MainWindow.h index 702632fe..5a882c3e 100644 --- a/include/find_object/MainWindow.h +++ b/include/find_object/MainWindow.h @@ -115,7 +115,7 @@ Q_SIGNALS: private: bool loadSettings(const QString & path); bool saveSettings(const QString & path) const; - int loadObjects(const QString & dirPath); + int loadObjects(const QString & dirPath, bool recursive = false); int saveObjects(const QString & dirPath); void setupTCPServer(); int addObjectFromFile(const QString & filePath); diff --git a/src/FindObject.cpp b/src/FindObject.cpp index 77d1e40a..f5fad2bb 100644 --- a/src/FindObject.cpp +++ b/src/FindObject.cpp @@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -140,25 +141,49 @@ bool FindObject::saveSession(const QString & path) return false; } -int FindObject::loadObjects(const QString & dirPath) +int FindObject::loadObjects(const QString & dirPath, bool recursive) { int loadedObjects = 0; QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.'); - UDirectory dir(dirPath.toStdString(), formats.toStdString()); - if(dir.isValid()) + + QStringList paths; + paths.append(dirPath); + + while(paths.size()) { - const std::list & names = dir.getFileNames(); // sorted in natural order - for(std::list::const_iterator iter=names.begin(); iter!=names.end(); ++iter) + QString currentDir = paths.front(); + UDirectory dir(currentDir.toStdString(), formats.toStdString()); + if(dir.isValid()) { - this->addObject((dirPath.toStdString()+dir.separator()+*iter).c_str()); + const std::list & names = dir.getFileNames(); // sorted in natural order + for(std::list::const_iterator iter=names.begin(); iter!=names.end(); ++iter) + { + if(this->addObject((currentDir.toStdString()+dir.separator()+*iter).c_str())) + { + ++loadedObjects; + } + } } - if(names.size()) + + paths.pop_front(); + + if(recursive) { - this->updateObjects(); - this->updateVocabulary(); + QDir d(currentDir); + QStringList subDirs = d.entryList(QDir::AllDirs|QDir::NoDotAndDotDot, QDir::Name); + for(int i=subDirs.size()-1; i>=0; --i) + { + paths.prepend(currentDir+QDir::separator()+subDirs[i]); + } } - loadedObjects = (int)names.size(); } + + if(loadedObjects) + { + this->updateObjects(); + this->updateVocabulary(); + } + return loadedObjects; } @@ -190,16 +215,16 @@ const ObjSignature * FindObject::addObject(const QString & filePath) id = 0; } } - return this->addObject(img, id, file.fileName()); + return this->addObject(img, id, filePath); } } return 0; } -const ObjSignature * FindObject::addObject(const cv::Mat & image, int id, const QString & filename) +const ObjSignature * FindObject::addObject(const cv::Mat & image, int id, const QString & filePath) { UASSERT(id >= 0); - ObjSignature * s = new ObjSignature(id, image, filename); + ObjSignature * s = new ObjSignature(id, image, filePath); if(!this->addObject(s)) { delete s; @@ -245,9 +270,9 @@ void FindObject::removeAllObjects() clearVocabulary(); } -void FindObject::addObjectAndUpdate(const cv::Mat & image, int id, const QString & filename) +void FindObject::addObjectAndUpdate(const cv::Mat & image, int id, const QString & filePath) { - const ObjSignature * s = this->addObject(image, id, filename); + const ObjSignature * s = this->addObject(image, id, filePath); if(s) { QList ids; @@ -1449,7 +1474,7 @@ bool FindObject::detect(const cv::Mat & image, find_object::DetectionInfo & info info.objDetectedOutliers_.insert(id, threads[j]->getOutliers()); info.objDetectedInliersCount_.insert(id, threads[j]->getInliers().size()); info.objDetectedOutliersCount_.insert(id, threads[j]->getOutliers().size()); - info.objDetectedFilenames_.insert(id, objects_.value(id)->filename()); + info.objDetectedFilePaths_.insert(id, objects_.value(id)->filePath()); } else { diff --git a/src/JsonWriter.cpp b/src/JsonWriter.cpp index ec7b1187..abda143a 100644 --- a/src/JsonWriter.cpp +++ b/src/JsonWriter.cpp @@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include "json/json.h" @@ -48,7 +49,7 @@ void JsonWriter::write(const DetectionInfo & info, const QString & path) QMultiMap::const_iterator iterInliers = info.objDetectedInliersCount_.constBegin(); QMultiMap::const_iterator iterOutliers = info.objDetectedOutliersCount_.constBegin(); QMultiMap::const_iterator iterSizes = info.objDetectedSizes_.constBegin(); - QMultiMap::const_iterator iterFilenames = info.objDetectedFilenames_.constBegin(); + QMultiMap::const_iterator iterFilePaths = info.objDetectedFilePaths_.constBegin(); for(QMultiMap::const_iterator iter = info.objDetected_.constBegin(); iter!= info.objDetected_.end();) { char index = 'a'; @@ -73,13 +74,20 @@ void JsonWriter::write(const DetectionInfo & info, const QString & path) root[name.toStdString()]["homography"] = homography; root[name.toStdString()]["inliers"] = iterInliers.value(); root[name.toStdString()]["outliers"] = iterOutliers.value(); - root[name.toStdString()]["filename"] = iterFilenames.value().toStdString(); + root[name.toStdString()]["filepath"] = iterFilePaths.value().toStdString(); + QString filename; + if(!iterFilePaths.value().isEmpty()) + { + QFileInfo file(iterFilePaths.value()); + filename=file.fileName(); + } + root[name.toStdString()]["filename"] = filename.toStdString(); ++iter; ++iterInliers; ++iterOutliers; ++iterSizes; - ++iterFilenames; + ++iterFilePaths; } } root["objects"] = detections; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 081dabc5..0dfe94aa 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -460,27 +460,49 @@ bool MainWindow::saveSettings(const QString & path) const return false; } -int MainWindow::loadObjects(const QString & dirPath) +int MainWindow::loadObjects(const QString & dirPath, bool recursive) { QList loadedObjects; QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.'); - UDirectory dir(dirPath.toStdString(), formats.toStdString()); - if(dir.isValid()) + + QStringList paths; + paths.append(dirPath); + + while(paths.size()) { - const std::list & names = dir.getFileNames(); // sorted in natural order - for(std::list::const_iterator iter=names.begin(); iter!=names.end(); ++iter) + QString currentDir = paths.front(); + UDirectory dir(currentDir.toStdString(), formats.toStdString()); + if(dir.isValid()) { - int id = this->addObjectFromFile((dirPath.toStdString()+dir.separator()+*iter).c_str()); - if(id >= 0) + const std::list & names = dir.getFileNames(); // sorted in natural order + for(std::list::const_iterator iter=names.begin(); iter!=names.end(); ++iter) { - loadedObjects.push_back(id); + int id = this->addObjectFromFile((currentDir.toStdString()+dir.separator()+*iter).c_str()); + if(id >= 0) + { + loadedObjects.push_back(id); + } } } - if(loadedObjects.size()) + + paths.pop_front(); + + if(recursive) { - this->updateObjects(loadedObjects); + QDir d(currentDir); + QStringList subDirs = d.entryList(QDir::AllDirs|QDir::NoDotAndDotDot, QDir::Name); + for(int i=subDirs.size()-1; i>=0; --i) + { + paths.prepend(currentDir + QDir::separator() + subDirs[i]); + } } } + + if(loadedObjects.size()) + { + this->updateObjects(loadedObjects); + } + return loadedObjects.size(); } @@ -511,7 +533,20 @@ void MainWindow::loadObjects() QString dirPath = QFileDialog::getExistingDirectory(this, tr("Loading objects... Select a directory."), Settings::workingDirectory()); if(!dirPath.isEmpty()) { - int count = loadObjects(dirPath); + QDir d(dirPath); + bool recursive = false; + if(d.entryList(QDir::AllDirs).size()) + { + QMessageBox::StandardButton b = QMessageBox::question( + this, + tr("Loading objects..."), + tr("The current directory contains subdirectories. Load objects recursively?"), + QMessageBox::Yes|QMessageBox::No, + QMessageBox::No); + recursive = b == QMessageBox::Yes; + } + + int count = loadObjects(dirPath, recursive); if(count) { QMessageBox::information(this, tr("Loading..."), tr("%1 objects loaded from \"%2\".").arg(count).arg(dirPath)); diff --git a/src/ObjSignature.h b/src/ObjSignature.h index 2ad347be..27cca18e 100644 --- a/src/ObjSignature.h +++ b/src/ObjSignature.h @@ -42,10 +42,10 @@ public: ObjSignature() : id_(-1) {} - ObjSignature(int id, const cv::Mat & image, const QString & filename) : + ObjSignature(int id, const cv::Mat & image, const QString & filePath) : id_(id), image_(image), - filename_(filename) + filePath_(filePath) {} virtual ~ObjSignature() {} @@ -60,7 +60,7 @@ public: QRect rect() const {return QRect(0,0,image_.cols, image_.rows);} int id() const {return id_;} - const QString & filename() const {return filename_;} + const QString & filePath() const {return filePath_;} const cv::Mat & image() const {return image_;} const std::vector & keypoints() const {return keypoints_;} const cv::Mat & descriptors() const {return descriptors_;} @@ -69,7 +69,7 @@ public: void save(QDataStream & streamPtr) const { streamPtr << id_; - streamPtr << filename_; + streamPtr << filePath_; streamPtr << (int)keypoints_.size(); for(unsigned int j=0; j> id_ >> filename_ >> nKpts; + streamPtr >> id_ >> filePath_ >> nKpts; keypoints_.resize(nKpts); for(int i=0;i keypoints_; cv::Mat descriptors_; QMultiMap words_; //