快速总结:
镜像(flip)
旋转(rotation)
缩放(scale)
裁剪(crop)
平移(translation)
高斯噪声(gaussion noise)
图像亮度、饱和度和对比度变化
PCA Jittering
Lable shuffle
SDA
生成对抗网络(generative adversi network)
注:crop、flip、scale是大杀器,color augmentation甚至导致反作用。
您可以水平和垂直翻转(flip)图像。某些框架不提供垂直翻转功能。但是,垂直翻转相当于将图像旋转180度然后执行水平翻转。以下是翻转图像的示例[1]。
image
从左边开始,为原始图像,然后水平翻转图像,然后垂直翻转图像。
您可以使用下面tensorflow的代码执行翻转。数据增广因子为 2到4倍
# NumPy.'img' = A single image.
flip_1 = np.fliplr(img)
# TensorFlow. 'x' = A placeholder for an image.
shape = [height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = shape)
flip_2 = tf.image.flip_up_down(x)
flip_3 = tf.image.flip_left_right(x)
flip_4 = tf.image.random_flip_up_down(x)
flip_5 = tf.image.random_flip_left_right(x)
关于此操作需要注意的一件事是旋转后图像尺寸可能无法保留。如果您的图像是正方形,则以直角旋转它将保留图像大小。如果它是一个矩形,旋转180度将保持大小。以更精细(finer)的角度旋转图像也会改变最终的图像尺寸。我们将在下一节中看到我们如何处理这个问题。以下是以直角旋转的方形图像的示例。
image
上图从左向右,图像相对于前一个图像顺时针(clockwise)旋转90度。
您可以使用下面tensorflow的代码执行翻转。数据增广因子为 2到4倍
# Placeholders: 'x' = A single image, 'y' = A batch of images
# 'k' denotes the number of 90 degree anticlockwise rotations
shape = [height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = shape)
rot_90 = tf.image.rot90(img, k=1)
rot_180 = tf.image.rot90(img, k=2)
# To rotate in any angle. In the example below, 'angles' is in radians
shape = [batch, height, width, 3]
y = tf.placeholder(dtype = tf.float32, shape = shape)
rot_tf_180 = tf.contrib.image.rotate(y, angles=3.1415)
# Scikit-Image. 'angle' = Degrees. 'img' = Input Image
# For details about 'mode', checkout the interpolation section below.
rot = skimage.transform.rotate(img, angle=45, mode='reflect')
图像可以向外缩放(放大)或者向内缩放(缩小)。如向外缩放(scaling outward)时,最终图像尺寸将大于原始图像尺寸,然后大多数图像框架从放大的新图像中剪切出一个部分,其大小等于原始图像。我们将在下一节中处理向内缩放,因为它会缩小图像大小,迫使我们对超出边界的内容做出假设。以下是放大的示例或图像。
image
从左边开始,为原始图像,图像放大10%再裁剪,图像放大20%再裁剪
您可以使用scikit-image使用以下命令执行缩放。数据增广因子=任意(arbitrary)。
# Scikit Image. 'img' = Input Image, 'scale' = Scale factor
# For details about 'mode', checkout the interpolation section below.
scale_out = skimage.transform.rescale(img, scale=2.0, mode='constant')
scale_in = skimage.transform.rescale(img, scale=0.5, mode='constant')
# Don't forget to crop the images back to the original size (for
# scale_out)
与缩放不同,我们只是从原始图像中随机抽样(sample)一个部分。然后,我们将此部分的大小调整为原始图像大小。这种方法通常称为随机裁剪(random cropping)。以下是随机裁剪的示例。仔细观察,您会发现此方法与缩放之间的区别。
注:数据增广中的缩放与裁剪区别在于crop和resize的顺序,缩放是先resize再crop,而裁剪时先crop再resize。顺序不同,对生成的图像影响很大,所以缩放和裁剪不能混为一谈。
image
从左边开始,为原始图像,从左上角裁剪的正方形区域,然后是从右下角裁剪的正方形区域。将裁剪的局部区域 resize为原始图像大小。
您可以使用下面tensorflow的代码执行随机裁剪。数据增广因子=任意。
# TensorFlow. 'x' = A placeholder for an image.
original_size = [height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = original_size)
# Use the following commands to perform random crops
crop_size = [new_height, new_width, channels]
seed = np.random.randint(1234)
x = tf.random_crop(x, size = crop_size, seed = seed)
output = tf.images.resize_images(x, size = original_size)
平移(translation)只涉及沿X或Y方向(或两者)移动图像。在下面的示例中,我们假设图像在其边界之外具有黑色背景,并且做适当的平移。这种增广方法非常有用,因为大多数对象几乎可以位于图像的任何位置。这迫使你的卷积神经网络可以无处不在的"look"。
image
从左边开始,原始图像,图像向右平移,图像向上平移。
您可以使用下面tensorflow的代码执行平移。数据增广因子=任意。
# pad_left, pad_right, pad_top, pad_bottom denote the pixel
# displacement. Set one of them to the desired value and rest to 0
shape = [batch, height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = shape)
# We use two functions to get our desired augmentation
x = tf.image.pad_to_bounding_box(x, pad_top, pad_left, height + pad_bottom + pad_top, width + pad_right + pad_left)
output = tf.image.crop_to_bounding_box(x, pad_bottom, pad_right, height, width)
当您的神经网络试图学习可能无用的高频特征(大量出现的图案)时,通常会发生过拟合(over-fitting)。具有零均值的高斯噪声基本上在所有频率中具有数据点(data points),从而有效地使高频特征失真(distorting)。这也意味着较低频率的元素(通常是您的预期数据)也会失真,但你的神经网络可以学会超越它。添加适量的噪声可以增强学习能力。
简单来说,给图像添加高斯噪声,会生成极为有用的图像,增加了有效样本,对训练网络有好处。
椒盐噪声(the salt and pepper noise)是一种常见的高斯噪声,它表现为随机的黑白像素在图像中传播。这类似于通过向图像添加高斯噪声而产生的效果,但可能具有较低的信息失真水平(lower information distortion level)。
image
从左边开始,原始图像,添加了高斯噪声的图像,添加了椒盐噪声的图像
您可以使用下面tensorflow的代码为图像添加高斯噪声。数据增广因子=2x。
#TensorFlow. 'x' = A placeholder for an image.
shape = [height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = shape)
# Adding Gaussian noise
noise = tf.random_normal(shape=tf.shape(x), mean=0.0, stddev=1.0,
dtype=tf.float32)
output = tf.add(x, noise)
其实还有一些基本的数据增广方法,如色彩抖动(color jittering)、对比度变换(contrast)[2]、PCA Jittering
参考:
Data Augmentation | How to use Deep Learning when you have Limited Data—Part 2
http://ai.52learn.online/