imgaug 简介和安装

imgaug 简介

imgaug是计算机视觉任务中常用的一个数据增强的包,相比于torchvision.transforms,它提供了更多的数据增强方法,因此在各种竞赛中,人们广泛使用imgaug来对数据进行增强操作。

  1. Github 地址:imgaug
  2. Readthedocs:imgaug
  3. 官方提供 notebook 例程:notebook

imgaug 的安装

imgaug 的安装方法和其他的 Python 包类似,我们可以通过以下两种方式进行安装

conda

1
2
conda config --add channels conda-forge
conda install imgaug

pip

1
2
3
4
5
6
7
#  install imgaug either via pypi

pip install imgaug

# install the latest version directly from github

pip install git+https://github.com/aleju/imgaug.git

imgaug 的使用

imgaug 仅仅提供了图像增强的一些方法,但是并未提供图像的 IO 操作,因此我们需要使用一些库来对图像进行导入,建议使用 imageio 进行读入,如果使用的是 opencv 进行文件读取的时候,需要进行手动改变通道,将读取的 BGR 图像转换为 RGB 图像。除此以外,当我们用 PIL.Image 进行读取时,因为读取的图片没有 shape 的属性,所以我们需要将读取到的 img 转换为 np.array()的形式再进行处理。因此官方的例程中也是使用 imageio 进行图片读取。

单张图片处理

在该单元,我们仅以几种数据增强操作为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import imageio
import imgaug as ia
%matplotlib inline

# 图片的读取
img = imageio.imread("./Lenna.jpg")

# 使用Image进行读取
# img = Image.open("./Lenna.jpg")
# image = np.array(img)
# ia.imshow(image)

# 可视化图片
ia.imshow(img)

现在我们已经得到了需要处理的图片,imgaug包含了许多从Augmenter继承的数据增强的操作。在这里我们以Affine为例子。

1
2
3
4
5
6
7
8
9
from imgaug import augmenters as iaa

# 设置随机数种子
ia.seed(4)

# 实例化方法
rotate = iaa.Affine(rotate=(-4,45))
img_aug = rotate(image=img)
ia.imshow(img_aug)

这是对一张图片进行一种操作方式,但实际情况下,我们可能对一张图片做多种数据增强处理。这种情况下,我们就需要利用imgaug.augmenters.Sequential()来构造我们数据增强的 pipline,该方法与torchvison.transforms.Compose()相类似。

1
2
3
4
5
iaa.Sequential(children=None, # Augmenter集合
random_order=False, # 是否对每个batch使用不同顺序的Augmenter list
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
6
7
8
9
# 构建处理序列
aug_seq = iaa.Sequential([
iaa.Affine(rotate=(-25,25)),
iaa.AdditiveGaussianNoise(scale=(10,60)),
iaa.Crop(percent=(0,0.2))
])
# 对图片进行处理,image不可以省略,也不能写成images
image_aug = aug_seq(image=img)
ia.imshow(image_aug)

总的来说,对单张图片处理的方式基本相同,我们可以根据实际需求,选择合适的数据增强方法来对数据进行处理。

对批次图片进行处理

在实际使用中,我们通常需要处理更多份的图像数据。此时,可以将图形数据按照 NHWC 的形式或者由列表组成的 HWC 的形式对批量的图像进行处理。主要分为以下两部分,对批次的图片以同一种方式处理和对批次的图片进行分部分处理。

对批次的图片以同一种方式处理

对一批次的图片进行处理时,我们只需要将待处理的图片放在一个list中,并将函数的 image 改为 images 即可进行数据增强操作,具体实际操作如下:

1
2
3
images = [img,img,img,img,]
images_aug = rotate(images=images)
ia.imshow(np.hstack(images_aug))

我们就可以得到如下的展示效果:


在上述的例子中,我们仅仅对图片进行了仿射变换,同样的,我们也可以对批次的图片使用多种增强方法,与单张图片的方法类似,我们同样需要借助Sequential来构造数据增强的 pipline。

1
2
3
4
5
6
7
8
9
10
aug_seq = iaa.Sequential([
iaa.Affine(rotate=(-25, 25)),
iaa.AdditiveGaussianNoise(scale=(10, 60)),
iaa.Crop(percent=(0, 0.2))
])

# 传入时需要指明是images参数
images_aug = aug_seq.augment_images(images = images)
#images_aug = aug_seq(images = images)
ia.imshow(np.hstack(images_aug))

对批次的图片分部分处理

imgaug 相较于其他的数据增强的库,有一个很有意思的特性,即就是我们可以通过imgaug.augmenters.Sometimes()对 batch 中的一部分图片应用一部分 Augmenters,剩下的图片应用另外的 Augmenters。

1
2
3
4
5
6
iaa.Sometimes(p=0.5,  # 代表划分比例
then_list=None, # Augmenter集合。p概率的图片进行变换的Augmenters。
else_list=None, #1-p概率的图片会被进行变换的Augmenters。注意变换的图片应用的Augmenter只能是then_list或者else_list中的一个。
name=None,
deterministic=False,
random_state=None)

对不同大小的图片进行处理

上面提到的图片都是基于相同的图像。以下的示例具有不同图像大小的情况,我们从维基百科加载三张图片,将它们作为一个批次进行扩充,然后一张一张地显示每张图片。具体的操作跟单张的图片都是十分相似,因此不做过多赘述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 构建pipline
seq = iaa.Sequential([
iaa.CropAndPad(percent=(-0.2, 0.2), pad_mode="edge"), # crop and pad images
iaa.AddToHueAndSaturation((-60, 60)), # change their color
iaa.ElasticTransformation(alpha=90, sigma=9), # water-like effect
iaa.Cutout() # replace one squared area within the image by a constant intensity value
], random_order=True)

# 加载不同大小的图片
images_different_sizes = [
imageio.imread("https://upload.wikimedia.org/wikipedia/commons/e/ed/BRACHYLAGUS_IDAHOENSIS.jpg"),
imageio.imread("https://upload.wikimedia.org/wikipedia/commons/c/c9/Southern_swamp_rabbit_baby.jpg"),
imageio.imread("https://upload.wikimedia.org/wikipedia/commons/9/9f/Lower_Keys_marsh_rabbit.jpg")
]

# 对图片进行增强
images_aug = seq(images=images_different_sizes)

# 可视化结果
print("Image 0 (input shape: %s, output shape: %s)" % (images_different_sizes[0].shape, images_aug[0].shape))
ia.imshow(np.hstack([images_different_sizes[0], images_aug[0]]))

print("Image 1 (input shape: %s, output shape: %s)" % (images_different_sizes[1].shape, images_aug[1].shape))
ia.imshow(np.hstack([images_different_sizes[1], images_aug[1]]))

print("Image 2 (input shape: %s, output shape: %s)" % (images_different_sizes[2].shape, images_aug[2].shape))
ia.imshow(np.hstack([images_different_sizes[2], images_aug[2]]))

different_size.png

imgaug 在 PyTorch 的应用

关于 PyTorch 中如何使用 imgaug 每一个人的模板是不一样的,我在这里也仅仅给出 imgaug 的 issue 里面提出的一种解决方案,大家可以根据自己的实际需求进行改变。
具体链接:how to use imgaug with pytorch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import numpy as np
from imgaug import augmenters as iaa
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms

# 构建pipline
tfs = transforms.Compose([
iaa.Sequential([
iaa.flip.Fliplr(p=0.5),
iaa.flip.Flipud(p=0.5),
iaa.GaussianBlur(sigma=(0.0, 0.1)),
iaa.MultiplyBrightness(mul=(0.65, 1.35)),
]).augment_image,
# 不要忘记了使用ToTensor()
transforms.ToTensor()
])

# 自定义数据集
class CustomDataset(Dataset):
def __init__(self, n_images, n_classes, transform=None):
# 图片的读取,建议使用imageio
self.images = np.random.randint(0, 255,
(n_images, 224, 224, 3),
dtype=np.uint8)
self.targets = np.random.randn(n_images, n_classes)
self.transform = transform

def __getitem__(self, item):
image = self.images[item]
target = self.targets[item]

if self.transform:
image = self.transform(image)

return image, target

def __len__(self):
return len(self.images)


def worker_init_fn(worker_id):
imgaug.seed(np.random.get_state()[1][0] + worker_id)


custom_ds = CustomDataset(n_images=50, n_classes=10, transform=tfs)
custom_dl = DataLoader(custom_ds, batch_size=64,
num_workers=4, pin_memory=True,
worker_init_fn=worker_init_fn)

关于 num_workers 在 Windows 系统上只能设置成 0,但是当我们使用 Linux 远程服务器时,可能使用不同的 num_workers 的数量,这是我们就需要注意 worker_init_fn()函数的作用了。它保证了我们使用的数据增强在 num_workers>0 时是对数据的增强是随机的。

总结

数据扩充是我们需要掌握的基本技能,除了 imgaug 以外,我们还可以去学习其他的数据增强库,包括但不局限于 Albumentations,Augmentor。除去 imgaug 以外,我还强烈建议大家学下 Albumentations,因为 Albumentations 跟 imgaug 都有着丰富的教程资源,大家可以有需求访问Albumentations 教程

参考资料

  1. kaggle-data-augmentation-packages-overview
  2. how to use imgaug with pytorch
  3. Kaggle 知识点:数据扩增方法
  4. PyTorch Classification Model Based On Imgaug.
  5. Tutorial Notebooks