Albumentations:使用一种更简单通用的方式进行图像数据增强

MIT License:github.com/albumentati…

为什么需要图像增强

  深度神经网络需要大量的训练数据才能获得良好的结果并防止过拟合。但是,通常很难获得足够的训练样本,主要难点在于收集和标注数据集的成本过高。此时可以通过图像增强来制作新样本:

  image.png

图像增强的效果

  有助于对抗过拟合,提高预测准确率。

  2018 年,谷歌发表了一篇关于 AutoAugment的论文——一种自动发现数据集最佳增强集的算法。他们表明,一组自定义的增强可以提高模型的性能。2022-02-271

使用Albumentations进行图像增强

  这个库是一个高级封装。

  如果使用Pillow进行简单的图像增强:

python
from PIL import Image, ImageEnhance

image = Image.open("parrot.jpg")

mirrored_image = image.transpose(Image.FLIP_LEFT_RIGHT)

rotated_image = image.rotate(45)

brightness_enhancer = ImageEnhance.Brightness(image)
brighter_image = brightness_enhancer.enhance(factor=1.5)
复制代码

  这种方法具有局限性,并且比较难以复用。局限性主要体现在图像增强的两种不同情况上:

  有些变换(例如像素级增强)会改变原始图像的像素值,但不会改变输出掩码。此时我们只需要对图像进行变换即可。

  image.png

  而有些变换(空间级增强)会改变图像和掩码,此时我们需要同时处理图像和标注数据。

  image.png

  对象检测任务也是如此。对于像素级增强,您只需要更改输入图像。使用空间级增强,您不仅需要对图像应用相同的变换,还需要对边界框坐标应用相同的变换。应用空间级增强后,您需要更新边界框的坐标以表示对象在增强图像上的正确位置。

  image.png

  Albumentations 主要提供:

  • 正确地将转换应用于输入数据和输出标签。

  • 允许为每个转换设置所需的概率和值的大小。

  • PipeLine 和统一的接口定义

    例如这个Pipeline首先裁剪输入图像的随机 512px x 512px 部分。然后以 30% 的概率随机改变该图像的亮度和对比度。最后,以 50% 的概率水平翻转生成的图像

    python
    import albumentations as A
    
    transform = A.Compose([
        A.RandomCrop(512, 512),
        A.RandomBrightnessContrast(p=0.3),
        A.HorizontalFlip(p=0.5),
    ])
    复制代码
  • 同时,这是一个可信赖的库,因为其拥有完备的测试。CI

  • 具有很强的拓展性

图像增强 Example

  在线demo:albumentations-demo.herokuapp.com/

python
import albumentations as A # Import albumentations
import cv2 # Import a library to read images from the disk (e.g., OpenCV).

# Define an augmentation pipeline.
transform = A.Compose([
    A.RandomCrop(width=256, height=256),
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.2),
])

# Read Image From Disk
image = cv2.imread("/path/to/image.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # OpenCV 因为[历史遗留原因](https://learnopencv.com/why-does-opencv-use-bgr-color-format/)读入的图像以BGR格式,需要进行转换

transformed = transform(image=image)
transformed_image = transformed["image"]
复制代码

  当然读入图像也可以使用其他库,例如Pillow:

python
# pip install pillow
from PIL import Image
import numpy as np

pillow_image = Image.open("image.jpg")
image = np.array(pillow_image)
复制代码

图像和标注共同处理 Example

  例如,对于语义分割任务,需要同时增加输入图像和一个或多个输出掩码。

python
import albumentations as A
import cv2

transform = A.Compose([
    A.RandomCrop(width=256, height=256),
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.2),
])

image = cv2.imread("/path/to/image.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 读入掩码,同时读入类型应当与numpy array相同/兼容,且与图像大小相同
mask = cv2.imread("/path/to/mask.png")

transformed = transform(image=image, mask=mask)
transformed_image = transformed['image']
transformed_mask = transformed['mask']

# 或者对于同一张图片有多张掩码,可以作为一个列表一同输入
mask_1 = cv2.imread("/path/to/mask_1.png")
mask_2 = cv2.imread("/path/to/mask_2.png")
mask_3 = cv2.imread("/path/to/mask_3.png")
masks = [mask_1, mask_2, mask_3]

# 且传入时注意关键字为 masks 而不是 mask
transformed = transform(image=image, masks=masks)
transformed_image = transformed['image']
transformed_masks = transformed['masks']
复制代码

  image.png

图像识别标定框 Example

  支持四种图像标注格式:pascal_vocalbumentationscoco 和 yolo .

  image.png

  如上图:一个矩形标注框可由四个变量确定,即[x_min, y_min, x_max, y_max]

  由此,我们可以归纳几种标注格式:

  1. pascal_voc:[x_min, y_min, x_max, y_max],在上图中是[98, 345, 420, 462]
  2. albumentations:归一化的pascal,即分别除以图像的的高/宽,[x_min, y_min, x_max, y_max],在上图中是[0.153125, 0.71875, 0.65625, 0.9625]
  3. coco:[x_min, y_min, width, height],在上图中是[98, 345, 322, 117]
  4. yolo:[x_center, y_center, width, height]并进行归一化,在上图中是[0.4046875, 0.840625, 0.503125, 0.24375]

  Albumentations支持同时对标注和图像进行变换:

python
import albumentations as A
import cv2

transform = A.Compose([
    A.RandomCrop(width=450, height=450),
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.2),
], bbox_params=A.BboxParams(format='coco', min_area=1024, min_visibility=0.1, label_fields=['class_labels']))
# 此处需要指定标注格式 可选:变换后的最小区域大小,最小目标可见度,以及指定变换参数名



image = cv2.imread("/path/to/image.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 指定标注之后,支持在坐标数组里面添加标注类型,例如[23, 74, 295, 388, 'dog'],[333, 421, 49, 49, 'sports ball', 'item']
transformed = transform(image=image, bboxes=bboxes)
transformed_image = transformed['image']
transformed_bboxes = transformed['bboxes']

# 也可以单独传递标签(默认) 例如:[23, 74, 295, 388]... ['cat', 'dog', 'sports ball']
transformed = transform(image=image, bboxes=bboxes, class_labels=class_labels) # 此处class_labels是上文label_fields指定的名字,支持多参数
transformed_image = transformed['image']
transformed_bboxes = transformed['bboxes']
transformed_class_labels = transformed['class_labels']
复制代码

  image.png

  image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享