针对图像领域,对比总结几种常见的数据增强方式。
方法对比
首先简单介绍几种读入图像的方式
(1)使用 Pillow 读图
1
2
3
4
5
6
7
8
9
10
|
from PIL import Image, ImageFilter
im = Image.open('cat.jpg')
# 应用模糊滤镜:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg')
# 缩小尺寸
im.thumbnail((w//2, h//2))
im.save('thumbnail.jpg', 'jpeg')
|
(2)使用 cv2 读图
1
2
3
4
5
6
7
8
9
|
import cv2
image = cv2.imread("/path/to/image.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 转换成灰度
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Canny边缘检测
edges = cv2.Canny(img, 30, 70)
|
因为历史原因, cv2 读图是 BGR 格式,需要转换成 RGB 格式(当 cv2.imwrite 的时候需要转换成 BGR)。大多数库都是 RGB 格式。
上述两种方式都是可以进行数据增强,但是需要有很多功能自己进行实现,所以使用其他的开源工具更加方便快捷。
当然 pytorch 中自带 transforms
可以完成数据增强,比如
1
2
3
4
5
6
7
8
9
10
11
12
|
# define pytorch transforms
transform = transforms.Compose([
transforms.ToPILImage(),
transforms.Resize((300, 300)),
transforms.CenterCrop((100, 100)),
transforms.RandomCrop((80, 80)),
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomRotation(degrees=(-90, 90)),
transforms.RandomVerticalFlip(p=0.5),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
])
|
(其中 p 是概率)
还有一些第三方开源库比如 imgaug 也提供了多样的数据扩增方法,且组合起来非常方便,速度较快。
那为什么还要选择 Albumentations 呢?主要是有以下两点考虑:
- 单一的接口应对多种视觉问题:分类、目标检测、分割、关键点;
- 优化了最快的速度与最好的性能。
分类问题是不受 label 限制的。但是在图像分割、目标检测和关键点检测的任务上, label 图和原图是需要一同转换的,torchvisioin 中没有现成的实验,Pillow 和 cv2 需要自己实现,比较复杂。
第二点关于速度的问题可以参考这里的代码:image_augmentation,这里不再多写。
使用策略
(1)最长使用的数据变换
Resize: resizing of images. This helps in particular when you have very high dimensional images and want to resize them to lower the resolutions. This can make deep learning neural network training much faster.
resize 可以使得图像的尺寸变小,然后深度网络训练时间变少。
Cropping: we can do cropping of an image. In particular, programmatically, we do Center Cropping and Random Cropping of an image.
使用最为广泛的是: center crop 和 random crop of an image
(2)随机选取数据增强的方式
这种随机选取一种进行数据增强是最合理的方式,能够最大发挥数据增强的限度,还是十分方便组合使用。
(可以好好参考一下这种写法,从直觉上认为是比较合理的。)
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
|
def strong_aug(p=0.5):
return Compose([
RandomRotate90(),
Flip(),
Transpose(),
OneOf([
IAAAdditiveGaussianNoise(),
GaussNoise(),
], p=0.2),
OneOf([
MotionBlur(p=0.2),
MedianBlur(blur_limit=3, p=0.1),
Blur(blur_limit=3, p=0.1),
], p=0.2),
ShiftScaleRotate(shift_limit=0.0625, scale_limit=0.2, rotate_limit=45, p=0.2),
OneOf([
OpticalDistortion(p=0.3),
GridDistortion(p=0.1),
IAAPiecewiseAffine(p=0.3),
], p=0.2),
OneOf([
CLAHE(clip_limit=2),
IAASharpen(),
IAAEmboss(),
RandomBrightnessContrast(),
], p=0.3),
HueSaturationValue(p=0.3),
], p=p)
|
(3)概率和数据集大小的关系
通常数据集大,增强的概率 10% ~ 30%,强度不需要太大;数据量小,概率是40% ~ 50%,可以相对大一些。
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
|
def get_train_transforms():
return A.Compose(
[
A.RandomSizedCrop(min_max_height=(800, 800), height=1024, width=1024, p=0.5),
A.OneOf([
A.HueSaturationValue(hue_shift_limit=0.2, sat_shift_limit= 0.2,
val_shift_limit=0.2, p=0.9),
A.RandomBrightnessContrast(brightness_limit=0.2,
contrast_limit=0.2, p=0.9),
],p=0.9),
A.ToGray(p=0.01),
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
A.Resize(height=512, width=512, p=1),
A.Cutout(num_holes=8, max_h_size=64, max_w_size=64, fill_value=0, p=0.5),
ToTensorV2(p=1.0),
],
p=1.0,
bbox_params=A.BboxParams(
format='pascal_voc',
min_area=0,
min_visibility=0,
label_fields=['labels']
)
)
# 在 dataloader 直接使用
train_dataset = DatasetRetriever(
image_ids=df_folds[df_folds['fold'] != fold_number].index.values,
marking=marking,
transforms=get_train_transforms(),
test=False,
)
|
参考文献
PyTorch and Albumentations for image classification
PyTorch and Albumentations for semantic segmentation
https://github.com/albumentations-team/albumentations_examples#augmentations-examples
https://github.com/albumentations-team/albumentations
https://www.pythonf.cn/read/166085