深度学习之图像数据集增强(Data Augmentation)
文章目录
- 一、 数据增强概述
- 二、python实现传统数据增强
- 参考文献
一、 数据增强概述
数据增强(Data Augmentation)是一种技术,通过对现有数据进行各种变换和处理来生成新的训练样本,从而增加数据集的多样性和数量。这些变换可以是几何变换、颜色变换、噪声添加等,使模型在训练过程中能够见到更多种类的数据,从而提升模型的泛化能力和鲁棒性。
在机器学习和深度学习中,数据的数量和质量对模型的性能至关重要。然而,获取大量标注数据通常既耗时又昂贵。数据增强通过对现有数据进行多种处理,模拟出更多样化 的训练样本,有效解决了数据稀缺的问题。这样不仅能防止模型过拟合(即模型在训练数据上表现很好,但在测试数据上表现不佳),还能够提升模型在不同情况下的表现,使其具有更强的泛化能力。
数据增强的方法多种多样,如下图所示:
这些方法各有优劣,可以根据具体任务和数据特点灵活选择和组合使用,以达到最佳的数据增强效果。通过数据增强,模型能够在有限的数据基础上获得更多的训练样本,提高训练效率和效果,最终在实际应用中表现得更加稳健和可靠。其中,传统数据增强方法比较常用且实现简单,因此本文主要实现传统数据增强的方法,其他数据增强方法后续有空再进行尝试。
二、python实现传统数据增强
import os
import random
from PIL import Image, ImageEnhance, ImageOps, ImageFilter
# 翻转图像
def flip_image(image, mode='horizontal'):
if mode == 'horizontal':
return image.transpose(Image.FLIP_LEFT_RIGHT)
elif mode == 'vertical':
return image.transpose(Image.FLIP_TOP_BOTTOM)
else:
raise ValueError("Mode should be 'horizontal' or 'vertical'")
# 旋转图像
def rotate_image(image, angle):
return image.rotate(angle)
# 缩放图像
def scale_image(image, scale_factor):
width, height = image.size
return image.resize((int(width * scale_factor), int(height * scale_factor)))
# 图像平移
def move(img): #平移,平移尺度为off
offset = ImageChops.offset(img, np.random.randint(1, 20), np.random.randint(1, 40))
return offset
# 裁剪图像
def crop_image(image, crop_box):
return image.crop(crop_box)
# 调整亮度、对比度、饱和度、色调
def adjust_color(image, brightness=1, contrast=1, saturation=1, hue=1):
enhancer = ImageEnhance.Brightness(image)
image = enhancer.enhance(brightness)
enhancer = ImageEnhance.Contrast(image)
image = enhancer.enhance(contrast)
enhancer = ImageEnhance.Color(image)
image = enhancer.enhance(saturation)
# hue adjustment not directly available in PIL, skipped
return image
# 添加噪声
def add_noise(image, noise_type='gaussian', mean=0, std=1):
# This function is a placeholder; PIL doesn't support direct noise addition
return image
# 模糊图像
def blur_image(image, blur_type='gaussian', radius=2):
if blur_type == 'gaussian':
return image.filter(ImageFilter.GaussianBlur(radius))
elif blur_type == 'motion':
return image.filter(ImageFilter.MotionBlur(radius)) # Pillow doesn't have MotionBlur, custom implementation needed
else:
raise ValueError("Blur type should be 'gaussian' or 'motion'")
# 仿射变换
def affine_transform(image, matrix):
return image.transform(image.size, Image.AFFINE, matrix)
def test():
input_image_path = 'skadi.jpg' # 输入图像路径
output_folder = 'output_path' # 输出文件夹
if not os.path.exists(output_folder):
os.makedirs(output_folder)
image = Image.open(input_image_path)
# 设置增强方法及其参数
methods = [
('flip', {'mode': 'horizontal'}),
('rotate', {'angle': 45}),
('scale', {'scale_factor': 1.5}),
('translate', {'x': 10, 'y': 20}),
('crop', {'crop_box': (10, 10, 200, 200)}),
('adjust_color', {'brightness': 1.2, 'contrast': 1.5, 'saturation': 1.3}),
('add_noise', {'noise_type': 'gaussian', 'mean': 0, 'std': 1}),
('blur', {'blur_type': 'gaussian', 'radius': 2}),
('affine', {'matrix': (1, 0.2, 0, 0.2, 1, 0)})
]
# 应用选择的增强方法
for method_name, params in methods:
if method_name == 'flip':
result_image = flip_image(image, **params)
elif method_name == 'rotate':
result_image = rotate_image(image, **params)
elif method_name == 'scale':
result_image = scale_image(image, **params)
elif method_name == 'translate':
result_image = translate_image(image, **params)
elif method_name == 'crop':
result_image = crop_image(image, **params)
elif method_name == 'adjust_color':
result_image = adjust_color(image, **params)
elif method_name == 'add_noise':
result_image = add_noise(image, **params)
elif method_name == 'blur':
result_image = blur_image(image, **params)
elif method_name == 'affine':
result_image = affine_transform(image, **params)
else:
continue
output_image_path = os.path.join(output_folder, f"{method_name}_output.jpg")
result_image.save(output_image_path)
if __name__ == '__main__':
test()
例子:对图像进行随机翻转
def pair_flip_image(img, label):
p = 0.5
if np.random.random() < p:
return flip_image(img), flip_image(label)
return img, label
def data_expand():
image_dir = r"D:\test"
image_list = os.listdir(os.path.join(image_dir, 'image'))
expand_time = 10
for idx in range(len(image_list)):
if image_list[idx].endswith(('.png', '.jpg', '.tif')):
print(image_list[idx])
image = Image.open(os.path.join(image_dir, 'image', image_list[idx]))
label = Image.open(os.path.join(image_dir, 'label', image_list[idx]))
for k in range(expand_time):
image, label = pair_flip_image(image, label)
image.save("image.png")
label.save("label.png")
if __name__ == '__main__':
data_expand()
参考文献
[1] 数据增强基本介绍和常用的数据增强方法
[2] 使用python及PIL库对图像分类数据图片进行数据增强扩充