imgaug
imgaug 简介和安装
imgaug 简介
imgaug
是计算机视觉任务中常用的一个数据增强的包,相比于torchvision.transforms
,它提供了更多的数据增强方法,因此在各种竞赛中,人们广泛使用imgaug
来对数据进行增强操作。
- Github 地址:imgaug (opens new window)
- Readthedocs:imgaug (opens new window)
- 官方提供 notebook 例程:notebook (opens new window)
imgaug 的安装
imgaug 的安装方法和其他的 Python 包类似,我们可以通过以下两种方式进行安装
conda
conda config --add channels conda-forge
conda install imgaug
2
pip
# install imgaug either via pypi
pip install imgaug
# install the latest version directly from github
pip install git+https://github.com/aleju/imgaug.git
2
3
4
5
6
7
imgaug 的使用
imgaug 仅仅提供了图像增强的一些方法,但是并未提供图像的 IO 操作,因此我们需要使用一些库来对图像进行导入,建议使用 imageio 进行读入,如果使用的是 opencv 进行文件读取的时候,需要进行手动改变通道,将读取的 BGR 图像转换为 RGB 图像。除此以外,当我们用 PIL.Image 进行读取时,因为读取的图片没有 shape 的属性,所以我们需要将读取到的 img 转换为 np.array()的形式再进行处理。因此官方的例程中也是使用 imageio 进行图片读取。
单张图片处理
在该单元,我们仅以几种数据增强操作为例
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)
2
3
4
5
6
7
8
9
10
11
12
13
14
现在我们已经得到了需要处理的图片,imgaug
包含了许多从Augmenter
继承的数据增强的操作。在这里我们以Affine
为例子。
from imgaug import augmenters as iaa
# 设置随机数种子
ia.seed(4)
# 实例化方法
rotate = iaa.Affine(rotate=(-4,45))
img_aug = rotate(image=img)
ia.imshow(img_aug)
2
3
4
5
6
7
8
9
这是对一张图片进行一种操作方式,但实际情况下,我们可能对一张图片做多种数据增强处理。这种情况下,我们就需要利用imgaug.augmenters.Sequential()
来构造我们数据增强的 pipline,该方法与torchvison.transforms.Compose()
相类似。
iaa.Sequential(children=None, # Augmenter集合
random_order=False, # 是否对每个batch使用不同顺序的Augmenter list
name=None,
deterministic=False,
random_state=None)
2
3
4
5
# 构建处理序列
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)
2
3
4
5
6
7
8
9
总的来说,对单张图片处理的方式基本相同,我们可以根据实际需求,选择合适的数据增强方法来对数据进行处理。
对批次图片进行处理
在实际使用中,我们通常需要处理更多份的图像数据。此时,可以将图形数据按照 NHWC 的形式或者由列表组成的 HWC 的形式对批量的图像进行处理。主要分为以下两部分,对批次的图片以同一种方式处理和对批次的图片进行分部分处理。
对批次的图片以同一种方式处理
对一批次的图片进行处理时,我们只需要将待处理的图片放在一个list
中,并将函数的 image 改为 images 即可进行数据增强操作,具体实际操作如下:
images = [img,img,img,img,]
images_aug = rotate(images=images)
ia.imshow(np.hstack(images_aug))
2
3
我们就可以得到如下的展示效果:
在上述的例子中,我们仅仅对图片进行了仿射变换,同样的,我们也可以对批次的图片使用多种增强方法,与单张图片的方法类似,我们同样需要借助
Sequential
来构造数据增强的 pipline。
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))
2
3
4
5
6
7
8
9
10
对批次的图片分部分处理
imgaug 相较于其他的数据增强的库,有一个很有意思的特性,即就是我们可以通过imgaug.augmenters.Sometimes()
对 batch 中的一部分图片应用一部分 Augmenters,剩下的图片应用另外的 Augmenters。
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)
2
3
4
5
6
对不同大小的图片进行处理
上面提到的图片都是基于相同的图像。以下的示例具有不同图像大小的情况,我们从维基百科加载三张图片,将它们作为一个批次进行扩充,然后一张一张地显示每张图片。具体的操作跟单张的图片都是十分相似,因此不做过多赘述。
# 构建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]]))
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
imgaug 在 PyTorch 的应用
关于 PyTorch 中如何使用 imgaug 每一个人的模板是不一样的,我在这里也仅仅给出 imgaug 的 issue 里面提出的一种解决方案,大家可以根据自己的实际需求进行改变。 具体链接:how to use imgaug with pytorch (opens new window)
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)
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
关于 num_workers 在 Windows 系统上只能设置成 0,但是当我们使用 Linux 远程服务器时,可能使用不同的 num_workers 的数量,这是我们就需要注意 worker_init_fn()函数的作用了。它保证了我们使用的数据增强在 num_workers>0 时是对数据的增强是随机的。
总结
数据扩充是我们需要掌握的基本技能,除了 imgaug 以外,我们还可以去学习其他的数据增强库,包括但不局限于 Albumentations,Augmentor。除去 imgaug 以外,我还强烈建议大家学下 Albumentations,因为 Albumentations 跟 imgaug 都有着丰富的教程资源,大家可以有需求访问Albumentations 教程 (opens new window)。