1
votes

TFRecords pour les vidéos

J'essaie de créer des TFRecords à partir d'un ensemble de données vidéo personnalisé et j'ai des problèmes pour bien comprendre comment les configurer.

Afin de préparer mes données pour le stockage, j'ai écrit un script qui, pour un flux vidéo donné, produit un cube 3D de forme [N_FRAMES, WIDTH, HEIGHT, CHANNEL] . Ensuite, je crée un tfrecord comme suit:

def readDataRecord(self, record):
  filename_queue = tf.train.string_input_producer([record], num_epochs=1)

  reader = tf.TFRecordReader()
  _, serialized_example = reader.read(filename_queue)

  feature =
  {'height': tf.FixedLenFeature([], tf.int64),
    'width': tf.FixedLenFeature([], tf.int64),
    'depth': tf.FixedLenFeature([], tf.int64),
    'data': tf.FixedLenFeature([], tf.string),
    'category': tf.FixedLenFeature([], tf.int64),
  }

  example = tf.parse_single_example(serialized_example, features=feature)

  video3D_buffer = tf.reshape(example['data'], shape=[])
  video3D = tf.decode_raw(video3D_buffer, tf.uint8)

  label = tf.cast(example['category'], tf.int32)

  return video3D, label

Ensuite, ma fonction d'analyse actuelle ressemble à ceci

def _int64_feature(self, value):
  return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

def _bytes_feature(self, value):
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

def createDataRecord(self, file_name, locations, categories):
    writer = tf.python_io.TFRecordWriter(file_name)

    feature = {}

    for loc, category in zip(locations, categories):
        data = self.3DVideo(loc) # the final array of shape [N_FRAMES, WIDTH, HEIGHT, CHANNEL]

        feature['height'] = self._int64_feature(self.height)
        feature['width'] = self._int64_feature(self.width)
        feature['depth'] = self._int64_feature(self.depth)
        feature['data'] = self._bytes_feature(data.tostring())
        feature['category'] = self._int64_feature(category)

        example = tf.train.Example(features=tf.train.Features(feature=feature))
        writer.write(example.SerializeToString())

    writer.close()

Cela étant dit, mes questions sont:

  1. Je sais que readDataRecord() est faux car il fonctionne sur des cadres individuels. Comment puis-je l'obtenir pour renvoyer des cubes 3D individuels de forme [N_FRAMES, WIDTH, HEIGHT, CHANNEL] avec leur catégorie respective?

  2. Est-ce même une bonne idée de simplement enregistrer le cube 3D entier?

Toute aide ou orientation sera grandement appréciée :)

PS: J'ai examiné d'autres méthodes, y compris video2tfrecord, mais la plupart d'entre elles semblent enregistrer des images individuelles pour chaque vidéo et je ne le veux pas.


1 commentaires

Vous avez probablement vu, mais quand même, stackoverflow.com/questions/48101576/...


3 Réponses :


0
votes

C'est donc ce que j'ai fini par faire pour y parvenir sans avoir à encoder des images individuelles.

J'ai fini par aplatir le cube puis l'écrire à la place comme indiqué ci-dessous:

def readDataRecord(self, record):
    ..........
    feature = \
    {'height': tf.FixedLenFeature([], tf.int64),
     'width': tf.FixedLenFeature([], tf.int64),
     'depth': tf.FixedLenFeature([], tf.int64),
     'data': tf.FixedLenFeature((NUM_FRAMES, WIDTH, HEIGHT, CHANNEL), tf.float32),
     'category': tf.FixedLenFeature([], tf.int64),
    }

    example = tf.parse_single_example(serialized_example, features=feature)

    cube = tf.cast(example['data'], tf.uint8)
    label = tf.cast(example['category'], tf.int32)

    return cube, label

L'analyseur résultant est:

def _cube_feature(self, value):
    return tf.train.Feature(float_list=tf.train.FloatList(value=value))

def createDataRecord(self, name, locations, categories):

    writer = tf.python_io.TFRecordWriter(name)

    feature = {}

    for loc, category in zip(locations, categories):
        data = self.3DVideo(loc)
        .............
        feature['data'] = self._cube_feature(data.flatten())
        feature['category'] = self._int64_feature(category)

        example = tf.train.Example(features=tf.train.Features(feature=feature))
        writer.write(example.SerializeToString())

    writer.close()


0 commentaires

1
votes

L'inconvénient de la réponse acceptée est que vous devez stocker quelque part les dimensions du tableau (NUM_FRAMES, WIDTH, HEIGHT, CHANNEL). La solution de contournement consiste à sérialiser le cube 3D entier à l'aide de tf.io.serialize_tensor(array.astype(...)) , à l'enregistrer sous forme de chaîne d'octets dans TFRecord, puis (après le chargement de TFRecord) à le restaurer à l'aide de tf.io.parse_tensor(bytestring_array_feature, out_type=...) . Voir une belle explication ici: https://stackoverflow.com/a/60283571 ( _bytes_feature défiler jusqu'au paragraphe sur _bytes_feature )


0 commentaires

0
votes

Un autre inconvénient de la réponse acceptée est qu'il en résulte des fichiers de données très volumineux car vous ne tirez pas parti des techniques de compression (Mo de données vidéo se transforment en Go de données vidéo).

Ce que vous devez faire est de stocker les données vidéo sous forme de liste d'images encodées JPEG (article de blog + code de la façon dont cela est fait peuvent être trouvés ici: https://gebob19.github.io/tfrecords/ )


0 commentaires