数据增强的必要性
目前几乎所有描述最先进的图像识别模型的论文都使用了基本的增强技术
深度神经网络需要大量的训练数据来获得良好的结果,并防止过度拟合,然而要获得足够的训练样本往往非常困难,多种原因可能使得收集足够的数据非常困难,甚至不可能。
为了制作一个训练数据集,你需要获得图像,然后给它们贴上标签。例如,如果你有一个图像分类任务,你需要分配正确的类标签;对于一个物体检测任务,你需要在物体周围画出边界框;对于一个语义分割任务,你需要为每个输入的图像像素分配一个正确的类别。这个过程需要手工劳动,而且有时给训练数据贴标签的成本可能很高。例如,为了正确标记医学图像,你需要昂贵的领域专家。
有时甚至收集训练图像也很困难,对医疗数据的处理有很多法律限制,获得这些数据需要很多努力。有时获得训练图像是比较可行的,但会花费很多钱。例如,为了获得卫星图像,你需要向卫星运营商支付费用来拍摄这些照片。为了获得用于道路场景识别的图像,你需要一个操作员,他将驾驶一辆汽车并收集所需的数据。
图像增强是一个从现有图像中创造新的训练样本的过程,为了制造一个新的样本,你稍微改变一下原始图像,例如可以让新的图像更亮一点、可以从原始图像上切下一块或者可以通过翻转原始图像来制作新的图像等等。
与只有少数最流行的转换技术的基础集相比,多样化的图像增强集提高了神经网络的性能。扩增有助于对抗过度拟合,提高计算机视觉任务(如分类、分割和物体检测)的深度神经网络的性能。最重要的是,像Albumentations这样的图像增强库使我们能够以最小的努力将图像增强添加到任何计算机视觉管道中。
albumentations的优势
目前有两种类型的图像增强:像素级增强和空间级增强。
虽然像opencv和Pillow也可以实现图像数据的增强,但是有些任务不仅需要对图像进行变换,同时标签也对应需要有所调整,例如对于分割任务,你需要对输入图像和输出掩码进行一些转换另外你还必须在图像转换和掩码转换中使用相同的参数。
对于像素级的增强,你只需要改变输入图像。对于空间级别的增强,你不仅需要对图像,而且还需要对边界框坐标应用同样的变换。在应用空间级增强后,你需要更新边界框的坐标,以代表增强后的图像上物体的正确位置。像素级增强改变了原始图像的像素值,但它们并不改变输出掩码,如改变图像的RGB调色板的亮度或对比度,就是像素级增强。相反空间级的增强则同时改变了图像和遮罩,当你应用图像变换时,如翻转、旋转或裁剪输入图像的一部分,你也需要对输出标签应用同样的变换以保持其正确性。
目前Albumentations是一个非常强大且主流的数据增强库
Albumentations提供一个单一的界面来处理不同的计算机视觉任务,如分类、语义分割、实例分割、物体检测、姿势估计等。目前该库在工业、深度学习研究、机器学习竞赛和开源项目中被广泛使用。
pip install albumentations
Albumentations的优势:
-
高性能:
Albumentations为最大的速度和性能进行了优化。在引擎盖下,该库使用来自OpenCV和NumPy的高度优化函数进行数据处理。我们有一个定期更新的基准,比较流行的图像增强库对最常见的图像变换的速度。Albumentations在大多数情况下表现出最好的性能。 -
支持多样化的增强功能
Albumentations支持超过60种不同的图像增强方式。 -
可扩展性
Albumentations允许轻松添加新的增强器,并通过单一接口与内置变换器一起在计算机视觉管道中使用它们。 -
严格的测试
扩增管道中的错误可能会悄悄地破坏输入数据。它们很容易被忽视,但用不正确的数据训练的模型的性能会下降,Albumentations有一个广泛的测试套件,有助于在开发期间发现错误。
Albumentations对coco进行数据增强
本文主要是以coco数据集为例,介绍使用Albumentations目标检测任务的数据增强方法
目标检测任务是指利用计算机技术及算法来实现对目标进行分类和定位的计算机视觉任务,目标检测任务中Bounding boxes是在图像上标记物体的矩形,其有多种格式的Bounding boxes表示形式,包括pascal_voc、albumentations、coco和yolo。
- pascal_voc:[x_min, y_min, x_max, y_max]
- albumentations:[x_min / width,y_min / height, x_max / width, y_max / height],其实就是在pascal_voc的基础上进行了归一化
- coco:[x_min,y_min,bbox_width,bbox_height]
- yolo:[x_center,y_center,bbox_width, bbox_height]
使用什么格式并不重要,处理方法是一样的,需要在下面使用到函数中的参数进行调整
读取coco的标注文件
path = './instances_val2014.json' # 这里需要改为个人环境中标注文件的路径
with open(instance_file, 'r') as f:
data = json.load(f)
读取后的结果是一个字典,包括info、images、licenses、annotations和categories五个键,我们主要关心的是images、annotations和categories这三个字段的内容:
- images:这是一个列表类型的结果,列表长度为图像总个数,每个列表数据是一个字典类型的数据,主要包括’file_name’、‘height’、'width’和’id’等8个字段
- annotations:也是一个列表类型的结果,列表长度为bbox总个数,每个列表数据是一个字典类型的数据,包括’segmentation’、‘area’、‘iscrowd’、‘image_id’、‘bbox’、'category_id’和’id’这七个字段,其中’segmentation’是用于分割任务的;'bbox’是一个包含四个元素的列表数据[x_min,y_min,bbox_width,bbox_height]
- categories:同样是一个列表类型的结果,列表总长度为80,表示该数据集共80个类别,每个列表数据是一个字典类型的数据,包括’supercategory’、'id’和’name’这三个字段
图像增强
transform = A.Compose([
A.RandomCrop(width=320, height=320),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=500, min_visibility=0.1))
首先定义一个数据增强pipeline,这里以随机裁剪、水平翻转和随机亮度对比度变化为例,A.RandomCrop接收两个参数,高度和宽度,A.RandomCrop(width=320, height=320)意味着A.RandomCrop将接受一个输入图像,从中提取一个256×256像素的随机patch,然后将结果传递给管道中的下一个增强器。
接着是进行水平翻转,A.HorizontalFlip有一个名为p的参数,p是一个特殊的参数,几乎所有的增强都支持,它控制应用增强的概率,p=0.5意味着在50%的概率下会进行水平翻转图像,而在50%的概率下,不会翻转输入图像。
接下来是A.RandomBrighntessContrast,它也有一个参数p,p=0.2意味着以20%的概率改变上一步得到图像的亮度和对比度,而在80%的概率下,图像保持不变。
下图是未进行增强的图像展示
以上设置对于图像分类任务是通用的,但是为了适用于目标检测任务,需要添加后面的参数,也就是bbox_params,需要将A.BboxParams的一个实例传递给该参数,A.BboxParams指定了用于处理bounding boxes的设置。其中 format设置了bounding boxes坐标的格式,可以设置为pascal_voc、albumentations、coco 或者 yolo,而且这个值是必须的,因为Albumentation需要知道bounding boxes的坐标源格式,以便正确地进行增强。
min_area 和 min_visibility 参数控制 Albumentations 在增强后bounding boxes的大小发生变化时应该如何处理,min_area是一个以像素为单位的值,如果一个bbox的面积在增强后变得小于min_area,Albumentations将放弃该box,返回的bounding boxes列表将不包含该box。min_visibility是一个介于0和1之间的值,如果增强后的bbox面积与增强前的bbox面积之比小于min_visibility,Albumentations将放弃该box,也就是如果增强过程切掉了一个bbox的绝大部分,那么这个盒子就不会出现在增强后bounding boxes的列表中。
就像这张图,如果min_visibility设置的再大些,那么toilet这个物体将不会被标记