官网: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)
这样的增强函数时,它大致会这样做:
因此,如果您将同一批次多次送入确定模式运行的增强器,您将多次获得完全相同增强的图像。通常,你不会想这样,所以默认设置成随机模式。但是,如果您有两批或更多批需要相同扩充的图像,则确定性模式是首选设置,如输入的是孪生网络或视频序列的多个帧。 然而,最常见的是同一图像的不同类型数据。例如,如果图像和边界框,边界框必须以与图像完全相同的方式进行扩充。
让我们用三个相同的图像为这两种模式写个样例。随机模式的结果应该不同,而确定模式的结果应该是相同的。
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
)
)
上面的结果显示第一行的随机模式和第二行的确定模式。 正如预期的那样,随机模式下两批的增强结果不同,但在确定模式下则相同。
为了提供更现实的示例,我们现在在其上增加图像和一组关键点。 图像和关键点增强的功能彼此分离,因此我们必须在调用它们之前切换到确定模式。 否则,我们的关键点将与图像的增强方式不同。
让我们加载一个带有关键点的示例图像,并将这两个图像可视化。
image = ia.quokka(size=0.25)
keypoints = ia.quokka_keypoints(size=0.25)
ia.imshow(
np.hstack([
image,
keypoints.draw_on_image(image)
])
)
现在将两者转换成批次。
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")
注意到大多数情况下的关键点与图像不匹配,有时匹配仅仅是出于偶然。
我们现在通过再次执行相同的代码来修复此问题,但这次使用确定性模式。
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")
正常了。现在即使在增强后,图像和关键点也会对齐。 但结果仍然不是我们想要的,因为它们对于所有批次都是相同的。 如果我们在没有改变数据集的情况下对此进行训练,我们将始终在每个图像之间获得相同的增强。 这对于大多数用例中的增强过程,因为这一个静态数据集转换为另一个静态数据集。 为了解决这个问题,我们必须不断切换到确定模式,每批次一次。 在每次这样的切换时,增强器的随机数发生器被设置为不同的状态,产生不同的增强。
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")
这就是我们想要的:批次和图像之间的不同增强,但每个图像及其上的关键点都是相同的。 在实际实验中,您当然不会手动调用to_deterministic()
三次,而只是在加载下一批数据后将调用置于训练循环内。
下一章:imgaug数据增强神器:第三章 调用多核CPU