TensorFlow:如何对多个图像应用相同的图像失真
TensorFlow: How to apply the same image distortion to multiple images
从 Tensorflow CNN example 开始,我尝试修改模型以将多个图像作为输入(这样输入不仅具有 3 个输入通道,而且通过堆叠图像获得 3 的倍数)。
为了增加输入,我尝试使用 random image operations,例如 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)
理论上,这可以正常工作。在进行了一些测试后,这似乎真的解决了我的问题。但是过了一会儿,我发现我遇到了 race-condition,因为我使用了多线程的 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因为它的 contrast_factor 参数。
- 一个(部分)可行的解决方案是使用 tf.concat() 将所有图像组合成一个巨大的图像,应用随机操作来改变对比度和亮度,然后拆分图像。但这不适用于随机翻转,因为这会(至少在我的情况下)改变图像的顺序,并且无法检测是否 tf.image.random_flip_left_right() 是否执行了翻转,必要时需要修复错误的图像顺序。
这是我通过查看 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)
我会使用 tf.case
做这样的事情。它允许您指定 return 如果某些条件成立 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()
从 Tensorflow CNN example 开始,我尝试修改模型以将多个图像作为输入(这样输入不仅具有 3 个输入通道,而且通过堆叠图像获得 3 的倍数)。 为了增加输入,我尝试使用 random image operations,例如 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)
理论上,这可以正常工作。在进行了一些测试后,这似乎真的解决了我的问题。但是过了一会儿,我发现我遇到了 race-condition,因为我使用了多线程的 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因为它的 contrast_factor 参数。
- 一个(部分)可行的解决方案是使用 tf.concat() 将所有图像组合成一个巨大的图像,应用随机操作来改变对比度和亮度,然后拆分图像。但这不适用于随机翻转,因为这会(至少在我的情况下)改变图像的顺序,并且无法检测是否 tf.image.random_flip_left_right() 是否执行了翻转,必要时需要修复错误的图像顺序。
这是我通过查看 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)
我会使用 tf.case
做这样的事情。它允许您指定 return 如果某些条件成立 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()