yolov5标签数据增强脚本

此代码用于将标注好的图片及其标签进行数据增强,优点在于不需要重新打标签

import xml.etree.ElementTree as ET
import os
import numpy as np
from PIL import Image
import shutil
import imgaug as ia
from imgaug import augmenters as iaa
from tqdm import tqdm


def read_xml_annotation(root, image_id):
    in_file = open(os.path.join(root, image_id), encoding='UTF-8')
    # print(in_file)
    tree = ET.parse(in_file)
    root = tree.getroot()
    bndboxlist = []

    for object in root.findall('object'):  # 找到root节点下的所有country节点
        bndbox = object.find('bndbox')  # 子节点下节点rank的值

        xmin = int(bndbox.find('xmin').text)
        xmax = int(bndbox.find('xmax').text)
        ymin = int(bndbox.find('ymin').text)
        ymax = int(bndbox.find('ymax').text)
        # print(xmin,ymin,xmax,ymax)
        bndboxlist.append([xmin, ymin, xmax, ymax])
        # print(bndboxlist)

    # ndbox = root.find('object').find('bndbox')
    return bndboxlist



def change_xml_list_annotation(root, image_id, new_target, saveroot, xml_id):
    save_path = os.path.join(saveroot, xml_id)
    in_file = open(os.path.join(root, str(image_id) + '.xml'), encoding='UTF-8')  # 这里root分别由两个意思
    tree = ET.parse(in_file)
    elem = tree.find('filename')
    elem.text = xml_id + img_type
    xmlroot = tree.getroot()
    index = 0

    for object in xmlroot.findall('object'):  # 找到root节点下的所有country节点
        bndbox = object.find('bndbox')  # 子节点下节点rank的值

        new_xmin = new_target[index][0]
        new_ymin = new_target[index][1]
        new_xmax = new_target[index][2]
        new_ymax = new_target[index][3]

        xmin = bndbox.find('xmin')
        xmin.text = str(new_xmin)
        ymin = bndbox.find('ymin')
        ymin.text = str(new_ymin)
        xmax = bndbox.find('xmax')
        xmax.text = str(new_xmax)
        ymax = bndbox.find('ymax')
        ymax.text = str(new_ymax)

        index += 1

    tree.write(save_path + '.xml')


def simple_example(AUGLOOP,IMG_DIR,XML_DIR,AUG_IMG_DIR,AUG_XML_DIR):
    boxes_img_aug_list = []
    new_bndbox_list = []
    new_name = None

    for root, sub_folders, files in os.walk(XML_DIR):
        for name in tqdm(files):
            bndbox = read_xml_annotation(XML_DIR, name)
            shutil.copy(os.path.join(XML_DIR, name), AUG_XML_DIR)
            try:
                shutil.copy(os.path.join(IMG_DIR, name[:-4] + img_type), AUG_IMG_DIR)
            except:
                shutil.copy(os.path.join(IMG_DIR, name[:-4] + '.JPG'), AUG_IMG_DIR)
            # print(os.path.join(IMG_DIR, name[:-4] + img_type))

            for epoch in range(1, AUGLOOP + 1):
                # 增强
                if epoch == 1:
                    seq = iaa.Sequential([
                        ####0.75-1.5随机数值为alpha,对图像进行对比度增强,该alpha应用于每个通道
                        iaa.ContrastNormalization((0.75, 1.5), per_channel=True),
                    ])
                elif epoch == 2:
                    seq = iaa.Sequential([
                        #### loc 噪声均值,scale噪声方差,50%的概率,对图片进行添加白噪声并应用于每个通道
                        iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.1 * 255), per_channel=0.75),
                    ])
                elif epoch == 3:
                    seq = iaa.Sequential([
                        iaa.Fliplr(1),  # 水平镜像翻转
                    ])
                # else:
                #     seq = iaa.Sequential([
                #         iaa.OneOf([iaa.Affine(rotate=90),
                #                    iaa.Affine(rotate=90),
                #                    iaa.Affine(rotate=270),
                #                    iaa.Affine(rotate=180),
                #                    iaa.Affine(rotate=180),
                #                    iaa.Affine(rotate=270)])
                #     ])
                seq_det = seq.to_deterministic()  # 保持坐标和图像同步改变,而不是随机
                # 读取图片
                try:
                    img = Image.open(os.path.join(IMG_DIR, name[:-4] + img_type))
                except:
                    img = Image.open(os.path.join(IMG_DIR, name[:-4] + '.JPG'))

                # JPG不支持alpha透明度,有可能报RGBA错误,将图片丢弃透明度转成RGB
                img = img.convert('RGB')
                # sp = img.size
                img = np.asarray(img)
                # bndbox 坐标增强
                for i in range(len(bndbox)):
                    bbs = ia.BoundingBoxesOnImage([
                        ia.BoundingBox(x1=bndbox[i][0], y1=bndbox[i][1], x2=bndbox[i][2], y2=bndbox[i][3]),
                    ], shape=img.shape)

                    bbs_aug = seq_det.augment_bounding_boxes([bbs])[0]
                    boxes_img_aug_list.append(bbs_aug)

                    # new_bndbox_list:[[x1,y1,x2,y2],...[],[]]
                    n_x1 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x1)))
                    n_y1 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y1)))
                    n_x2 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x2)))
                    n_y2 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y2)))
                    if n_x1 == 1 and n_x1 == n_x2:
                        n_x2 += 1
                    if n_y1 == 1 and n_y2 == n_y1:
                        n_y2 += 1
                    if n_x1 >= n_x2 or n_y1 >= n_y2:
                        print('error', name)
                    new_bndbox_list.append([n_x1, n_y1, n_x2, n_y2])

                    # 存储变化后的图片
                    image_aug = seq_det.augment_images([img])[0]
                    # 新文件名
                    new_name = name[:-4] + '-' + str(epoch)
                    path = os.path.join(AUG_IMG_DIR, new_name + img_type)

                    image_auged = bbs.draw_on_image(image_aug, thickness=0)
                    Image.fromarray(image_auged).save(path)

                # 存储变化后的XML
                change_xml_list_annotation(XML_DIR, name[:-4], new_bndbox_list, AUG_XML_DIR, new_name)
                new_bndbox_list = []


if __name__ == "__main__":

    # 随机种子
    ia.seed(1)
    img_type = '.jpg'
    # img_type = '.png'

    # 原数据路径
    IMG_DIR = "/media/bvision/My Book/boatDetail/images/"
    XML_DIR = "/media/bvision/My Book/boatDetail/xml/"

    # 存储增强后的影像文件夹路径
    AUG_IMG_DIR = "/media/bvision/My Book/boatDetail/new_img/"
    if not os.path.exists(AUG_IMG_DIR):
        os.mkdir(AUG_IMG_DIR)

    # 存储增强后的XML文件夹路径
    AUG_XML_DIR = "/media/bvision/My Book/boatDetail/new_xml/"
    if not os.path.exists(AUG_XML_DIR):
        os.mkdir(AUG_XML_DIR)

    # 数据增强n倍
    simple_example(3, IMG_DIR, XML_DIR, AUG_IMG_DIR, AUG_XML_DIR)
  • 7
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
YOLOv5是目前最先进的目标检测模型之一,他的数据增强代码优秀的贡献了YOLOv5的精度和鲁棒性。数据增强深度学习中最核心的手段之一,对数据集进行平移、旋转、缩放、颜色增强等操作,使得数据集变得更加丰富多样,这可以有效提高模型训练的效果。下面介绍YOLOv5数据增强代码YOLOv5的data.py文件中,增加了以下的增强操作,代码如下: 1.随机缩放:可以将图像随机缩放到指定的尺寸,这样可以增加模型对不同尺度物体的适应性。 def random_scale(img, scale_range=(0.1, 2), target_size=None): if random.random() < 0.5: if target_size is None: h, w = img.shape[:2] target_size = (int(w * random.uniform(scale_range[0], scale_range[1])), int(h * random.uniform(scale_range[0], scale_range[1]))) img = cv2.resize(img, target_size, interpolation=cv2.INTER_LINEAR) return img 2.随机翻转:可以将图像随机左右翻转或上下翻转,扩增数据集,减小过拟合的风险。 def random_horizontal_flip(img, prob=0.5): if random.random() < prob: return cv2.flip(img, 1) return img def random_vertical_flip(img, prob=0.5): if random.random() < prob: return cv2.flip(img, 0) return img 3.随机裁剪:可以将图像随机裁剪到指定大小,这样可以增加模型对不同物体大小的适应性。 def random_crop(img, bboxes, crop_size, max_trial=50, min_scale=0.3): h, w = img.shape[:2] crop_h, crop_w = crop_size for i in range(max_trial): scale = random.uniform(min_scale, 1) aspect_ratio = random.uniform(0.5, 2) crop_h_scale = int(round(crop_h * math.sqrt(aspect_ratio) * scale)) crop_w_scale = int(round(crop_w / math.sqrt(aspect_ratio) * scale)) if crop_h_scale <= h and crop_w_scale <= w: y = random.randint(0, h - crop_h_scale) x = random.randint(0, w - crop_w_scale) crop_img = img[y:y + crop_h_scale, x:x + crop_w_scale] new_bboxes = bboxes.copy() new_bboxes[:, [0, 2]] = bboxes[:, [0, 2]] - x new_bboxes[:, [1, 3]] = bboxes[:, [1, 3]] - y new_bboxes[:, [0, 2]] = np.clip(new_bboxes[:, [0, 2]], 0, crop_w_scale - 1) new_bboxes[:, [1, 3]] = np.clip(new_bboxes[:, [1, 3]], 0, crop_h_scale - 1) new_bboxes = new_bboxes[(new_bboxes[:, 2] - new_bboxes[:, 0] >= 1) & (new_bboxes[:, 3] - new_bboxes[:, 1] >= 1)] if new_bboxes.shape[0] != 0: return crop_img, new_bboxes return img, bboxes 4.颜色变化:可以对图像进行颜色变化,增加模型对不同光照环境下的适应性。 def random_color_distort(img, brightness_delta=32, contrast_low=0.5, contrast_high=1.5, saturation_low=0.5, saturation_high=1.5, hue_delta=18): if random.random() < 0.5: img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) img = np.array(img, dtype=np.float32) img[:, :, 0] = (img[:, :, 0] + random.uniform(-hue_delta, hue_delta)) % 180 img[:, :, 1] = np.clip(img[:, :, 1] * random.uniform(saturation_low, saturation_high), 0, 255) img[:, :, 2] = np.clip(img[:, :, 2] * random.uniform(contrast_low, contrast_high) + random.uniform(-brightness_delta, brightness_delta), 0, 255) img = np.array(img, dtype=np.uint8) img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR) return img 以上是YOLOv5数据增强代码,可以通过上述增强手段扩大数据集,增加对物体姿态、角度、亮度等复杂情况的适应能力,提高模型性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI小笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值