我正在尝试进行不同种类的(图像)数据增强以训练我的神经网络。
我知道tf.image提供了一些增强功能,但是它们太简单了-例如,我只能将图像旋转90度,而不是任何角度。
我也知道tf.keras.preprocessing.image提供随机旋转,随机剪切,随机移位和随机缩放。但是,这些方法只能应用于numpy数组,而不能应用于张量。
我知道我可以先读取图像,使用tf.keras.preprocessing.image中的函数进行增强,然后将这些增强的numpy数组转换为张量。
但是,我只是想知道是否有一种方法可以实现张量方向的扩充,这样我就不必麻烦“图像文件->张量-> numpy数组->张量”过程。 / p>
针对那些想知道如何应用您的变换的人进行更新:
有关详细的源代码,您可能需要检查tf.contrib.image.transform和tf.contrib.image.matrices_to_flat_transforms。
这是我的代码:
def transformImg(imgIn,forward_transform):
t = tf.contrib.image.matrices_to_flat_transforms(tf.linalg.inv(forward_transform))
# please notice that forward_transform must be a float matrix,
# e.g. [[2.0,0,0],[0,1.0,0],[0,0,1]] will work
# but [[2,0,0],[0,1,0],[0,0,1]] will not
imgOut = tf.contrib.image.transform(imgIn, t, interpolation="BILINEAR",name=None)
return imgOut
基本上,上面的代码正在执行
例如,平行于x轴的shear transform是
因此,我们可以实现这样的剪切变换(使用上面定义的transformImg()
):
def shear_transform_example(filename,shear_lambda):
image_string = tf.read_file(filename)
image_decoded = tf.image.decode_jpeg(image_string, channels=3)
img = transformImg(image_decoded, [[1.0,shear_lambda,0],[0,1.0,0],[0,0,1.0]])
return img
img = shear_transform_example("white_square.jpg",0.1)
(请注意img
是张量,不包含将张量转换为图像文件的代码。)
PS
以上代码适用于tensorflow 1.10.1,可能不适用于将来的版本。
老实说,我真的不知道他们为什么设计tf.contrib.image.transform,而我们必须使用另一个函数(tf.linalg.inv)来获得我们想要的东西。我真的希望他们可以将tf.contrib.image.transform更改为可以在a more intuitive way中使用。
答案 0 :(得分:3)
看看tf.contrib.image.transform
。它可以对图像应用一般投影变换。
您还需要查看tf.contrib.image.matrices_to_flat_transforms
才能将仿射矩阵转换为tf.contrib.image.transform
接受的投影格式。
答案 1 :(得分:0)
我通常将tf.data.Dataset
和Dataset.map
和tf.py_func
一起使用。 Dataset.prefetch
意味着通常没有时间成本(只要在CPU上进行预处理所需的时间少于在GPU上运行网络所需的时间)。如果您在多个GPU上进行操作,则可能需要重新考虑,但是以下内容对我来说在单个GPU系统上效果很好。
为简单起见,我假设您将所有映像都放在磁盘上的单独文件中,尽管它可以轻松地适用于zip存档或其他格式,例如hdf5(不适用于.tar
文件-不确定为什么,但我仍然怀疑这是个好主意。)
import tensorflow as tf
from PIL import Image
def map_tf(path_tensor, label_tensor):
# path_tensor and label_tensor correspond to a single example
def map_np(path_str):
# path_str is just a normal string here
image = np.array(Image.load(path_str), dtype=np.uint8)
image = any_cv2_or_numpy_augmentations(image)
return image,
image, = tf.py_func(
map_np, (path_tensor,), Tout=(tf.uint8,), stateful=False)
# any tensorflow operations here.
image = tf.cast(image, tf.float32) / 255
image.set_shape((224, 224, 3))
return image, label
paths, labels = load_image_paths_and_labels()
dataset = tf.data.Dataset.from_tensor_slices((paths, labels))
if is_training:
shuffle_buffer = len(paths) # full shuffling - can be shorter
dataset = dataset.shuffle(shuffle_buffer).repeat()
dataset = dataset.map(map_tf_fn, num_parallel_calls=8)
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(1)
# play with the following if you want - not finalized API, and only in
# more recent version of tensorflow
# dataset = dataset.apply(tf.contrib.data.prefetch_to_device('/gpu:0'))
image_batch, label_batch = dataset.make_one_shot_iterator().get_next()
您也可以在tensorflow中进行解码,并直接在any_cv2_or_numpy_augmentations
中使用py_func
(尽管您不回避在问题中提到的张量-> numpy->张量舞)。我怀疑您会注意到两种方式的性能差异。
检查this answer以获得更多选项。