TensorFlow:如何将相同的图像扭曲应用于多个图像

9

Tensorflow卷积神经网络示例开始,我试图修改模型以具有多个图像作为输入(因此输入不仅有3个输入通道,而且通过叠加图像来使其成倍增加)。为了增强输入,我尝试使用TensorFlow提供的随机图像操作,如翻转、对比度和亮度。我目前将相同的随机扭曲应用于所有输入图像的解决方案是使用这些操作的固定种子值:

def distort_image(image):
  flipped_image = tf.image.random_flip_left_right(image, seed=42)
  contrast_image = tf.image.random_contrast(flipped_image, lower=0.2, upper=1.8, seed=43)
  brightness_image = tf.image.random_brightness(contrast_image, max_delta=0.2, seed=44)
  return brightness_image

在构建图时,对于每个图像都会多次调用此方法,因此我认为对于每个图像,它将使用相同的随机数序列,结果是应用于我的图像输入序列的操作相同。

# ...

# distort images
distorted_prediction = distort_image(seq_record.prediction)
distorted_input = []
for i in xrange(INPUT_SEQ_LENGTH):
    distorted_input.append(distort_image(seq_record.input[i,:,:,:]))
stacked_distorted_input = tf.concat(2, distorted_input)

# Ensure that the random shuffling has good mixing properties.
min_queue_examples = int(num_examples_per_epoch *
                         MIN_FRACTION_EXAMPLES_IN_QUEUE)

# Generate a batch of sequences and prediction by building up a queue of examples.
return generate_sequence_batch(stacked_distorted_input, distorted_prediction, min_queue_examples, 
                               batch_size, shuffle=True)

理论上来说,这很好用。在进行了一些测试后,它确实似乎解决了我的问题。但是过了一段时间后,我发现我遇到了一种竞争条件,因为我使用CNN示例代码的输入管道与多个线程一起运行(这是TensorFlow推荐的方法,可以在运行时提高性能并减少内存消耗):

def generate_sequence_batch(sequence_in, prediction, min_queue_examples,
                        batch_size):
    num_preprocess_threads = 8 # <-- !!!
    sequence_batch, prediction_batch = tf.train.shuffle_batch(
        [sequence_in, prediction],
        batch_size=batch_size,
        num_threads=num_preprocess_threads,
        capacity=min_queue_examples + 3 * batch_size,
        min_after_dequeue=min_queue_examples)
return sequence_batch, prediction_batch

由于多个线程创建我的示例,不再保证所有图像操作按正确顺序执行(指随机操作的正确顺序)。

我陷入了完全无法解决的困境。请问有人知道如何解决这个问题,将同样的图像扭曲应用于多个图像吗?

我的一些想法:

  • 我考虑在这些图像扭曲方法周围进行一些同步,但我找不到TensorFlow提供的任何东西
  • 我尝试自己使用tf.random_uniform()生成一个随机数,例如随机亮度变化,并将此值用于tf.image.adjust_contrast()。但是,TensorFlow随机生成器的结果始终是张量,并且我没有找到一种使用此张量作为tf.image.adjust_contrast()的参数的方法,该方法期望其对比度因子参数为简单的float32。
  • 一种(部分)可行的解决方案是使用tf.concat()将所有图像组合成一个大图像,应用随机操作以更改对比度和亮度,然后在图像之后拆分。但是,这对于随机翻转不起作用,因为这会(至少在我的情况下)改变图像的顺序,而且没有办法检测tf.image.random_flip_left_right()是否已执行翻转,这将需要如有必要修复图像的错误顺序。
2个回答

10

以下是我查看tensorflow中random_flip_up_down和random_flip_left_right代码后得出的结论:

def image_distortions(image, distortions):
    distort_left_right_random = distortions[0]
    mirror = tf.less(tf.pack([1.0, distort_left_right_random, 1.0]), 0.5)
    image = tf.reverse(image, mirror)
    distort_up_down_random = distortions[1]
    mirror = tf.less(tf.pack([distort_up_down_random, 1.0, 1.0]), 0.5)
    image = tf.reverse(image, mirror)
    return image


distortions = tf.random_uniform([2], 0, 1.0, dtype=tf.float32)
image = image_distortions(image, distortions)
label = image_distortions(label, distortions)

这就是我一直在寻找的。谢谢! - b3nk4n

1
我会使用tf.case来完成类似的操作。它允许你指定在某些条件下返回什么https://www.tensorflow.org/api_docs/python/tf/case
import tensorflow as tf

def distort(image, x):
    # flip vertically, horizontally, both, or do nothing
    image = tf.case({
        tf.equal(x,0): lambda: tf.reverse(image,[0]),
        tf.equal(x,1): lambda: tf.reverse(image,[1]),
        tf.equal(x,2): lambda: tf.reverse(image,[0,1]),
    }, default=lambda: image, exclusive=True)

    return image

def random_distortion(image):
    x = tf.random_uniform([1], 0, 4, dtype=tf.int32)
    return distort(image, x[0])

检查它是否有效。

import numpy as np
import matplotlib.pyplot as plt

# create image
image = np.zeros((25,25))
image[:10,5:10] = 1.
# create subplots
fig, axes = plt.subplots(2,2)
for i in axes.flatten(): i.axis('off')

with tf.Session() as sess:
    for i in range(4):
        distorted_img = sess.run(distort(image, i))
        axes[i % 2][i // 2].imshow(distorted_img, cmap='gray')

    plt.show()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接