2012-02-12 13 views
7

Addestramento di un DescrittoreCarrello OpenCV può essere un'operazione che richiede molto tempo se l'immagine di addestramento è grande. Sembra quindi che salvare i dati di DescriptorMatcher su disco per ricaricarli in seguito sarebbe una cosa abbastanza ovvia da fare.Salvataggio e caricamento FlannBasedMatcher

Purtroppo non sembra esserci alcuna soluzione ovvia a questa esigenza.

Il più vicino che sono venuto a trovare una risposta è this thread in the OpenCV discussion group. Il thread è iniziato nel 2009 e le persone sono ancora alla ricerca di una risposta nel 2011!

Questo frammento di codice preso da quel filo sembra che dovrebbe ricaricare un indice da un file:

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

Ma non sono stato in grado di capire da questo come implementare completa Salva funzionalità/carico.

Nel caso sia pertinente, sto utilizzando OpenCV 2.3.1.

risposta

5

Non ho visto una risposta a questo su forum o mailing list. Ho dovuto scavare nel codice sorgente OpenCV (2.4.5) per vedere come questo deve essere fatto. Richiede la sottoclasse per ottenere i membri protetti di FlannBasedMatcher.

Il tasto imposta l'algoritmo su FLANN_INDEX_SAVED e il nome del file su indexParams.

Anche di nota:

  • devono essere passati I descrittori per aggiungere() prima readIndex()

  • Per l'indice da costruire, si deve fare una partita su di esso, poi chiama scrivi(). train() non sembra fare nient'altro che costruire il matcher (non lo alimenta descrittori)

  • Questo funziona con i descrittori SURF. Per una soluzione completa potrebbe essere necessario salvare/ripristinare IndexParams e/o SearchParams del matcher.

prossima cosa da fare è comprimere l'indice (con gzip), può essere 3-4 volte più piccolo e il costo per decomprimere è relativamente basso. Questa dovrebbe essere una patch in 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

Nota: a quanto ho capito, i descrittori stessi devono essere serializzati/deserializzati separatamente. Al momento del caricamento, _prior_ per chiamare readIndex, i descrittori devono essere deserializzati e aggiunti (vale a dire, con FlannBasedMatcher :: add). – sircolinton

3

In OpenCV 2.4.0 (ma anche in 2.3.1a) ci sono:

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

che vengono attuate, almeno per il FlannDescriptorMatcher ma l'implementazione sembra salvare solo le IndexParams del matcher. Invece flann :: Index_ ha metodi di salvataggio e caricamento (in 2.3.1 c'è un salvataggio mentre il carico sembra essere disponibile usando SavedIndexParams

+0

Sì, le funzioni di lettura e scrittura salvano solo IndexParams. Daremo un'occhiata alle altre funzioni che hai menzionato. –

3

Questa domanda è stata posta molto tempo fa, quindi probabilmente hai già la tua risposta, ma io appena implementato qualcosa usando un codice simile a quello che mostri. Non ho salvato il DescriptorMatcher, ma ho creato un file descriptors.xml per ogni immagine nella raccolta, e poi ho caricato tutto questo in un vettore da utilizzare come input per il treno() call Questo ha ridotto il tempo di esecuzione del programma da 2 minuti a 5 secondi, ma impiega 3-4 secondi per caricare i descrittori nel vettore Sarebbe utile caricare l'intero indice addestrato. un modo per farlo

1

ho guardato il codice OpenCV 3.2.0 e ha scoperto che in scrittura del matcher Flann-based()/lettura function() continua a non salvare/caricare i dati addestrati. Ispirato dalla risposta di Wally, ho creato una simile classe matcher salvabile ereditata da FlannBasedMatcher. Nota che questo matcher salvabile attualmente funziona solo con i descrittori SURF.

Questa classe salvabile FlannBasedSavableMatcher scrive indexParams, searchParams, e descrittori addestrati in un file XML/yml ma deve scrivere flannIndex in un file binario separato dal momento che il metodo save() di flannIndex supporta solo il formato binario non elaborato.

Di seguito è riportato l'intestazione della classe.

#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_ */ 

Il file sorgente può essere trovato alla https://github.com/renweizhukov/LearningOpenCV/blob/master/FlannKnnSavableMatching1toN/src/FlannBasedSavableMatcher.cpp, mentre un utilizzo campione può essere trovato alla https://github.com/renweizhukov/LearningOpenCV/blob/master/FlannKnnSavableMatching1toN/src/main.cpp.

Problemi correlati