Sérialiser le nombre variable de masques d'instance binaire avec le format tfrecord de Tensorflow
Pour l'ensemble de données MS Coco 2014, chaque image a un nombre variable de cadres de délimitation et des masques d'instances binaires correspondants qui peuvent être obtenus à partir du polygone d'instance indiqué dans le fichier d'annotation. J'y parviens en utilisant pycocotools (en particulier le fichier coco.py). Maintenant, je souhaite sérialiser les informations d'image en utilisant le format tfrecords de Tensorflow. Après avoir lu les annotations d'un dict python, indexées par chaque identifiant d'image, j'ai pu sérialiser des nombres variables de boîtes englobantes comme:
x_min_values = []
x_max_values = []
y_min_values = []
y_max_values = []
for bb in bounding_boxes:
x_min_values.append(int(bb[0]))
y_min_values.append(int(bb[1]))
x_max_values.append(int(bb[2]))
y_max_values.append(int(bb[3]))
Et puis pour mon dict de fonctionnalités à utiliser dans tf.train.Example
, j'ai converti chaque liste en une liste de fonctionnalités int64 comme:
def _int64_feature_list(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
Mais maintenant, le problème est que puisque les masques d'instance sont en 2 dimensions, je ne suis pas sûr de la stratégie que je devrais utiliser pour les sérialiser. S'il n'y avait qu'un seul masque, comme dans un masque de segmentation, alors je pourrais simplement aplatir le tableau et écrire une liste de fonctionnalités 64 bits, puis utiliser la hauteur et la largeur de l'image pour remodeler le tableau lors de la désérialisation, mais je ne peux pas le faire pour un nombre variable de masques. Toutes les idées appréciées.
Réponses
Besoin d'utiliser FixedLenSequenceFeature comme expliqué ci-dessous:
Un exemple de 2 images comportant chacune 3 et 2 cadres de délimitation
bounding_boxes = []
bounding_boxes.append(np.random.randint(low=0, high=2000,size=(3, 4)))
bounding_boxes.append(np.random.randint(low=0, high=2000,size=(2, 4)))
for i, box in enumerate(bounding_boxes):
print({i},box)
Production:
{0} [[1806 1172 1919 1547]
[1478 1654 498 1689]
[131515 1654 1586]]
{1} [[601 1473 1670 756]
[1791 993 1049 1793]]
#Write tfrecord
def _int64_feature(list_of_ints):
return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))
out_path = './test.tfrec'
with tf.io.TFRecordWriter(out_path) as out:
for box in bounding_boxes:
example = tf.train.Example(features=tf.train.Features(feature={
'boxes': _int64_feature(np.array(box).flatten().tolist()),
}))
out.write(example.SerializeToString())
Vérifiez le tfrecord écrit:
ds = tf.data.TFRecordDataset(out_path)
for i, data in enumerate(ds):
process_each = {
'boxes': tf.io.FixedLenSequenceFeature([], dtype=tf.int64, allow_missing=True),
}
samples = tf.io.parse_example(data, process_each)
print(i, samples['boxes'].numpy().reshape(-1, 4))
Production:
0 [[1806 1172 1919 1547]
[1478 1654 498 1689]
[131515 1654 1586]]
1 [[601 1473 1670 756]
[1791 993 1049 1793]]