欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

YOLOV5-6.x 解说] 数据增强方法介绍 + 代码实现数据增强方法介绍 + 代码实现

最编程 2024-03-26 22:54:09
...

主干目录:


【YOLOV5-6.x 版本讲解】整体项目代码注释导航


现在YOLOV5已经更新到6.X版本,现在网上很多还停留在5.X的源码注释上,因此特开一贴传承开源精神!5.X版本的可以看其他大佬的帖子本文章主要从6.X版本出发,主要解决6.X版本的项目注释与代码分析!......

https://blog.****.net/qq_39237205/article/details/125729662

以下内容为本栏目的一部分,更多关注以上链接目录,查找YOLOV5的更多信息

祝福你朋友早日发表sci!


1 数据增强的作用


  • 分割需要在像素级别进行标签标注


  • 一些专业领域的图像标注,依赖于专业人士的知识素养


  • 在数据集规模很小的情况,如何提高模型的表现力


  • 迁移学习:使得具有大量标注数据的源域帮助提升模型的训练效果


  • 数据增强 学习到空间的不变形,像素级别的不变形特征都有限,利用平移,缩放,旋转,改变色调值等方法,让模型见过各种类型的数据,提高模型在测试数据上的判别力


2 YOLO数据增强的方法


2.1 rectangular


2.1.1 含义


同个batch里做rectangle宽高等比变换, 加快训练 ,对于多余的黑边做到最小,实现降低计算量。


2.1.2 图解


网络异常,图片无法展示
|


2.1.3 代码


# 文件位置:utils/datasets.py
# 6、为Rectangular Training作准备:即减少大小不同图片处理时,对于多余的黑边做到最小,实现降低计算量
        # 这里主要是注意shapes的生成 这一步很重要 因为如果采样矩形训练那么整个batch的形状要一样 就要计算这个符合整个batch的shape
        # 而且还要对数据集按照高宽比进行排序 这样才能保证同一个batch的图片的形状差不多相同 再选择一个共同的shape代价也比较小
        if self.rect:
            #  所有训练图片的shape
            s = self.shapes  # wh
            # 计算高宽比
            ar = s[:, 1] / s[:, 0]  # aspect ratio
            irect = ar.argsort()    # 根据高宽比排序
            self.img_files = [self.img_files[i] for i in irect] # 获取排序后的img_files
            self.label_files = [self.label_files[i] for i in irect]  # 获取排序后的label_files
            self.labels = [self.labels[i] for i in irect]   # 获取排序后的labels
            self.shapes = s[irect]   # 获取排序后的wh
            ar = ar[irect]   # 获取排序后的wh
 
            # 计算每个batch采用的统一尺度 Set training image shapes
            shapes = [[1, 1]] * nb
            for i in range(nb):
                # 同一个batch的图片提取出来
                ari = ar[bi == i]
                mini, maxi = ari.min(), ari.max()   # 获取第i个batch中,最小和最大高宽比
                if maxi < 1:
                    # [H,W]如果高/宽小于1(w > h),宽大于高,矮胖型,(img_size*maxi,img_size)(保证原图像尺度不变进行缩放)
                    shapes[i] = [maxi, 1]
                elif mini > 1:
                    # [H,W]如果高/宽大于1(w < h),宽小于高,瘦高型,(img_size,img_size *(1/mini))(保证原图像尺度不变进行缩放)
                    shapes[i] = [1, 1 / mini]
            # 计算每个batch输入网络的shape值(向上设置为32的整数倍)
            # 要求每个batch_shapes的高宽都是32的整数倍,所以要先除以32,取整再乘以32(不过img_size如果是32倍数这里就没必要了)
            self.batch_shapes = np.ceil(np.array(shapes) * img_size / stride + pad).astype(np.int) * stride


2.2 HSV变换


2.2.1 含义


  • HSV-Hue augmentation (fraction), 色调


  • HSV-Saturation augmentation (fraction), 饱和度


  • HSV-Value augmentation (fraction), 曝光度


2.2.2 图解效果


ead454f0ce8745d99c5d52d09cc0a438.png


2.2.3 代码


# 调用函数的文件位置:文件位置:utils/datasets.py
# 色域空间增强Augment colorspace:H色调、S饱和度、V亮度
# 通过一些随机值改变hsv,实现数据增强
augment_hsv(img, hgain=hyp['hsv_h'], sgain=hyp['hsv_s'], vgain=hyp['hsv_v'])
 
# 被调用的函数位置:utils/augmentations.py
def augment_hsv(im, hgain=0.5, sgain=0.5, vgain=0.5):
    # HSV color-space augmentation
    if hgain or sgain or vgain:
        r = np.random.uniform(-1, 1, 3) * [hgain, sgain, vgain] + 1  # random gains
        hue, sat, val = cv2.split(cv2.cvtColor(im, cv2.COLOR_BGR2HSV))
        dtype = im.dtype  # uint8
 
        x = np.arange(0, 256, dtype=r.dtype)
        lut_hue = ((x * r[0]) % 180).astype(dtype)
        lut_sat = np.clip(x * r[1], 0, 255).astype(dtype)
        lut_val = np.clip(x * r[2], 0, 255).astype(dtype)
 
        im_hsv = cv2.merge((cv2.LUT(hue, lut_hue), cv2.LUT(sat, lut_sat), cv2.LUT(val, lut_val)))
        cv2.cvtColor(im_hsv, cv2.COLOR_HSV2BGR, dst=im)  # no return needed


2.3 随机旋转、平移、缩放、裁剪,错切/非垂直投影 、透视变换(从0开始)


2.3.1.1 旋转+缩放


20e19ddf4e11428d94b481e53a9f1b50.png


分析:


  • src为左边图片,dst为右边旋转缩放变换后的图片, xy为横纵坐标, M为旋转缩放矩阵


  • 旋转参数主要是M[0,1], M[1, 0]起作用, 且M[0,1], M[1, 0]互为相反数


  • 缩放参数主要是M[0,0], M[1,1]起作用


2.3.1.2 平移


d609febd94784772981558d62a5d0baa.png


  • src为左边图片, dst为右边旋转缩放变换后的图片, xy为横纵坐标, M为平移矩阵


  • x轴平移参数主要是M[0,2]起作用


  • y轴平移参数主要是M[1,2]起作用


2.3.1.3 错切/非垂直投影


74b6175ee3174a999e333396939a8ae0.png


  • 错切的类似于固定图片一边, 对另外平行一边施加一个推力形成的变形


  • src为左边图片, dst为右边错切变换后的图片, xy为横纵坐标, M为错切矩阵


  • 错切参数主要是M[0,1], M[1, 0]起作用


2.3.1.4 透视变换


36957fcf57094d05b92e77b17d435b13.png


  • src为左边图片, dst为右边透视变换后的图片, xy为横纵坐标, M为变换矩阵


  • 变换参数主要是M[2,0], M[2,1]起作用


2.3.2 代码实现


# 调用函数地址:utils/datasets.py
# Augment
        # random_perspective Augment  随机透视变换 [1280, 1280, 3] => [640, 640, 3]
        # 对mosaic整合后的图片进行随机旋转、平移、缩放、裁剪,透视变换,并resize为输入大小img_size
img4, labels4 = random_perspective(img4, labels4, segments4,
                                           degrees=self.hyp['degrees'], # 旋转
                                           translate=self.hyp['translate'], # 平移
                                           scale=self.hyp['scale'], # 缩放
                                           shear=self.hyp['shear'], # 错切/非垂直投影
                                           perspective=self.hyp['perspective'], # 透视变换
                                           border=self.mosaic_border)  # border to remove
 
# 被调用的函数地址:utils/augmentations.py
def random_perspective(im, targets=(), segments=(), degrees=10, translate=.1, scale=.1, shear=10, perspective=0.0,
                       border=(0, 0)):
    # torchvision.transforms.RandomAffine(degrees=(-10, 10), translate=(0.1, 0.1), scale=(0.9, 1.1), shear=(-10, 10))
    # targets = [cls, xyxy]
 
    height = im.shape[0] + border[0] * 2  # shape(h,w,c)
    width = im.shape[1] + border[1] * 2
 
    # Center
    C = np.eye(3)
    C[0, 2] = -im.shape[1] / 2  # x translation (pixels)
    C[1, 2] = -im.shape[0] / 2  # y translation (pixels)
 
    # Perspective # 透视变换
    P = np.eye(3)
    P[2, 0] = random.uniform(-perspective, perspective)  # x perspective (about y)
    P[2, 1] = random.uniform(-perspective, perspective)  # y perspective (about x)
 
    # Rotation and Scale 旋转+缩放
    R = np.eye(3)
    a = random.uniform(-degrees, degrees)
    # a += random.choice([-180, -90, 0, 90])  # add 90deg rotations to small rotations
    s = random.uniform(1 - scale, 1 + scale)
    # s = 2 ** random.uniform(-scale, scale)
    R[:2] = cv2.getRotationMatrix2D(angle=a, center=(0, 0), scale=s)
 
    # Shear 错切/非垂直投影
    S = np.eye(3)
    S[0, 1] = math.tan(random.uniform(-shear, shear) * math.pi / 180)  # x shear (deg)
    S[1, 0] = math.tan(random.uniform(-shear, shear) * math.pi / 180)  # y shear (deg)
 
    # Translation 平移
    T = np.eye(3)
    T[0, 2] = random.uniform(0.5 - translate, 0.5 + translate) * width  # x translation (pixels)
    T[1, 2] = random.uniform(0.5 - translate, 0.5 + translate) * height  # y translation (pixels)
<					

推荐阅读