2012-02-12 2 views
7

Обучение дескриптору OpenCVМатчер может занимать много времени, если набор обучающих изображений большой. Таким образом, кажется, что сохранение подготовленных данных дескриптораМатчера на диск для последующей перезагрузки было бы довольно очевидной задачей.Сохранение и загрузка FlannBasedMatcher

К сожалению, похоже, не существует очевидного решения этой проблемы.

Ближайший я пришел найти ответ this thread in the OpenCV discussion group. Тема началась в 2009 году, и люди все еще ищут ответ в 2011 году!

Этот фрагмент кода взят из этого потока выглядит, как он должен перезагрузить индекс из файла:

FileStorage fs("data.xml",FileStorage::READ); 
Mat data; 
fs["mtx"] >> data; 
flann::Index idx(data,"index.bin"); 

Но я не мог понять, от этого, как реализовать полный сохранения/функциональности нагрузки.

На всякий случай это актуально, я использую OpenCV 2.3.1.

ответ

5

Я не видел ответа на это на форумах или в списке рассылки. Мне нужно было найти исходный код OpenCV (2.4.5), чтобы узнать, как это нужно сделать. Он требует, чтобы подклассы попадали в защищенные члены FlannBasedMatcher.

Ключ устанавливает алгоритм в FLANN_INDEX_SAVED и имя файла на indexParams.

Следует также отметить:

  • Дескрипторы должны быть переданы добавить() перед тем readIndex()

  • Для индекса, который будет построен, вы должны сделать матч на него первым, а затем call write(). train(), похоже, ничего не делает, кроме как построить сопряжение (не передает его дескрипторы)

  • Это работает с дескрипторами SURF. Для полного решения может потребоваться сохранить/восстановить IndexParams и/или SearchParams.

Следующее, что нужно сделать, это сжать индекс (с помощью gzip), он может быть в 3-4 раза меньше, а стоимость декомпрессии относительно невысока. Это должно быть патчем в OpenCV.

class SaveableMatcher : public cv::FlannBasedMatcher 
{ 
public: 
SaveableMatcher() 
{ 
} 

virtual ~SaveableMatcher() 
{ 
} 

void printParams() 
{ 
    printf("SaveableMatcher::printParams: \n\t" 
     "addedDescCount=%d\n\t" 
     "flan distance_t=%d\n\t" 
     "flan algorithm_t=%d\n", 
     addedDescCount, 
     flannIndex->getDistance(), 
     flannIndex->getAlgorithm()); 

    vector<std::string> names; 
    vector<int> types; 
    vector<std::string> strValues; 
    vector<double> numValues; 

    indexParams->getAll(names, types, strValues, numValues); 

    for (size_t i = 0; i < names.size(); i++) 
     printf("\tindex param: %s:\t type=%d val=%s %.2f\n", 
       names[i].c_str(), types[i], 
       strValues[i].c_str(), numValues[i]); 

    names.clear(); 
    types.clear(); 
    strValues.clear(); 
    numValues.clear(); 
    searchParams->getAll(names, types, strValues, numValues); 

    for (size_t i = 0; i < names.size(); i++) 
     printf("\tsearch param: %s:\t type=%d val=%s %.2f\n", 
       names[i].c_str(), types[i], 
       strValues[i].c_str(), numValues[i]); 
} 

void readIndex(const char* filename) 
{ 
    indexParams->setAlgorithm(cvflann::FLANN_INDEX_SAVED); 
    indexParams->setString("filename", filename); 

    // construct flannIndex now, so printParams works 
    train(); 

    printParams(); 
} 

void writeIndex(const char* filename) 
{ 
    printParams(); 
    flannIndex->save(filename); 
} 
}; 
+0

Примечание: как я понимаю, сами дескрипторы должны быть сериализованы/десериализованы отдельно. При загрузке _prior_ для вызова readIndex дескрипторы должны быть десериализованы и добавлены (т. Е. С помощью FlannBasedMatcher :: add). – sircolinton

3

В OpenCV 2.4.0 (но и в 2.3.1a) есть:

// Reads matcher object from a file node 
virtual void read(const FileNode&); 
// Writes matcher object to a file storage 
virtual void write(FileStorage&) const; 

, которые реализуются по крайней мере, для FlannDescriptorMatcher, но реализация, кажется, сохранить только IndexParams из согласовани. Вместо flann :: Index_ есть методы сохранения и загрузки (в 2.3.1 есть сэкономить, пока загрузка кажется доступной с использованием SavedIndexParams

+0

Да, функции чтения и записи сохраняют только IndexParams. Я рассмотрю другие функции, которые вы упомянули. –

3

Этот вопрос задан давно, так что вы, вероятно, уже имеете свой ответ, но я просто реализовал что-то, используя код, похожий на то, что вы показываете. Я не сохранил дескрипторMatcher, но создал файл descriptors.xml для каждого изображения в коллекции, а затем загрузил все это в вектор, который будет использоваться в качестве ввода в поезд() Это сократило время работы программы от 2 минут до 5 секунд, но загрузка векторов в вектор занимает 3-4 секунды. Было бы удобно загрузить весь обучаемый индекс. Я все еще ищу способ сделать это.

1

Я посмотрел на коде OpenCV 3.2.0 и обнаружил, что запись Flann базирующегося сличителя (в)/функцию чтения() по-прежнему не сохранять/загружать подготовленные данные. Вдохновленный ответом Валли, я создал подобный класс разумного совпадения, унаследованный от FlannBasedMatcher. Обратите внимание, что этот savable matcher в настоящее время работает только с дескрипторами SURF.

Этот безопасный класс FlannBasedSavableMatcher записывает indexParams, searchParams и обученные дескрипторы в файл xml/yml, но должен писать flannIndex в отдельный двоичный файл, поскольку метод save() flannIndex поддерживает только двоичный формат.

Ниже приведен заголовок класса.

#ifndef INCLUDES_FLANNBASEDSAVABLEMATCHER_H_ 
#define INCLUDES_FLANNBASEDSAVABLEMATCHER_H_ 

#include <string> 

#include <opencv2/core.hpp> 
#include <opencv2/features2d.hpp> 

namespace cv 
{ 

class FlannBasedSavableMatcher : public FlannBasedMatcher 
{ 
private: 
    std::vector<std::string> trainedImgFilenameList; 
    std::string flannIndexFileDir; 
    std::string flannIndexFilename; 

public: 
    FlannBasedSavableMatcher(); 
    virtual ~FlannBasedSavableMatcher(); 

    std::vector<std::string> getTrainedImgFilenameList(); 
    void setTrainedImgFilenameList(const std::vector<std::string>& imgFilenameList); 
    void setFlannIndexFileDir(const std::string& dir); 
    void setFlannIndexFilename(const std::string& filename); 

    virtual void read(const FileNode& fn); 
    virtual void write(FileStorage& fs) const; 

    static Ptr<FlannBasedSavableMatcher> create(); 
}; 

} 

#endif /* INCLUDES_FLANNBASEDSAVABLEMATCHER_H_ */ 

Исходный файл может быть найден в https://github.com/renweizhukov/LearningOpenCV/blob/master/FlannKnnSavableMatching1toN/src/FlannBasedSavableMatcher.cpp, в то время как использование образец можно найти на https://github.com/renweizhukov/LearningOpenCV/blob/master/FlannKnnSavableMatching1toN/src/main.cpp.

Смежные вопросы