2015-10-01 1 views
-1

Après les étapes http://caffe.berkeleyvision.org/gathered/examples/feature_extraction.html pour extraire fonction de nouvelles images après la formation,caractéristiques d'extrait dans un fichier texte

vous finissez par obtenir un fichier Data.mdb.

Je préférerais de beaucoup écrire des caractéristiques dans un fichier txt pour pouvoir facilement le manipuler. J'ai fait quelques recherches sur Google et trouvé du code, mais cela n'a pas fonctionné. En outre, les fichiers data.mdb générés, lorsqu'ils sont ouverts à l'aide d'applications d'ouverture de mdb sur mac, n'affichent aucune table.

Existe-t-il un moyen facile d'écrire des fonctionnalités extraites dans un fichier texte, ou alternativement, moyen facile de manipuler le fichier mdb afin que nous puissions vérifier les valeurs réelles par image?

Répondre

0

L'interface C++ pour Caffe fournit une fonctionnalité lmdb pour lire les données, puis les réécrire.

Vous pouvez prendre un look yourself sur la façon dont LMDBDataLayer exécute ses lectures, puis l'utiliser comme référence pour écrire un programme pour manipuler/écrire en texte les données d'une base de données LMDB.

0

Je ne sais pas si vous avez déjà compris comment résoudre ce problème, mais voici comment je viens de le découvrir récemment. Je suis nouveau à Caffe et j'ai du mal à comprendre toute l'architecture de Caffe. Je voulais juste une méthode rapide pour extraire les fonctionnalités de CNN de Caffe et les manipuler plus tard. De plus, je travaille sur OSX et n'ai pas installé Caffe depuis la source. Je l'ai installé via 'port', et l'installation semble incomplète. J'ai donc lancé 'feature_extractor' de Caffe sur une autre machine où Caffe est correctement installé et copié le fichier de sortie sur ma machine pour le traitement ultérieur. Pour cela, vous devrez installer LMDB et Protobuf de Google sur votre machine. Pour cela, vous devez installer LMDB et Google Protobuf. Vous devrez lier le programme C/C++ avec liblmdb et libprotobuf.

J'ai suivi le tutoriel de Caffe pour enregistrer la sortie de la couche 'fc7' d'AlexNet dans un fichier au format LMDB. Puis j'ai écrit un simple programme C/C++ pour le lire. Cela peut être fait en utilisant le code suivant:

#include <fstream> 
#include <iostream> 
#include <lmdb.h> 

using namespace std; 

int main(int argc, char *argv[]) 
{ 
    if(argc!=2) 
    { 
     cerr<< "Error"<< endl 
      << "Usage : "<< argv[0]<< " mdb_dirname"<< endl; 
     return 0; 
    } 
    char *mdb_dirname  = argv[1]; 

    int rc; 
    MDB_env *env; 
    MDB_dbi dbi; 
    MDB_val key, data; 
    MDB_txn *txn; 
    MDB_cursor *cursor; 
    char sval[32]; 

    rc = mdb_env_create(&env); 
    rc = mdb_env_open(env, mdb_dirname, 0, 0664); 
    rc = mdb_txn_begin(env, NULL, 0, &txn); 
    rc = mdb_open(txn, NULL, 0, &dbi); 
    rc = mdb_cursor_open(txn, dbi, &cursor); 

    key.mv_size = sizeof(int); 
    key.mv_data = sval; 
    data.mv_size = sizeof(sval); 
    data.mv_data = sval; 

    while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) 
    { 
     printf("key: %p %d %.*s, data: %p %d %.*s\n", 
       key.mv_data, (int) key.mv_size, (int) key.mv_size, (char *) key.mv_data, 
       data.mv_data, (int) data.mv_size, (int) data.mv_size, (char *) data.mv_data); 
    } 
    mdb_cursor_close(cursor); 
    mdb_txn_abort(txn); 

    mdb_close(env, dbi); 
    mdb_env_close(env); 

    return 0; 
} 

« mdb_dirname » est le répertoire créé par « feature_extractor ». Il contient 'data.mdb' et 'lock.mdb'.

A noté que je suis aussi nouveau à LMDB. Je ne comprends pas vraiment toutes les lignes de code ci-dessus. Cependant, je ne fonctionne pas :)

Si vous traitez votre fichier LMDB, vous pouvez observer que 'key.mv_data' est bien l'index de votre exemple. La donnée 'data.mv_data' devrait donc contenir le vecteur de caractéristiques pour cet exemple. J'ai regardé dans le code source de feature_extractor de Caffe et j'ai trouvé que la chaîne 'data.mv_data' est obtenue à partir de la sérialisation d'un objet 'Datum'. Ce datum est en effet construit à l'aide de Protocol Buffer ou Protobuf de Google. Vous pouvez trouver 'caffe.proto' quelque part dans le répertoire Caffe. Ce fichier .proto est traité par le compilateur 'protoc' et produit 'caffe.pb.h' et 'caffe.pb.cc' qui doivent être inclus dans votre projet. Si vous ne pouvez pas le trouver, voici à quoi cela ressemble

syntax = "proto2"; 

package caffe; 

message Datum { 
    optional int32 channels = 1; 
    optional int32 height = 2; 
    optional int32 width = 3; 
    // the actual image data, in bytes 
    optional bytes data = 4; 
    optional int32 label = 5; 
    // Optionally, the datum could also hold float data. 
    repeated float float_data = 6; 
    // If true data contains an encoded image that need to be decoded 
    optional bool encoded = 7 [default = false]; 
} 

Ensuite, vous pouvez convertir des données.mv_data » dans les vecteurs de caractéristiques par

while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) 
    { 
     string str((char*)data.mv_data, (int)data.mv_size); 

     datum.ParseFromString(str); 

     if(datum.float_data_size()>0) 
     { 
      // datum.float_data_size() is the dimension of the feature vectors 
      for(int i = 0; i < datum.float_data_size(); i++) 
      { 
       float f = datum.float_data(i); 
       // do something 
      } 
     } 
    } 

Lorsque je construis le code ci-dessus, il y a beaucoup d'erreurs êtes les reliant, comme les références non définies ... et autres étoffes liées à Protobuf. Si vous rencontrez le même problème, une solution que j'ai trouvée est de lier le programme contre libprotobuf.a au lieu de simplement -llmdb (lien statique au lieu de lien dynamique).

Un autre petit problème est que l'étiquette attribuée à chaque exemple dans le fichier traité par 'feature_extractor' est perdue. Je ne sais pas pourquoi. Je viens donc de mettre ces étiquettes dans un fichier séparé et de les traiter le long du fichier LMDB. Par exemple, si vous voulez sortir le fichier LIBSVM:

int c = 0; 
    while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) 
    { 
     string str((char*)data.mv_data, (int)data.mv_size); 
     datum.ParseFromString(str); 
     if(datum.float_data_size()>0) 
     { 
      cout<< label[c]<< " "; 
      for(int i = 0; i < datum.float_data_size(); i++) 
      { 
       float f = datum.float_data(i); 
       cout<< (i+1)<< ":"<< f<< " "; 
      } 
      cout<< endl; 
      c++; 
     } 
    } 

Bonne chance.