Vannesa's Studio

关于数据增强

Word count: 1.3kReading time: 5 min
2020/10/04 Share

关于数据增强

为什么需要大量的数据?

  • 网络模型的参数越多,需要给你的模型足够比例的样本
  • 需要的参数的个数与任务的复杂度成比例

如何获得更多的数据?

  • 不需要新奇的图片,神经网络在开始的时候并不是那么聪明,比如,一个欠训练的神经网络会认为如下的网球是不同、独特的图片。

    相同的网球,但被移位(translated)了
  • 对现有的数据集进行微小的改变
    1. 翻转(flips)、移位(translations)、旋转(rotations)等
    2. 一个卷积神经网络,如果能够对物体即使它放在不同的地方也能稳健的分类,就被称为具有不变性的属性。更具体的,CNN可以对移位(translation)、视角(viewpoint)、大小(size)、照明(illumination)(或者以上的组合)具有不变性。
  • 算法会去寻找最能区分两个类别的、最明显的特征

你的神经网络会与你喂给它的数据质量一样好或坏
通过执行数据增强,你可以阻止神经网络学习不相关的特征,从根本上提升整体性能。

数据增强的类别

  1. 线下增强(offline augmentation):适用于较小的数据集(smaller dataset),最终会增加一定的倍数的数据集。
    e.g.焊缝缺陷识别任务
  2. 线上增强(online augmentation) :适用于较大的数据集(larger datasets),因为你无法承受爆炸性增加的规模。
    e.g.yolov3中对于图片进行的小批量的转换

焊缝缺陷数据集扩充

常见的数据扩充方法

  • 一定程度内的随机旋转平移缩放裁剪填充左右翻转
  • 对图像中的像素添加噪声扰动。常见的有椒盐噪声高斯白噪声
  • 颜色变换。在图像的RGB颜色空间上添加增量;
  • 改变图片的亮度、清晰度、对比度、锐度等;
  • 除此之外,还有采样算法SMTE,生成对抗网络GAN等都可以进行图像扩充

对于我们的项目,主要用到裁剪和缩放

数据集扩充

翻转

1
2
3
4
5
6
7
8
9
10
def Image_flip(img):
"""
:param img:原始图片矩阵
:return: 0-垂直; 1-水平; -1-垂直&水平
"""
if img is None:
return # return == return none
paras = [0, 1, -1] # choice返回随机项
img_new = cv2.flip(img, choice(paras)) # cv2.flip(img,flipcode)
return img_new

平移

1
2
3
4
5
6
7
8
9
10
11
12
def Image_traslation(img):
"""
:param img: 原始图片矩阵
:return: [1, 0, 100]-宽右移100像素; [0, 1, 100]-高下移100像素
"""
paras_wide = [[1, 0, 100], [1, 0, -100]]
paras_height = [[0, 1, 100], [0, 1, -100]]
rows, cols = img.shape[:2]
img_shift = np.float32([choice(paras_wide), choice(paras_height)])
border_value = tuple(int(x) for x in choice(choice(img))) # 边界填充值
img_new = cv2.warpAffine(img, img_shift, (cols, rows), borderValue=border_value) #
return img_new

warpAffine 仿射变换
仿射变换是指在向量空间中进行一次线性变换(乘以一个矩阵)并加上一个平移(加上一个向量),变换为另一个向量空间的过程。
仿射变换可以通过一系列的原子变换的复合来实现包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear)

  • 参数
1
2
3
4
5
6
7
8
void cv::warpAffine     (   InputArray      src, # 输入图像
OutputArray dst, # 输出图像,尺寸由dsize指定,图像类型与原图像一致
InputArray M, # 2X3的变换矩阵
Size dsize, # 指定图像输出尺寸
int flags = INTER_LINEAR, # 插值算法标识符
int borderMode = BORDER_CONSTANT, # 边界像素模式
const Scalar & borderValue = Scalar() # 边界取值,有默认值Scalar()即0
)

旋转

1
2
3
4
5
6
7
8
9
10
11
12
def Image_rotate(img):
"""
:param img:原始图片矩阵
:return:旋转中心,旋转角度,缩放比例
"""
rows, cols = img.shape[:2]
rotate_core = (cols/2, rows/2)
rotate_angle = [60, -60, 45, -45, 90, -90, 210, 240, -210, -240]
paras = cv2.getRotationMatrix2D(rotate_core, choice(rotate_angle), 1)
border_value = tuple(int(x) for x in choice(choice(img)))
img_new = cv2.warpAffine(img, paras, (cols, rows), borderValue=border_value)
return img_new

高斯噪声与椒盐噪声

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
def Image_noise(img):
"""
:param img:原始图片矩阵
:return: 0-高斯噪声,1-椒盐噪声
"""
paras = [0, 1]
gaussian_class = choice(paras)
noise_ratio = [0.05, 0.06, 0.08]
if gaussian_class == 1:
output = np.zeros(img.shape, np.uint8)
prob = choice(noise_ratio)
thres = 1 - prob
#print('prob', prob)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
rdn = random.random()
if rdn < prob:
output[i][j] = 0
elif rdn > thres:
output[i][j] = 255
else:
output[i][j] = img[i][j]
return output
else:
mean = 0
var=choice([0.001, 0.002, 0.003])
#print('var', var)
img = np.array(img/255, dtype=float)
noise = np.random.normal(mean, var**0.5, img.shape)
out = img + noise
if out.min() < 0:
low_clip = -1
else:
low_clip = 0
out = np.clip(out, low_clip, 1.0)
out = np.uint8(out*255)
return out

裁剪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def Image_random_crop(image, min_ratio=0.6, max_ratio=1.0):
h, w = image.shape[:2]

ratio = random.random()

scale = min_ratio + ratio * (max_ratio - min_ratio)

new_h = int(h * scale)
new_w = int(w * scale)

y = np.random.randint(0, h - new_h)
x = np.random.randint(0, w - new_w)

image = image[y:y + new_h, x:x + new_w, :]

return image

扩充数据集的同时对标签进行操作

github下载速度慢

  • chrome下载github加速插件

数据增强

References

  1. 数据增强(Data Augmentation) https://zhuanlan.zhihu.com/p/41679153
  2. 图像采集数据集整理和扩充方案 https://blog.csdn.net/Celibrity/article/details/106297733
  3. python图片随机缩放和随机裁剪 https://blog.csdn.net/weixin_44936889/article/details/103607064
  4. 深度学习模型训练痛点及解决方法 https://blog.csdn.net/qq_37764129/article/details/89362949 这篇特别好
CATALOG
  1. 1. 关于数据增强
    1. 1.1. 为什么需要大量的数据?
    2. 1.2. 如何获得更多的数据?
    3. 1.3. 数据增强的类别
  2. 2. 焊缝缺陷数据集扩充
    1. 2.1. 常见的数据扩充方法
    2. 2.2. 数据集扩充
      1. 2.2.1. 翻转
      2. 2.2.2. 平移
      3. 2.2.3. 旋转
      4. 2.2.4. 高斯噪声与椒盐噪声
      5. 2.2.5. 裁剪
    3. 2.3. 扩充数据集的同时对标签进行操作
      1. 2.3.1. github下载速度慢
      2. 2.3.2. 数据增强
  3. 3. References