原文:https://blog.csdn.net/u012897374/article/details/80142744
版权声明:本文为博主原创文章,转载请附上博文链接!
简介
Augmentor是一个Python包,旨在帮助机器学习任务的图像数据人工生成和数据增强。它主要是一种数据增强工具,但也将包含基本的图像预处理功能。
特色
Augmentor是用于图像增强的软件包,重点在于提供通常用于生成机器学习问题的图像数据的操作。
Augmentor包含许多用于标准图像处理功能的类,例如Rotate 旋转类、Crop 裁剪类等等。 包含的操作有:旋转rotate、裁剪crop、透视perspective skewing、shearing、弹性形变Elastic Distortions、亮度、对比度、颜色等等;更多的操作及其参数设定,点击
数据增强通常是一个多阶段过程,Augmentor因此采用基于管道的处理方法,操作依次添加形成最终的操作管道。图像送到管道中,管道的操作依次作用到图片上形成新的图片,保存下来。
Augmentor 管道中定义的操作按照一定的概率随机地作用于图片上。
安装
控制台输入:
pip install Augmentor
安装成功。
使用Examples
分3步:
- 实例化Pipeline 对象,通过指定包含要处理图片所在的目录;
- 定义数据增强操作,crop、rotate等等,添加到pipeline中;
- 调用pipeline的sample(n)函数,同时指定增强后的样本总量;
import Augmentor
# 1. 指定图片所在目录
p = Augmentor.Pipeline("./images")
# 2. 增强操作
# 旋转 概率0.7,向左最大旋转角度10,向右最大旋转角度10
p.rotate(probability=0.7,max_left_rotation=10, max_right_rotation=10)
# 放大 概率0.3,最小为1.1倍,最大为1.6倍;1不做变换
p.zoom(probability=0.3, min_factor=1.1, max_factor=1.6)
# resize 同一尺寸 200 x 200
p.resize(probability=1,height=200,width=200)
# 3. 指定增强后图片数目总量
p.sample(2000)
增强后的图片文件保存在images下的output中。
总结
- 个人认为其最大的亮点是只需要指定要增强图片所在的路径即可,不用进行读入、以及numpy数据转换;
- 增强时只需要指定最后的数目N,无论原始图片有多少,总能生成你想要的数目!!!
- API也高度抽象;容易理解、上手!
- 增强后的图片会保存在指定增强图片所在目录下的output目录里;
推荐自己动手试一试。网址
imgaug是一个封装好的用来进行图像augmentation的python库,支持关键点(keypoint)和bounding box一起变换。项目主页: imgaug doc
1. 安装和卸载
# 通过github安装
sudo pip install git+https://github.com/aleju/imgaug
# 通过pypi安装
sudo pip install imgaug
# 本地安装, 下面的VERSION变成自己想要安装的version, 例如: imgaug-0.2.5.tar.gz
python setup.py sdist && sudo pip install dist/imgaug-VERSION.tar.gz
# 卸载
sudo pip uninstall imgaug
1
2
3
4
5
6
7
8
9
10
11
2. 基本使用
首先定义一个变换序列,然后直接将图像batch传入即可:
from imgaug import augmenters as iaa
seq = iaa.Sequential([
iaa.Crop(px=(0, 16)), # crop images from each side by 0 to 16px (randomly chosen)
iaa.Fliplr(0.5), # 0.5 is the probability, horizontally flip 50% of the images
iaa.GaussianBlur(sigma=(0, 3.0)) # blur images with a sigma of 0 to 3.0
])
for batch_idx in range(1000):
# 'images' should be either a 4D numpy array of shape (N, height, width, channels)
# or a list of 3D numpy arrays, each having shape (height, width, channels).
# Grayscale images must have shape (height, width, 1) each.
# All images must have numpy's dtype uint8. Values are expected to be in
# range 0-255.
images = load_batch(batch_idx)
images_aug = seq.augment_images(images)
train_on_images(images_aug)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
3. Augmenters常用函数
先导入Augmenters类:
from imgaug import augmenters as iaa
1
3.1 iaa.Sequential()
产生一个处理图片的Sequential
函数原型:
iaa.Sequential(children=None,
random_order=False,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
参数:
children: 想要应用在图像上的Augmenter或者Augmenter集合。默认None
random_order: bool类型, 默认False。是否对每个batch的图片应用不同顺序的Augmenter list。当设置为True时,不同batch之间图片的处理顺序都会不一样,但是同一个batch内顺序相同。
deterministic: bool类型, 默认False。
3.2 iaa.someOf()
将Augmenter中的部分变换应用在图片处理上,而不是应用所有的Augmenter。例如:可以定义20种变换,但每次只选择其中的5个。但是不支持固定选择某一个Augmenter。
函数原型:
iaa.SomeOf(n=None,
children=None,
random_order=False,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
6
参数:
n: 从总的Augmenters中选择多少个。可以是一个int, tuple, list或者随机值。
random_order: 是否每次顺序不一样。
例子:
# 每次选择一个翻转方式
seq = iaa.SomeOf(1, [
iaa.Fliplr(1.0),
iaa.Flipud(1.0)
])
imgs_aug = seq.augment_images(imgs)
# 每次使用1~3个Augmenter来处理图片,每个batch中的Augmenters顺序一样。
seq = iaa.SomeOf((1, 3), [
iaa.Fliplr(1.0),
iaa.Flipud(1.0),
iaa.GaussianBlur(1.0)
])
imgs_aug = seq.augment_images(imgs)
# 每次使用1到多个Augmenter来处理图片,每个batch中的Augmenters顺序不一样。
seq = iaa.SomeOf((1, None), [
iaa.Fliplr(1.0),
iaa.Flipud(1.0),
iaa.GaussianBlur(1.0)
], random_order=True)
imgs_aug = seq.augment_images(imgs)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
3.3 iaa.OneOf()
每次从一系列Augmenters中选择一个来变换。
iaa.OneOf(children,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
参数含义与上面一样。
3.4 iaa.Sometimes()
对batch中的一部分图片应用一部分Augmenters,剩下的图片应用另外的Augmenters。
iaa.Sometimes(p=0.5,
then_list=None,
else_list=None,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
6
p: float。多大比例的图片会被Augmente。
then_list: Augmenter集合。p概率的图片进行变换的Augmenters。
else_list: 1-p概率的图片会被进行变换的Augmenters。注意变换的图片应用的Augmenter只能是then_list或者else_list中的一个。
3.5 iaa.WithColorspace()
在某个特定的颜色空间对图像进行变换。即:先将图片从一个颜色空间变换到另一个颜色空间,然后在另一个颜色空间中对图像进行变换,最后再变换回原来的颜色空间。
iaa.WithColorspace(to_colorspace,
from_colorspace='RGB',
children=None,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
6
to_colorspace: 要变换的颜色空间。有以下选择:RGB, BGR, GRAY, CIE, YCrCb, HSV, HLS, Lab, Luv
from_colorspace: 原来的颜色空间, 默认RGB。
children: 要执行的变换。
# 先将图片从RGB变换到HSV,然后将H值增加10,然后再变换回RGB。
aug = iaa.WithColorspace(to_colorspace="HSV", from_colorspace="RGB",
children=iaa.WithChannels(0, iaa.Add(10)))
1
2
3
3.6 iaa.WithChannels()
从图片中挑选出一个Channel来进行变换,变换完了之后再将该channel merge回去。
iaa.WithChannels(channels=None,
children=None,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
参数:
channels: int或者int list。哪些channel要被用来变换。
children: channel被选出来之后要进行哪些变换。
3.7 iaa.Noop()
不进行任何变换。某些情况下只想使用一个Augmenter作为占位符,这样可以继续调用augment_image()函数,但实际不作变换。例如进行测试的时候可以使用这个。
3.8 iaa.Lambda()
自定义一些变换函数。
iaa.Lambda(func_images,
func_keypoints,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
参数:
func_images: 对每一个image调用此函数。该函数的形式为:
function(images, random_state, parents, hooks)
1
该函数必须返回变换后的图片。
+ func_keypoints: 对每个图像的关键点进行变换的函数。该函数形式为:
function(keypoints_on_images, random_state, parents, hooks)
1
该函数返回变换后的keypoint。
例子:
def func_images(images, random_state, parents, hooks):
images[:, ::2, :, :] = 0
return images
def func_keypoints(keypoints_on_images, random_state, parents, hooks):
return keypoints_on_images
aug = iaa.Lambda(
func_images=func_images,
func_keypoints=func_keypoints
)
1
2
3
4
5
6
7
8
9
10
11
将每张图片没隔两行的像素点变成黑色的条带,关键点保留。
3.9 iaa.AssertShape()
assert要变换的图片和keypoint的shape。如果不满足就抛出异常。
iaa.AssertShape(shape,
check_images=True,
check_keypoints=True,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
6
参数:
shape: 元组,通常形式为(N, H, W, C)。元组中每个元素的值可以为:None, int, 两个int类型的tuple或者一个int类型的list。如果是None,表示所有值都可以接受。如果是int,则只有对应的位置是该值才会被接受。如果是int类型的tuple,例如(a,b),则对应位置的值必须是a<=x
# 检查输入的每张图片是否是32×32×3的,如果是则执行水平翻转,否则报错
seq = iaa.Sequential([
iaa.AssertShape((None, 32, 32, 3)),
iaa.Fliplr(0.5)
])
# 先检查图片的高度是否是32<=H<64, 宽度是否是32, channel是否是1或者3。如果都满足则执行水平翻转,否则报错。
seq = iaa.Sequential([
iaa.AssertShape((None, (32, 64), 32, [1, 3])),
iaa.Fliplr(0.5)
])
1
2
3
4
5
6
7
8
9
10
11
3.10 iaa.Scale()
将图像缩放到固定大小。
iaa.Scale(size,
interpolation='cubic',
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
参数:
size: 字符串”keep”,此时保持图像原大小不坐缩放。如果是一个整数n,则缩放成(n, n)。如果是一个float v,则每张图片会被缩放成(H*v, W*v),此时每张图像大小仍然不一样。如果是一个tuple类型(a, b), 如果a、b中至少有一个小数,则从[a,b]中挑选一个数作为缩放比例。如果a、b都是整数,则从[a,b]中挑选一个整数作为缩放后的大小。如果是1个list,则list中的数要么全是整数,要么全是小数(不能混用)。如果是一个dict类型,则该dict必须有两个key: height和width。每个key的值仍然可以按照上面的方法选取。此外, key的值还可以是”keep-aspect-ratio”, 表示按照比例缩放。
interpolation: 缩放方法。如果是All, 则会随机从下面挑选一个: nearest、linear、area、cubic,注意每张图片可能不一样。如果是int,则应该是下面的一种:cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_AREA,cv2.INTER_CUBIC。如果是string,则该种方法会被一直使用,必须是下面的一种: nearest, linear, area, cubic。如果是int list或者string list, 则每张图片会从中随机选取一个。
3.11 iaa.CropAndPad()
截取(crop)或者填充(pad),填充时,被填充区域为黑色。
iaa.CropAndPad(px=None,
percent=None,
pad_mode='constant',
pad_cval=0,
keep_size=True,
sample_independently=True,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
6
7
8
9
参数:
px: 想要crop(negative values)的或者pad(positive values)的像素点。注意与percent不能同时存在。如果是None, pixel级别的crop不会被使用。int或者int list与上面相同。如果是一个4个元素的tuple,那么4个元素分别代表(top, right, bottom, left),每个元素可以是int或者int tuple或者int list。
percent:按比例来crop或者pad, 与px相同。但是两者不能同时存在。
pad_mode: 填充方式。可以是All, string, string list。可选的填充方式有: constant, edge, linear_ramp, maximum, median, minimum, reflect, symmetric, wrap。具体含义可查numpy文档。
pad_cval: float、int、float tuple、int tuple、float list、int list。当pad_mode=constant的时候选择填充的值。
keep_size: bool类型。经过crop后,图像大小会改变。如果该值设置为1,则在crop或者pad后再缩放成原来的大小。
sample_independently : bool类型。如果设置为False,则每次从px或者percent中选出来的值会作用在四个方位。
3.12 iaa.Pad()
与iaa.CropAndPad()相同,只接受positive values。
3.13 iaa.Crop()
与iaa.CropAndPad()相同,只接受negative values。
3.14 iaa.Fliplr()
水平镜面翻转。
iaa.Fliplr(p=0, name=None, deterministic=False, random_state=None)
1
参数:
p: int或者float,每张图片呗翻转的概率
3.15 Flipud()
上下翻转,与上面相同。
3.16 iaa.ChangeColorspace()
改变图像空间。
iaa.ChangeColorspace(to_colorspace, from_colorspace='RGB', alpha=1.0, name=None, deterministic=False, random_state=None)
1
参数:
to_colorspace: 见上。
from_colorspace: 见上。
alpha: 覆盖旧的颜色空间时,新颜色空间的Alpha值。为int, float, int tuple, float tuple。
3.17 iaa.Grayscale()
变成灰度图。
iaa.Grayscale(alpha=0, from_colorspace='RGB', name=None, deterministic=False, random_state=None)
1
参数:
alpha: 覆盖旧的颜色空间时,新颜色空间的Alpha值。
3.18 iaa.GaussianBlur()
高斯扰动。
iaa.GaussianBlur(sigma=0, name=None, deterministic=False, random_state=None)
1
参数:
sigma: 高斯变换的标准差。可为float, float tuple。常见的有0,不扰动。3,强扰动。
3.19 iaa.AverageBlur()
从最邻近像素中取均值来扰动。
iaa.AverageBlur(k=1, name=None, deterministic=False, random_state=None)
1
参数:
k:窗口大小。可为int, int tuple。当为int tuple时,如果每个元素也是tuple,每个元素分别作为height和width,窗口大小不一致。
3.20 iaa.MedianBlur()
通过最近邻中位数来扰动。
iaa.MedianBlur(k=1, name=None, deterministic=False, random_state=None)
1
与上面相同。
3.21 iaa.Convolve()
对图像使用卷积。
iaa.Convolve(matrix=None, name=None, deterministic=False, random_state=None)
1
matrix: 卷积矩阵。
3.22 iaa.Sharpen()
锐化。
iaa.Sharpen(alpha=0, lightness=1, name=None, deterministic=False, random_state=None)
1
3.23 iaa.Emboss()
浮雕效果。
iaa.Emboss(alpha=0, strength=1, name=None, deterministic=False, random_state=None)
1
3.24 iaa.EdgeDetect()
边缘检测。
iaa.EdgeDetect(alpha=0, name=None, deterministic=False, random_state=None)
1
3.25 iaa.DirectedEdgeDetect()
特定方向的边缘检测。
iaa.DirectedEdgeDetect(alpha=0, direction=(0.0, 1.0), name=None, deterministic=False, random_state=None)
1
3.26 iaa.Add()
随机加上一个值。
iaa.Add(value=0, per_channel=False, name=None, deterministic=False, random_state=None)
1
3.27 iaa.AddElementwise()
按像素加。
iaa.AddElementwise(value=0, per_channel=False, name=None, deterministic=False, random_state=None)
1
3.28 iaa.AdditiveGaussianNoise()
添加高斯噪声。
iaa.AdditiveGaussianNoise(loc=0, scale=0, per_channel=False, name=None, deterministic=False, random_state=None)
1
3.29 iaa.Multiply()
给图像中的每个像素点乘一个值使得图片更亮或者更暗。
iaa.Multiply(mul=1.0, per_channel=False, name=None, deterministic=False, random_state=None)
1
3.30 iaa.MultiplyElementwise()
按像素值乘。
iaa.MultiplyElementwise(self, mul=1.0, per_channel=False, name=None, deterministic=False, random_state=None)
1
3.31 iaa.Dropout()
随机去掉一些像素点, 即把这些像素点变成0。
iaa.Dropout(p=0, per_channel=False, name=None, deterministic=False, random_state=None)
1
3.32 iaa.CoarseDropout()
将矩形框的值设置为0。
iaa.CoarseDropout(p=0, size_px=None, size_percent=None, per_channel=False, min_size=4, name=None, deterministic=False, random_state=None)
1
3.33 iaa.Invert()
将每个像素值p变成255-p。
iaa.Invert(p=0, per_channel=False, min_value=0, max_value=255, name=None, deterministic=False, random_state=None)
1
3.34 iaa.ContrastNormalization()
改变图像的对比度。
iaa.ContrastNormalization(alpha=1.0, per_channel=False, name=None, deterministic=False, random_state=None)
1
3.35 iaa.Affine()
仿射变换。包含:平移(Translation)、旋转(Rotation)、放缩(zoom)、错切(shear)。仿设变换通常会产生一些新的像素点,我们需要指定这些新的像素点的生成方法,这种指定通过设置cval和mode两个参数来实现。参数order用来设置插值方法。
iaa.Affine(scale=1.0,
translate_percent=None,
translate_px=None,
rotate=0.0,
shear=0.0,
order=1,
cval=0,
mode='constant',
name=None, deterministic=False, random_state=None)
1
2
3
4
5
6
7
8
9
参数:
scale: 图像缩放因子。1表示不缩放,0.5表示缩小到原来的50%。此参数可以是float, float tuple, dict。如果是float, 则所有图片按照这种比例缩放。如果是float tuple, 则随机选取一个值来进行缩放,此时x-axis和y-axis的缩放比例相同。如果是一个dict,则应该有两个key:x, y,每个x或y的值都可以是float, float tuple,此时x-axis和y-axis的缩放比例不一样。
translate_percent: 平移比例,0表示不平移,0.5表示平移50%。可以是float, float tuple, dict,具体含义与scale相同。用正负来表示平移方向。
translate_px: 按照像素来进行平移。可以是int, int tuple, dict,具体含义与translate_percent相同。
rotate: 平移角度,0~360度之间,正负也可以表示方向。可以为float, float tuple。
shear: 错切的程度,0~360度之间,正负表示方向。可以为float, int, float tuple, int tuple。
order: 插值顺序,与skimage中定义相同。下面0和1方法快,3比较慢,4、5特别慢。可以是int, int list, ia.ALL。如果是ia.ALL,则每次从所有的插值方法中随机选取。
0:最邻近插值。
1: 双线性插值(默认)。
2: 双二次插值(不推荐)。
3:双三次插值。
4: Bi-quartic。
5:Bi-quintic。
cval: 当平移后使用常量填充的时候指定填充的常量值,只有在mode=constant的时候才会生效。可以是int, float, tuple, ia.ALL。如果是ia.ALL,则会从[0,255]之间随机选取一个值填充。
mode: 采用何种方式填充经过变换后空白的像素点。可以是string, string list, ia.ALL。基本用法与上面相同。其中字符串的选取范围是:
constant: 采用一个常量填充。
edge: 边缘填充。
symmetric: 镜面对称填充。
reflect: Pads with the reflection of the vector mirrored on the first and last values of the vector along each axis.
wrap: Pads with the wrap of the vector along the axis. The first values are used to pad the end and the end values are used to pad the beginning.
3.36 iaa.PiecewiseAffine()
随机放置一些规则的网格点然后移动这些点的周围的像素。这回导致局部的扭曲。
iaa.PiecewiseAffine(scale=0,
nb_rows=4,
nb_cols=4,
order=1,
cval=0,
mode='constant',
name=None, deterministic=False, random_state=None)
1
2
3
4
5
6
7
3.37 iaa.ElasticTransformation()
通过移动局部像素来变换。
iaa.ElasticTransformation(alpha=0,
sigma=0,
name=None,
deterministic=False,
random_state=None)
1
2
3
4
5
4. keypoint变换
imgaug支持在图像变换的同时变换图像中的关键点。例子如下:
import imgaug as ia
from imgaug import augmenters as iaa
iaa.seed(1)
image=ia.quokka(size=(256,256))
# 定义4个关键点
keypoints=ia.KeypointsOnImage([
ia.Keypoint(x=65, y=100),
ia.Keypoint(x=75, y=200),
ia.Keypoint(x=100, y=100),
ia.Keypoint(x=200, y=80)
], shape=image.shape)
# 定义一个变换序列
seq=iaa.Sequential([
iaa.Multiply((1.2, 1.5)), # 改变亮度,不影响关键点
iaa.Affine(
rotate=10,
scale=(0.5, 0.7)
) # 旋转10度然后缩放,会影响关键点
])
# 固定变换序列,之后就可以先变换图像然后变换关键点,这样可以保证两次的变换完全相同。
# 如果调用次函数,需要在每次batch的时候都调用一次,否则不同的batch执行相同的变换。
seq_det = seq.to_deterministic()
# 转换成list或者batch来变换。由于只有一张图片, 因此用[0]来取出该图和关键点。
image_aug = seq_det.augment_images([image])[0]
keypoints_aug = seq_det.augment_keypoints([keypoints])[0]
# print coordinates before/after augmentation (see below)
# use after.x_int and after.y_int to get rounded integer coordinates
for i in range(len(keypoints.keypoints)):
before = keypoints.keypoints[i]
after = keypoints_aug.keypoints[i]
print("Keypoint %d: (%.8f, %.8f) -> (%.8f, %.8f)" % (
i, before.x, before.y, after.x, after.y)
)
# 将关键点画在图片上。
# image with keypoints before/after augmentation (shown below)
image_before = keypoints.draw_on_image(image, size=7)
image_after = keypoints_aug.draw_on_image(image_aug, size=7)
fig, axes = plt.subplots(2, 1, figsize=(20, 15))
plt.subplots_adjust(left=0.2, bottom=0.2, right=0.8, top=0.8, hspace=0.3, wspace=0.0)
axes[0].set_title("image before")
axes[0].imshow(image_before)
axes[1].set_title("image after augmentation")
axes[1].imshow(image_after)
plt.show()
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
50
51
52
53
54
5. Bounding Boxes变换
imgaug在图像变换的同时变换图像中的bound box。bounding的支持包括:
将bounding box封装成对象
对bounding box进行变换
将bounding box画在图像上
移动bounding box的位置,将变换后的bounding box映射到图像上,计算bounding box的IoU。
5.1 基本变换
例子如下:
import imgaug as ia
from imgaug import augmenters as iaa
ia.seed(1)
image = ia.quokka(size=(256, 256))
# 定义2个bounding box
bbs = ia.BoundingBoxesOnImage([
ia.BoundingBox(x1=65, y1=100, x2=200, y2=150),
ia.BoundingBox(x1=150, y1=80, x2=200, y2=130)
], shape=image.shape)
seq = iaa.Sequential([
iaa.Multiply((1.2, 1.5)), # 改变亮度, 不影响bounding box
iaa.Affine(
translate_px={"x": 40, "y": 60},
scale=(0.5, 0.7)
) # 平移后缩放,会影响bounding box
])
# 固定变换
seq_det = seq.to_deterministic()
# 变换图像和bounding box
image_aug = seq_det.augment_images([image])[0]
bbs_aug = seq_det.augment_bounding_boxes([bbs])[0]
# 打印坐标
# use .x1_int, .y_int, ... to get integer coordinates
for i in range(len(bbs.bounding_boxes)):
before = bbs.bounding_boxes[i]
after = bbs_aug.bounding_boxes[i]
print("BB %d: (%.4f, %.4f, %.4f, %.4f) -> (%.4f, %.4f, %.4f, %.4f)" % (
i,
before.x1, before.y1, before.x2, before.y2,
after.x1, after.y1, after.x2, after.y2)
)
# 输出
# BB 0: (65.0000, 100.0000, 200.0000, 150.0000) -> (130.7524, 171.3311, 210.1272, 200.7291)
# BB 1: (150.0000, 80.0000, 200.0000, 130.0000) -> (180.7291, 159.5718, 210.1272, 188.9699)
# image with BBs before/after augmentation (shown below)
image_before = bbs.draw_on_image(image, thickness=2)
image_after = bbs_aug.draw_on_image(image_aug, thickness=2, color=[0, 0, 255])
fig, axes = plt.subplots(2, 1, figsize=(20, 15))
plt.subplots_adjust(left=0.2, bottom=0.2, right=0.8, top=0.8, hspace=0.3, wspace=0.0)
axes[0].set_title("image before")
axes[0].imshow(image_before)
axes[1].set_title("image after augmentation")
axes[1].imshow(image_after)
plt.show()
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
50
51
52
53
54
5.2 平移bounding box
调用shift函数即可。
import imgaug as ia
from imgaug import augmenters as iaa
ia.seed(1)
# Define image and two bounding boxes
image = ia.quokka(size=(256, 256))
bbs = ia.BoundingBoxesOnImage([
ia.BoundingBox(x1=25, x2=75, y1=25, y2=75),
ia.BoundingBox(x1=100, x2=150, y1=25, y2=75)
], shape=image.shape)
# 两个box先右移动25像素,然后第2个box再向下移动25像素
bbs_shifted = bbs.shift(left=25)
bbs_shifted.bounding_boxes[1] = bbs_shifted.bounding_boxes[1].shift(top=25)
# Draw images before/after moving BBs
image = bbs.draw_on_image(image, color=[0, 255, 0], thickness=2, alpha=0.75)
image = bbs_shifted.draw_on_image(image, color=[0, 0, 255], thickness=2, alpha=0.75)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
得到的图像为:
5.3 图像有缩放时bounding box的映射
调用on函数即可。
import imgaug as ia
from imgaug import augmenters as iaa
ia.seed(1)
# Define image with two bounding boxes
image = ia.quokka(size=(256, 256))
bbs = ia.BoundingBoxesOnImage([
ia.BoundingBox(x1=25, x2=75, y1=25, y2=75),
ia.BoundingBox(x1=100, x2=150, y1=25, y2=75)
], shape=image.shape)
# Rescale image and bounding boxes
image_rescaled = ia.imresize_single_image(image, (512, 512))
bbs_rescaled = bbs.on(image_rescaled)
# Draw image before/after rescaling and with rescaled bounding boxes
image_bbs = bbs.draw_on_image(image, thickness=2)
image_rescaled_bbs = bbs_rescaled.draw_on_image(image_rescaled, thickness=2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
5.4 计算Intersections, Unions和IoU
import imgaug as ia
from imgaug import augmenters as iaa
import numpy as np
ia.seed(1)
# Define image with two bounding boxes.
image = ia.quokka(size=(256, 256))
bb1 = ia.BoundingBox(x1=50, x2=100, y1=25, y2=75)
bb2 = ia.BoundingBox(x1=75, x2=125, y1=50, y2=100)
# Compute intersection, union and IoU value
# Intersection and union are both bounding boxes. They are here
# decreased/increased in size purely for better visualization.
bb_inters = bb1.intersection(bb2).extend(all_sides=-1)
bb_union = bb1.union(bb2).extend(all_sides=2)
iou = bb1.iou(bb2)
# Draw bounding boxes, intersection, union and IoU value on image.
image_bbs = np.copy(image)
image_bbs = bb1.draw_on_image(image_bbs, thickness=2, color=[0, 255, 0])
image_bbs = bb2.draw_on_image(image_bbs, thickness=2, color=[0, 255, 0])
image_bbs = bb_inters.draw_on_image(image_bbs, thickness=2, color=[255, 0, 0])
image_bbs = bb_union.draw_on_image(image_bbs, thickness=2, color=[0, 0, 255])
image_bbs = ia.draw_text(
image_bbs, text="IoU=%.2f" % (iou,),
x=bb_union.x2+10, y=bb_union.y1+bb_union.height//2,
color=[255, 255, 255], size=13
)
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
得到的图像如下:
6. Stochastic Parameter
在做变换的时候,我们希望每张图片的变换都不一样,通过参数随机化选取可以实现。但是想要复现之前的变换,需要通过determinism来实现,比较繁琐。为了避免这种情况,使用Stochastic Parameters来实现。这个变量通常是一个抽象的概率分布,例如正太分布、均匀分布等等。通常所有的augmenter都能接受这个参数,这样就很方便控制变量范围。他们都可以和determinism结合。
例子:
from imgaug import augmenters as iaa
from imgaug import parameters as iap
seq = iaa.Sequential([
iaa.GaussianBlur(
sigma=iap.Uniform(0.0, 1.0)
),
iaa.ContrastNormalization(
iap.Choice(
[1.0, 1.5, 3.0],
p=[0.5, 0.3, 0.2]
)
),
iaa.Affine(
rotate=iap.Normal(0.0, 30),
translate_px=iap.RandomSign(iap.Poisson(3))
),
iaa.AddElementwise(
iap.Discretize(
(iap.Beta(0.5, 0.5) * 2 - 1.0) * 64
)
),
iaa.Multiply(
iap.Positive(iap.Normal(0.0, 0.1)) + 1.0
)
])
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
所有可用的概率分布有:
6.1 正态分布
Normal(loc, scale): 均值为loc,标准差scale。
from imgaug import parameters as iap
params = [
iap.Normal(0, 1),
iap.Normal(5, 3),
iap.Normal(iap.Choice([-3, 3]), 1),
iap.Normal(iap.Uniform(-3, 3), 1)
]
iap.show_distributions_grid(params)
1
2
3
4
5
6
7
8
6.2 拉普拉斯分布
Laplace(loc, scale): 峰值loc, 宽度scale:
from imgaug import parameters as iap
params = [
iap.Laplace(0, 1),
iap.Laplace(5, 3),
iap.Laplace(iap.Choice([-3, 3]), 1),
iap.Laplace(iap.Uniform(-3, 3), 1)
]
iap.show_distributions_grid(params)
1
2
3
4
5
6
7
8
6.3 其他连续概率分布还有:
卡方分布(ChiSquare)
韦伯分布(Weibull)
均匀分布(Uniform )
Beta分布
6.4 离散概率分布
二项分布(Binomial)
离散均匀分布(DiscreteUniform)
泊松分布(Poisson distribution)
6.5 对分布的数学运算
imgaug支持随机参数的算术运算。 允许修改从分布中抽取的值或者将几个分布相互组合。支持的操作有:
Add
Subtract
Multiply
Divide
Power
6.6 特殊参数
支持的操作有:
Deterministic
Choice
Clip
Discretize
Absolute
RandomSign
ForceSign
Positive
Negative
FromLowerResolution
具体含义和用法见文档。
7. Blending/Overlaying images
augment会直接改变图片而把原图舍弃掉了。有时我们需要改变图像的局部,或者将原来的图片跟新变换的图片结合起来。这可以通过给变换前后的图片配上一定的权重(αα参数)或者使用一个pixel-wise的mask。
一个例子如下:
# First row
iaa.Alpha(
(0.0, 1.0),
first=iaa.MedianBlur(11),
per_channel=True
)
# Second row
iaa.SimplexNoiseAlpha(
first=iaa.EdgeDetect(1.0),
per_channel=False
)
# Third row
iaa.SimplexNoiseAlpha(
first=iaa.EdgeDetect(1.0),
second=iaa.ContrastNormalization((0.5, 2.0)),
per_channel=0.5
)
# Forth row
iaa.FrequencyNoiseAlpha(
first=iaa.Affine(
rotate=(-10, 10),
translate_px={"x": (-4, 4), "y": (-4, 4)}
),
second=iaa.AddToHueAndSaturation((-40, 40)),
per_channel=0.5
)
# Fifth row
iaa.SimplexNoiseAlpha(
first=iaa.SimplexNoiseAlpha(
first=iaa.EdgeDetect(1.0),
second=iaa.ContrastNormalization((0.5, 2.0)),
per_channel=True
),
second=iaa.FrequencyNoiseAlpha(
exponent=(-2.5, -1.0),
first=iaa.Affine(
rotate=(-10, 10),
translate_px={"x": (-4, 4), "y": (-4, 4)}
),
second=iaa.AddToHueAndSaturation((-40, 40)),
per_channel=True
),
per_channel=True,
aggregation_method="max",
sigmoid=False
)
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
50
得到的图片为: