YOLO系列基础(七)从数据增强到图像线性变换
系列文章地址
YOLO系列基础(一)卷积神经网络原理详解与基础层级结构说明-CSDN博客
YOLO系列基础(二)Bottleneck瓶颈层原理详解-CSDN博客
YOLO系列基础(三)从ResNet残差网络到C3层-CSDN博客
YOLO系列基础(四)归一化层(BN层)的前世今生!-CSDN博客
YOLO系列基础(五)从神经元共适应性到模型Dropout层-CSDN博客
YOLO系列基础(六)YOLOv1原理详解原理如此清晰-CSDN博客
背景
随着YOLOv11版本的发布,YOLO算法在视觉检测领域独领风骚,本系列旨在从小白出发,给大家讲解清楚视觉检测算法的前世今生,并讲清楚YOLOv11版本算法的所有模块功能!
但此篇我们先讲解另外一个操作:数据增强和图像的线性变换
从数据集的多样性和过拟合开始
过拟合问题一般来说有两种因素共同影响。
- 神经网络设定不合理,造成神经元共适应性现象
- 数据集多样性不足,场景单一
有关于神经网络的设定问题以查看一下此篇博客:
YOLO系列基础(五)从神经元共适应性到模型Dropout层-CSDN博客
本篇我们详解数据集导致的过拟合问题,其实我们对于数据集的多样性不足会导致过拟合问题已经有了很深的印象,有些人也能侃侃而谈一些原因,但是都不够全面。
什么是过拟合问题?
过拟合(Overfitting)是机器学习中的一个常见问题,指的是模型在训练数据上表现得过于出色,以至于它开始捕捉并学习训练数据中的噪声和随机波动,而不是学习数据的潜在规律或模式。这种情况发生时,模型在训练集上的性能(如准确率、召回率等指标)通常非常高,但在未见过的数据(如测试集或实际应用中的数据)上的性能却显著下降。
过拟合的模型往往过于复杂,它们包含了大量的参数和细节,这些参数和细节对于训练数据是有效的,但对于新的、类似的数据则不再有效。这通常发生在模型具有比训练数据中的信息量更多的自由参数时,或者当训练数据不足够多样或数量不足时。
数据集的多样性不足是如何导致过拟合的?
模型记忆噪声
首先我们要知道,噪声是不可避免的,就算你的数据集再优异,都存在噪声。而且从某种意义上说,缺乏足够噪声的数据集反而是不够好的,因为现实世界是存在噪声的。
而当数据集缺乏多样性时,模型会记住训练数据中的噪声和特定模式,而不是学习到数据的普遍规律。这导致模型在训练集上表现良好,但在未见过的数据(如测试集)上表现不佳,因为测试集上没有模型记忆中相同的噪声。
特征场景覆盖不全
多样性不足的数据集无法涵盖所有可能的特征组合和边缘情况。这导致模型在训练时无法充分学习数据的全部分布,从而在面对新数据时无法做出准确的预测。
人话说就是目标物体的所有特征信息数据集中并没有全面展示。
偏差样本问题
当数据集的多样性不足的时候,会容易造成训练数据集中某些类别的样本数量远多于其他类别,或者数据集的分布与真实世界的分布不一致,那么模型可能会学习到这种偏差。这种偏差在模型面对真实世界数据时会导致性能下降。
举个例子:如果你的数据集中北极熊出现在冰天雪地的照片远远多于动物园的照片,那么你的模型将难以检测动物园中的北极熊。
综上,我们需要多样化的数据集,而如何获取多样化的数据集呢?答案就是数据增强
数据增强
但是数据集的采集、标注耗时耗力,很多优秀的数据集大多都是不开源的。那么我们就有了数据增强的需要
数据增强的概念最早由Simard在1998年提出,随着2000年VRM(Vicinal Risk Minimization)准则的提出,数据增强技术被正式标准化。
数据增强的好处
数据增强是一种通过人工或自动方式对数据进行修改或变换,以增加数据集规模和多样性的技术。其主要目的是:
- 提高模型的泛化能力:通过生成更多的训练样本,模型可以学习到更多的特征,从而提高对未见数据的预测能力。
- 减少过拟合:数据增强可以增加数据集的多样性,使得模型不会过度依赖于某些特定的特征,从而减少过拟合的风险。
- 降低数据收集成本:在某些情况下,收集和标记新的数据非常困难或昂贵。数据增强可以通过对已有数据进行变换来生成新的样本,从而降低数据收集的成本。
图片数据增强的方式大全
图片数据增强是计算机视觉和图像处理领域中的一个关键技术,主要用于改善图像的质量或者使其更适合后续的图像分析任务。以下是一些常见的图片数据增强方式:
几何变换
- 翻转:水平翻转:使图像左右对称。垂直翻转:使图像上下对称。
import cv2
# 读取图像
image = cv2.imread('path_to_image.jpg')
def get_flipped(image, way):
'''
翻转函数,way=1 水平翻转,way=0 垂直反转
'''
return cv2.flip(image, way)
- 旋转:随机旋转图像一定角度,常见角度范围为0到360度,可以模拟不同角度的视图。
def get_rotated(iamge, angle):
'''旋转图像angle角度'''
# 获取图像尺寸
(h, w) = image.shape[:2]
# 计算中心
center = (w // 2, h // 2)
# 旋转图像(角度为45度)
rotated = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, rotated, (w, h))
return rotated
- 缩放:随机放大或缩小图像,以不同的比例缩放图像,使模型适应不同尺寸的物体。
def get_scaled(image, fx=0.5, fy=0.5):
'''缩放图像,fx和fy为x轴和y轴的缩放系数'''
scaled = cv2.resize(image, None, fx=fx, fy=fy, interpolation=cv2.INTER_AREA)
return scaled
- 裁剪:随机裁剪图像的一部分,可以是中心裁剪或随机裁剪,以增加数据多样性。
def get_cropped(image, (x1,y1), (x2, y2)):
# 裁剪图像(左上角和右下角坐标)
cropped = image[y1:y2, x1:x2]
return cropped
- 平移:在水平和垂直方向上移动图像的内容,帮助模型学习到物体在不同位置的特征。
def get_translated(image, dx=100,dy=50):
# 平移矩阵(默认向右平移100,向下平移50)
M = np.float32([[1, 0, 100], [0, 1, 50]])
return cv2.warpAffine(image, M, (w, h))
- 透视变换:改变图像的透视角度,模拟不同的视角效果。
# 定义源点和目标点
pts1 = np.float32([[50, 50], [200, 50], [50, 200], [200, 200]])
pts2 = np.float32([[10, 100], [200, 50], [10, 250], [200, 200]])
# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)
# 应用透视变换
warped = cv2.warpPerspective(image, M, (w, h))
颜色变换
- 亮度调整:通过增加或减少图像的亮度值来改变图像的整体亮度,模拟不同的光照条件。
# 增加亮度(值为正数)或减少亮度(值为负数)
beta = 30 # 亮度增量
adjusted_brightness = cv2.convertScaleAbs(image, alpha=1, beta=beta)
- 对比度调整:通过改变图像中亮度值的分布来增强图像的对比度,使得图像中的细节更加清晰。
# 对比度控制(alpha值)
alpha = 1.5 # 对比度因子
adjusted_contrast = cv2.convertScaleAbs(image, alpha=alpha, beta=0)
- 饱和度调整:通过改变颜色的饱和程度来影响图像的色彩表现,增加饱和度可以使颜色更加鲜艳,而降低饱和度则会使颜色趋向灰色。
# 转换为HSV颜色空间
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 调整饱和度(S通道)
h, s, v = cv2.split(hsv)
s = cv2.add(s, 50) # 增加饱和度
s = cv2.clip(s, 0, 255).astype(hsv.dtype) # 裁剪并转换类型
# 合并通道并转换回BGR颜色空间
adjusted_saturation = cv2.merge([h, s, v])
adjusted_saturation = cv2.cvtColor(adjusted_saturation, cv2.COLOR_HSV2BGR)
- 色相调整:通过改变颜色的色相值来改变图像的整体色调,可以用来生成不同色彩风格的图像。
# 调整色相(H通道)
h, s, v = cv2.split(hsv)
h = cv2.add(h, 30) # 增加色相值(注意循环)
h[h >= 180] -= 180 # 处理超过180的情况
# 合并通道并转换回BGR颜色空间
adjusted_hue = cv2.merge([h, s, v])
adjusted_hue = cv2.cvtColor(adjusted_hue, cv2.COLOR_HSV2BGR)
噪声添加
- 高斯噪声:模拟传感器噪声。
# 生成高斯噪声
mean = 0
sigma = 25
gauss = np.random.normal(mean, sigma, image.shape).astype('uint8')
# 将噪声添加到图像
noisy = cv2.add(image, gauss)
- 椒盐噪声:模拟图像传输中的干扰,图像中随机出现亮点(盐)和暗点(胡椒)。
# 生成椒盐噪声
num_salt = 1000 # 盐的数量
num_pepper = 1000 # 椒的数量
# 盐噪声
img = image.copy()
coords = [np.random.randint(0, i - 1, num_salt) for i in image.shape]
img[coords[0], coords[1], :] = 255
# 椒噪声
coords = [np.random.randint(0, i - 1, num_pepper) for i in image.shape]
img[coords[0], coords[1], :] = 0
noisy_salt_pepper = img
- 高斯模糊:对图像应用高斯模糊,以模拟景深或模糊效果。
Mixup:通过混合两张图像及其对应的标签来生成新的训练样本。具体来说,给定两对训练样本,通过线性插值的方式将两张输入图像及其标签混合生成新的训练样本。
这些图片数据增强技术可以单独使用,也可以组合使用,以提高训练数据的多样性和模型的鲁棒性。在实际应用中,可以根据具体任务和数据集特点选择合适的数据增强方法。