imgaug数据增强神器:第二章 随机模式和确定模式

官网:https://imgaug.readthedocs.io/en/latest/
教程:https://nbviewer.jupyter.org/github/aleju/imgaug-doc/blob/master/notebooks/A02 - Stochastic and Deterministic Augmentation.ipynb







一、随机模式和确定模式

imgaug将其增强分为两种模式:随机模式和确定模式。两者都执行几乎相同的步骤。调用augment_images(images)这样的增强函数时,它大致会这样做:

  • 随机模式:
    1. 从随机数生成器RR开始
    2. RR复制到RcR_c
    3. RcR_c中抽取随机值
    4. 基于采样的随机值增强图像
    5. 舍弃RcR_c
    6. 转发RR(以便下一轮产生不同的随机数)
  • 确定模式:
    1. 从随机数生成器RR开始
    2. RR复制到RcR_c
    3. RcR_c中抽取随机值
    4. 基于采样的随机值增强图像
    5. 舍弃RcR_c
    6. [不同点] 保持RR不变(或者以某种方式将其重置为(1)中的状态)。因此,下一个调用将使用与步骤(3)中的相同样本。

因此,如果您将同一批次多次送入确定模式运行的增强器,您将多次获得完全相同增强的图像。通常,你不会想这样,所以默认设置成随机模式。但是,如果您有两批或更多批需要相同扩充的图像,则确定性模式是首选设置,如输入的是孪生网络或视频序列的多个帧。 然而,最常见的是同一图像的不同类型数据。例如,如果图像和边界框,边界框必须以与图像完全相同的方式进行扩充。




二、可视化随机和确定模式

让我们用三个相同的图像为这两种模式写个样例。随机模式的结果应该不同,而确定模式的结果应该是相同的。

import numpy as np
import imgaug as ia
import imgaug.augmenters as iaa
%matplotlib inline
ia.seed(2)

aug = iaa.Affine(translate_px=(-30, 30), rotate=(-20, 20), cval=255)
image = ia.quokka(size=0.15)
batches = [[image] * 3, [image] * 3]  # two batches of each three images

# augment in stochastic mode
images_stochastic = [aug.augment_images(batch) for batch in batches]

# augment in deterministic mode
aug_det = aug.to_deterministic()
images_deterministic = [aug_det.augment_images(batch) for batch in batches]

# visualize
whitespace = np.full(image.shape, 255, dtype=np.uint8)
ia.imshow(
    ia.draw_grid(
        images_stochastic[0] + [whitespace] + images_stochastic[1] +  # first row
        images_deterministic[0] + [whitespace] + images_deterministic[1],  # second row
        rows=2,
        cols=2*3
    )
)

imgaug数据增强神器:第二章 随机模式和确定模式

上面的结果显示第一行的随机模式和第二行的确定模式。 正如预期的那样,随机模式下两批的增强结果不同,但在确定模式下则相同。




三、增加图像和关键点

为了提供更现实的示例,我们现在在其上增加图像和一组关键点。 图像和关键点增强的功能彼此分离,因此我们必须在调用它们之前切换到确定模式。 否则,我们的关键点将与图像的增强方式不同。

让我们加载一个带有关键点的示例图像,并将这两个图像可视化。

image = ia.quokka(size=0.25)
keypoints = ia.quokka_keypoints(size=0.25)

ia.imshow(
    np.hstack([
        image,
        keypoints.draw_on_image(image)
    ])
)

imgaug数据增强神器:第二章 随机模式和确定模式

现在将两者转换成批次。

BATCH_SIZE = 4
images_batch = [image] * BATCH_SIZE
keypoints_batch = [keypoints] * BATCH_SIZE

现在使用仿射变换来增强它们。 我们从一组可能的旋转(15的倍数)中选择一个随机旋转。 我们首先在这里使用随机模式,并且将在下面进一步看到,在增强图像和相应的关键点时选择随机模式是糟糕的选择。

aug = iaa.Affine(rotate=[0, 15, 30, 45, 60])

# stochastic mode
images_aug1 = aug.augment_images(images_batch)
images_aug2 = aug.augment_images(images_batch)
images_aug3 = aug.augment_images(images_batch)
keypoints_aug1 = aug.augment_keypoints(keypoints_batch)
keypoints_aug2 = aug.augment_keypoints(keypoints_batch)
keypoints_aug3 = aug.augment_keypoints(keypoints_batch)

现在我们将结果可视化。 每行包含一个增强批次的结果。

import matplotlib.pyplot as plt

# draw keypoints on images and convert the results to a single image
def draw_and_merge(ims, kps):
    return np.hstack([kp_i.draw_on_image(im_i) for im_i, kp_i in zip(ims, kps)])

fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(15, 8))
axes[0].imshow(draw_and_merge(images_aug1, keypoints_aug1))
axes[1].imshow(draw_and_merge(images_aug2, keypoints_aug2))
axes[2].imshow(draw_and_merge(images_aug3, keypoints_aug3))
for i in range(3):
    axes[i].set_title("Batch %d" % (i+1,))
    axes[i].axis("off")

imgaug数据增强神器:第二章 随机模式和确定模式
注意到大多数情况下的关键点与图像不匹配,有时匹配仅仅是出于偶然。

我们现在通过再次执行相同的代码来修复此问题,但这次使用确定性模式。

aug_det = aug.to_deterministic()  # <- this changed

images_aug1 = aug_det.augment_images(images_batch)
images_aug2 = aug_det.augment_images(images_batch)
images_aug3 = aug_det.augment_images(images_batch)
keypoints_aug1 = aug_det.augment_keypoints(keypoints_batch)
keypoints_aug2 = aug_det.augment_keypoints(keypoints_batch)
keypoints_aug3 = aug_det.augment_keypoints(keypoints_batch)

并再次运行相同的可视化代码:

# draw keypoints on images and convert the results to a single image
def draw_and_merge(ims, kps):
    return np.hstack([kp_i.draw_on_image(im_i) for im_i, kp_i in zip(ims, kps)])

fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(15, 8))
axes[0].imshow(draw_and_merge(images_aug1, keypoints_aug1))
axes[1].imshow(draw_and_merge(images_aug2, keypoints_aug2))
axes[2].imshow(draw_and_merge(images_aug3, keypoints_aug3))
for i in range(3):
    axes[i].set_title("Batch %d" % (i+1,))
    axes[i].axis("off")

imgaug数据增强神器:第二章 随机模式和确定模式

正常了。现在即使在增强后,图像和关键点也会对齐。 但结果仍然不是我们想要的,因为它们对于所有批次都是相同的。 如果我们在没有改变数据集的情况下对此进行训练,我们将始终在每个图像之间获得相同的增强。 这对于大多数用例中的增强过程,因为这一个静态数据集转换为另一个静态数据集。 为了解决这个问题,我们必须不断切换到确定模式,每批次一次。 在每次这样的切换时,增强器的随机数发生器被设置为不同的状态,产生不同的增强。

aug_det        = aug.to_deterministic()
images_aug1    = aug_det.augment_images(images_batch)
keypoints_aug1 = aug_det.augment_keypoints(keypoints_batch)

aug_det        = aug.to_deterministic()
images_aug2    = aug_det.augment_images(images_batch)
keypoints_aug2 = aug_det.augment_keypoints(keypoints_batch)

aug_det        = aug.to_deterministic()
images_aug3    = aug_det.augment_images(images_batch)
keypoints_aug3 = aug_det.augment_keypoints(keypoints_batch)

现在可视化结果:

fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(15, 8))
axes[0].imshow(draw_and_merge(images_aug1, keypoints_aug1))
axes[1].imshow(draw_and_merge(images_aug2, keypoints_aug2))
axes[2].imshow(draw_and_merge(images_aug3, keypoints_aug3))
for i in range(3):
    axes[i].set_title("Batch %d" % (i+1,))
    axes[i].axis("off")

imgaug数据增强神器:第二章 随机模式和确定模式
这就是我们想要的:批次和图像之间的不同增强,但每个图像及其上的关键点都是相同的。 在实际实验中,您当然不会手动调用to_deterministic()三次,而只是在加载下一批数据后将调用置于训练循环内。

下一章:imgaug数据增强神器:第三章 调用多核CPU