Serializuj zmienną liczbę masek instancji binarnych za pomocą formatu tfrecord firmy Tensorflow
W przypadku zestawu danych MS Coco 2014 każdy obraz ma zmienną liczbę obwiedni i odpowiadających im masek instancji binarnych, które można uzyskać z wielokąta instancji podanego w pliku adnotacji. Osiągam to za pomocą pycocotools (w szczególności pliku coco.py). Teraz chcę serializować informacje o obrazie przy użyciu formatu tfrecords firmy Tensorflow. Po przeczytaniu adnotacji do dyktu w Pythonie, indeksowanych przez każdy identyfikator obrazu, byłem w stanie serializować zmienne liczby pól ograniczających, takich jak:
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]))
A potem, aby moja funkcja dyktowania była używana w tf.train.Example
, przekonwertowałem każdą listę na listę funkcji int64 jako:
def _int64_feature_list(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
Ale teraz problem polega na tym, że ponieważ maski instancji są dwuwymiarowe, nie jestem pewien, jaką strategię powinienem użyć, aby je serializować. Gdyby była tylko jedna maska, jak w masce segmentacji, mógłbym po prostu spłaszczyć tablicę i napisać 64-bitową listę funkcji, a następnie użyć wysokości i szerokości obrazu do zmiany kształtu tablicy podczas deserializacji, ale nie mogę tego zrobić dla zmiennej liczby masek. Wszelkie spostrzeżenia mile widziane.
Odpowiedzi
Musisz użyć FixedLenSequenceFeature, jak wyjaśniono poniżej:
Przykład 2 obrazów, z których każdy ma 3 i 2 obwiednie
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)
Wynik:
{0} [[1806 1172 1919 1547]
[1478 1654 498 1689]
[131 515 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())
Sprawdź zapisany tfrecord:
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))
Wynik:
0 [[1806 1172 1919 1547]
[1478 1654 498 1689]
[131 515 1654 1586]]
1 [[601 1473 1670 756]
[1791 993 1049 1793]]