imgaug 简介和安装 imgaug 简介 imgaug是计算机视觉任务中常用的一个数据增强的包,相比于torchvision.transforms,它提供了更多的数据增强方法,因此在各种竞赛中,人们广泛使用imgaug来对数据进行增强操作。
Github 地址:imgaug
Readthedocs:imgaug
官方提供 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 imageioimport imgaug as ia %matplotlib inline img = imageio.imread("./Lenna.jpg" ) 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 , random_order=False , 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_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_aug = aug_seq.augment_images(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 , else_list=None , 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 seq = iaa.Sequential([ iaa.CropAndPad(percent=(-0.2 , 0.2 ), pad_mode="edge" ), iaa.AddToHueAndSaturation((-60 , 60 )), iaa.ElasticTransformation(alpha=90 , sigma=9 ), iaa.Cutout() ], 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 ]]))
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 npfrom imgaug import augmenters as iaafrom torch.utils.data import DataLoader, Datasetfrom torchvision import transforms 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, transforms.ToTensor() ])class CustomDataset (Dataset ): def __init__ (self, n_images, n_classes, transform=None ): 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 教程 。
参考资料
kaggle-data-augmentation-packages-overview
how to use imgaug with pytorch
Kaggle 知识点:数据扩增方法
PyTorch Classification Model Based On Imgaug.
Tutorial Notebooks