我想让我的输入图像(张量)在每批中随机向上/向下或向右/向左移动。
例如,我有一批尺寸为[10, 48, 64, 1]
的灰度图像。
如果有一张图片,我知道我可以使用tf.pad和tf.slice(或其他内置函数)
但我希望通过一次操作将随机移位应用于10个不同的图像。
有可能吗?或者我应该使用循环,如tf.scan?
答案 0 :(得分:4)
作为替代方案,您还可以使用tf.contrib.image.transform()并使用参数 a2 和 b2 来翻译图片:
import numpy as np
import tensorflow as tf
image1 = np.array([[[.1], [.1], [.1], [.1]],
[[.2], [.2], [.2], [.2]],
[[.3], [.3], [.3], [.3]],
[[.4], [.4], [.4], [.4]]])
image2 = np.array([[[.1], [.2], [.3], [.4]],
[[.1], [.2], [.3], [.4]],
[[.1], [.2], [.3], [.4]],
[[.1], [.2], [.3], [.4]]])
images = np.stack([image1, image2])
images_ = tf.convert_to_tensor(images, dtype=tf.float32)
shift1_x = 1
shift1_y = 2
shift2_x = -1
shift2_y = 0
transforms_ = tf.convert_to_tensor([[1, 0, -shift1_x, 0, 1, -shift1_y, 0, 0],
[1, 0, -shift2_x, 0, 1, -shift2_y, 0, 0]],
tf.float32)
shifted_ = tf.contrib.image.transform(images=images_,
transforms=transforms_)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
shifted = sess.run([shifted_])
print(shifted)
变换投影矩阵也可以是大小为N x 8的张量,因此可以不同地移动批次的每个图像。这可以通过tf.random_uniform()轻松扩展,以包含每个图像的x / y偏移的一些随机性。
修改强> 对批次的每个图像使用随机移位:
...
images_ = tf.convert_to_tensor(images, dtype=tf.float32)
num_imgs = images.shape[0]
base_ = tf.convert_to_tensor(np.tile([1, 0, 0, 0, 1, 0, 0, 0], [num_imgs, 1]), dtype=tf.float32)
mask_ = tf.convert_to_tensor(np.tile([0, 0, 1, 0, 0, 1, 0, 0], [num_imgs, 1]), dtype=tf.float32)
random_shift_ = tf.random_uniform([num_imgs, 8], minval=-2.49, maxval=2.49, dtype=tf.float32)
transforms_ = base_ + random_shift_ * mask_
shifted_ = tf.contrib.image.transform(images=images_,
transforms=transforms_)
...
编辑2: 为了完成,这里只是另一个辅助函数,它应用随机旋转并转移到批处理的每个单个图像:
def augment_data(input_data, angle, shift):
num_images_ = tf.shape(input_data)[0]
# random rotate
processed_data = tf.contrib.image.rotate(input_data,
tf.random_uniform([num_images_],
maxval=math.pi / 180 * angle,
minval=math.pi / 180 * -angle))
# random shift
base_row = tf.constant([1, 0, 0, 0, 1, 0, 0, 0], shape=[1, 8], dtype=tf.float32)
base_ = tf.tile(base_row, [num_images_, 1])
mask_row = tf.constant([0, 0, 1, 0, 0, 1, 0, 0], shape=[1, 8], dtype=tf.float32)
mask_ = tf.tile(mask_row, [num_images_, 1])
random_shift_ = tf.random_uniform([num_images_, 8], minval=-shift, maxval=shift, dtype=tf.float32)
transforms_ = base_ + random_shift_ * mask_
processed_data = tf.contrib.image.transform(images=processed_data,
transforms=transforms_)
return processed_data
答案 1 :(得分:1)
您在寻找tf.random_crop
和tf.pad
吗?
好吧,当使用tf.random_crop
时,随机移位将应用于批处理中的所有图像。批次内部的转换是相同的,但对于不同的批次可能会有所不同。
如果您想在批处理中使用不同的班次,我认为使用队列/输入管道会更好。有关详情,请参阅https://www.tensorflow.org/programmers_guide/reading_data。
这是我自己项目的一部分示例代码。 self.image_names
是一个Python列表,其中包含所有训练图像的路径。在输入管道中,数据流就像一个流:你只需要处理一个图像,队列自动处理调度事务(一些线程读取数据,一些线程处理数据,一些组单个图像成批,其他人将数据提供给GPU等,以保持整个管道繁忙。在下面的代码中,images
和labels
是队列。也就是说,当你处理这个变量时(就像我在self.data_augmentation
中那样),你可以认为它只包含一个图像,但实际上队列处理其中的每个项目(它就像一个隐式循环) ),然后tf.train.shuffle_batch
将对队列中的训练数据进行混洗,并将它们分组。
def data_augmentation(images):
if FLAGS.random_flip_up_down:
images = tf.image.random_flip_up_down(images)
if FLAGS.random_brightness:
images = tf.image.random_brightness(images, max_delta=0.3)
if FLAGS.random_contrast:
images = tf.image.random_contrast(images, 0.8, 1.2)
return images
def input_pipeline(self, batch_size, num_epochs=None, aug=False):
images_tensor = tf.convert_to_tensor(self.image_names, dtype=tf.string)
labels_tensor = tf.convert_to_tensor(self.labels, dtype=tf.int64)
input_queue = tf.train.slice_input_producer([images_tensor, labels_tensor], num_epochs=num_epochs)
labels = input_queue[1]
images_content = tf.read_file(input_queue[0])
images = tf.image.convert_image_dtype(tf.image.decode_png(images_content, channels=1), tf.float32)
if aug:
images = self.data_augmentation(images)
new_size = tf.constant([FLAGS.image_size, FLAGS.image_size], dtype=tf.int32)
images = tf.image.resize_images(images, new_size)
image_batch, label_batch = tf.train.shuffle_batch([images, labels], batch_size=batch_size, capacity=50000,
min_after_dequeue=10000)
# print 'image_batch', image_batch.get_shape()
return image_batch, label_batch