Наборы данных Tensorflow: Обрезка/изменение размера изображений на пакет после набора данных.пакет()

0

Вопрос

Можно ли обрезать/изменять размер изображений за пакет ?

Я использую API набора данных Tensorflow, как показано ниже:

dataset = dataset.shuffle().repeat().batch(batch_size, drop_remainder=True)

Я хочу, чтобы в пакете все изображения имели одинаковый размер. Однако в разных партиях он может иметь разные размеры.

Например, 1-я партия содержит все изображения формы (размер пакета, 300, 300, 3). Следующая партия может содержать изображения формы (размер пакета, 224, 224, 3). Другая партия может иметь изображения формы (размер пакета, 400, 400, 3).

В принципе, я хочу, чтобы пакеты имели симметричную форму, однако все изображения в пакете имеют статические формы.

Если мы поступим так, как следует:

dataset = dataset.shuffle().repeat().batch(batch_size, drop_remainder=True).map(lambda x, y: map_fn(x, y))

Применяется ли вышеуказанная функция .map() к каждому пакету отдельно или ко всему набору данных ?

Если выше .map() не применяется к каждой партии отдельно, как мы можем это сделать ? Можем ли мы определить любой итератор после dataset.batch(), применить tf.image.crop_and_resize() к каждому изображению в пакете, а затем использовать dataset.concatenate() для объединения всех преобразованных пакетов ?

Я создаю набор данных, как показано ниже:

# Dataset creation (read image data from files of COCO dataset)
dataset = tf.data.Dataset.list_files(self._file_pattern, shuffle=False)
dataset = dataset.shard(dataset_num_shards, dataset_shard_index)
dataset = dataset.shuffle(tf.cast(256 / dataset_num_shards, tf.int64))
dataset = dataset.interleave(map_func=tf.data.TFRecordDataset(filename).prefetch(1), cycle_length=32, block_length=1, num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset = dataset.map(tf_example_decoder.TfExampleDecoder().decode, num_parallel_calls=64)
dataset = dataset.shuffle(64).repeat()
# Parse each image for preprocessing
dataset = dataset.map(lambda data, _: _parse_example(data), num_parallel_calls=64)
dataset = dataset.batch(batch_size=batch_size, drop_remainder=True)

# Below code suggested by you to resize images to fixed shape in each batch
def resize_data(images, labels):
    tf.print('Original shape -->', tf.shape(images))
    SIZE = (300, 300)
    return tf.image.resize(images, SIZE), labels
dataset = dataset.map(resize_data)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)

tf.estimator.Estimator(...).train(
        input_fn=dataset,
        steps=steps,
        hooks=train_hooks)
python tensorflow tensorflow-datasets
2021-11-24 05:50:45
1

Лучший ответ

1

В общем, вы можете попробовать что-то вроде этого:

import tensorflow as tf
import numpy as np

dataset1 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 300, 300, 3)))
dataset2 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 224, 224, 3)))
dataset3 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 400, 400, 3)))
dataset = dataset1.concatenate(dataset2.concatenate(dataset3))
dataset = dataset.shuffle(1).repeat().batch(32, drop_remainder=True)

def resize_data(images):
  tf.print('Original shape -->', tf.shape(images))
  SIZE = (180, 180)

  return tf.image.resize(images, SIZE)

dataset = dataset.map(resize_data)

for images in dataset.take(3):
  tf.print('New shape -->', tf.shape(images))
Original shape --> [32 300 300 3]
New shape --> [32 180 180 3]
Original shape --> [32 224 224 3]
New shape --> [32 180 180 3]
Original shape --> [32 400 400 3]
New shape --> [32 180 180 3]

Вы также можете использовать tf.image.resize_with_crop_or_pad если ты хочешь:

def resize_data(images):
  tf.print('Original shape -->', tf.shape(images))
  SIZE = (180, 180)
  return tf.image.resize_with_crop_or_pad(images, SIZE[0], SIZE[1])

dataset = dataset.map(resize_data)

for images in dataset.take(3):
  tf.print('New shape -->', tf.shape(images))

Обратите внимание, что с помощью repeat() создаст бесконечный набор данных.

Обновление 1

Если вам нужен случайный размер для каждой партии, попробуйте что-нибудь вроде этого:

import tensorflow as tf
import numpy as np

dataset1 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 300, 300, 3)))
dataset2 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 224, 224, 3)))
dataset3 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 400, 400, 3)))
dataset = dataset1.concatenate(dataset2.concatenate(dataset3))
dataset = dataset.batch(32, drop_remainder=True).shuffle(96)


def resize_data(images):
  batch_size = tf.shape(images)[0]
  images_resized = tf.TensorArray(dtype=tf.float32, size = 0, dynamic_size=True)
  SIZE = tf.random.uniform((2,), minval=300, maxval=500, dtype=tf.int32)
  for i in range(batch_size):
    images_resized = images_resized.write(images_resized.size(), tf.image.resize(images[i], SIZE))
  return images_resized.stack()

dataset = dataset.map(resize_data)

for images in dataset:
  tf.print('New shape -->', tf.shape(images))
New shape --> [32 392 385 3]
New shape --> [32 468 459 3]
New shape --> [32 466 461 3]

Обновление 2

Очень гибкий вариант, который работает для любого размера пакета, будет выглядеть следующим образом:

import tensorflow as tf
import numpy as np

dataset1 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 300, 300, 3)))
dataset2 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 224, 224, 3)))
dataset3 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 400, 400, 3)))
dataset = dataset1.concatenate(dataset2.concatenate(dataset3))

def resize_and_batch(dataset, batch_size):
  final_dataset = None
  duration = len(dataset)//batch_size
  random_sizes = [tf.random.uniform((2,), minval=300, maxval=500, dtype=tf.int32) for _ in range(duration)]

  for i, size in zip(range(duration), random_sizes):
    idx = i * batch_size
    if i == 0:
      final_dataset = tf.data.Dataset.from_tensor_slices([tf.image.resize(x, size) for x in dataset.take(batch_size)])
    else:
      final_dataset = final_dataset.concatenate(tf.data.Dataset.from_tensor_slices([tf.image.resize(x, size) for x in dataset.skip(idx).take(batch_size)]))
  return final_dataset

batch_size = 10
ds = resize_and_batch(dataset, batch_size)
ds = ds.batch(batch_size).shuffle(len(ds))
for images in ds:
 tf.print('New shape -->', images.shape)
New shape --> TensorShape([10, 399, 348, 3])
New shape --> TensorShape([10, 356, 329, 3])
New shape --> TensorShape([10, 473, 373, 3])
New shape --> TensorShape([10, 489, 489, 3])
New shape --> TensorShape([10, 421, 335, 3])
New shape --> TensorShape([10, 447, 455, 3])
New shape --> TensorShape([10, 355, 382, 3])
New shape --> TensorShape([10, 310, 396, 3])
New shape --> TensorShape([10, 345, 356, 3])
2021-12-01 14:51:04

Это выглядит хорошо. Однако у меня все еще ничего не получается. Когда я пытаюсь обучить модель, она выдает ошибку, как показано ниже: INVALID_ARGUMENT: Cannot add tensor to the batch: number of elements does not match. Shapes are: [tensor]: [640,426,3], [batch]: [480,640,3] Несмотря на то, что я дал РАЗМЕР = (300, 300) в tf.image.resize(изображения, РАЗМЕР), пакет имеет РАЗМЕР = (480, 640). И поскольку следующее изображение имеет другой РАЗМЕР = (640, 426), его не удалось добавить в пакет. Это означает, что каким-то образом он не может применить функцию .map() к каждой отдельной партии. Есть какая-нибудь помощь/идея ?
Avid Learner

Не могли бы вы добавить код о том, как вы создаете свои наборы данных, в свой вопрос? Думаю, я догадываюсь, в чем может быть проблема.
AloneTogether

Я обновил вопрос о том, как я создаю набор данных. Жду вашего ответа.
Avid Learner

Обновленный ответ-
AloneTogether

batch_size=16. Это выдает ту же ошибку с размером пакета > 1.>
Avid Learner

Трудно понять, что именно вы делаете без какого-либо доступа к набору данных, который вы используете, и переменным, которые вы определили где-то еще. Проблема, вероятно, в том, что в каждой партии нет изображений одинаковой формы.
AloneTogether

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................