目标检测xml文件实现mixup数据增强(修改文件路径直接能用,非常方便)

在这里,先给出原博主的代码:https://blog.csdn.net/qq_36756866/article/details/106299705
这个代码有一些bug,并且生成数据的数量并不能任意改变,于是我自己修改了一部分代码,实现生成任意数据量的功能。使用只需修改文件路径即可,非常方便,不会有任何bug。代码如下:

# coding:utf-8

import cv2
import os
import random
import numpy as np
import xml.etree.ElementTree as ET
import xml.dom.minidom

img_path = '/root/wu_datasets/ReCurrentPapper/data/DOTA/DOTAship/VOCdevkit/VOC2012/JPEGImages/'           # 原始图片文件夹路径
save_path = '/root/wu_datasets/ReCurrentPapper/data/DOTA_mixup/VOCdevkit/VOC2012/JPEGImages/'       # mixup的图片文件夹路径
xml_path = '/root/wu_datasets/ReCurrentPapper/data/DOTA/DOTAship/VOCdevkit/VOC2012/Annotations/'           # 原始图片对应的标注文件xml文件夹的路径
save_xml = '/root/wu_datasets/ReCurrentPapper/data/DOTA_mixup/VOCdevkit/VOC2012//Annotations/'        # mixup的图片对应的标注文件xml的文件夹路径
img_names = os.listdir(img_path)
img_num = len(img_names)
#print(img_names)
# sum 代表生成数据的总和
sum = []
# 这里表示比原先数据集多10倍
for i in range(10):
    for i in range(0, img_num):
        sum.append(i)
# print(sum)
cnt = 0
for k in sum:
    cnt += 1
    print(cnt)
    imgname = img_names[k]
    imgpath = img_path + imgname
    img = cv2.imread(imgpath)
    img_h, img_w = img.shape[0], img.shape[1]
    # print(img_h,img_w)

    i = random.randint(0, img_num - 1)
    add_path = img_path + img_names[i]
    addimg = cv2.imread(add_path)
    add_h, add_w = addimg.shape[0], addimg.shape[1]
    if add_h != img_h or add_w != img_w:
        print('resize!')
        addimg = cv2.resize(addimg, (img_w, img_h), interpolation=cv2.INTER_LINEAR)
    scale_h, scale_w = img_h / add_h, img_w / add_w

    lam = np.random.beta(1.5, 1.5)
    # print(lam)
    mixed_img = lam * img + (1 - lam) * addimg
    save_img = save_path + str(cnt) + '.jpg'
    cv2.imwrite(save_img, mixed_img)
    # print(save_img)

    # print(imgname, img_names[i])
    if imgname != img_names[i]:
        xmlfile1 = xml_path + imgname[:-4] + '.xml'
        xmlfile2 = xml_path + img_names[i][:-4] + '.xml'
        # print(xmlfile1,xmlfile2)

        tree1 = ET.parse(xmlfile1)
        tree2 = ET.parse(xmlfile2)

        doc = xml.dom.minidom.Document()
        root = doc.createElement("annotation")
        doc.appendChild(root)


        for folds in tree1.findall("folder"):
            folder = doc.createElement("folder")
            folder.appendChild(doc.createTextNode(str(folds.text)))
            root.appendChild(folder)
        for filenames in tree1.findall("filename"):
            filename = doc.createElement("filename")
            filename.appendChild(doc.createTextNode("{}.jpg".format(cnt)))
            root.appendChild(filename)
        for paths in tree1.findall("path"):
            path = doc.createElement("path")
            path.appendChild(doc.createTextNode(str(paths.text)))
            root.appendChild(path)
        for sources in tree1.findall("source"):
            source = doc.createElement("source")
            database = doc.createElement("database")
            database.appendChild(doc.createTextNode(str("Unknow")))
            source.appendChild(database)
            root.appendChild(source)
        for sizes in tree1.findall("size"):
            size = doc.createElement("size")
            width = doc.createElement("width")
            height = doc.createElement("height")
            depth = doc.createElement("depth")
            width.appendChild(doc.createTextNode(str(img_w)))
            height.appendChild(doc.createTextNode(str(img_h)))
            depth.appendChild(doc.createTextNode(str(3)))
            size.appendChild(width)
            size.appendChild(height)
            size.appendChild(depth)
            root.appendChild(size)

        nodeframe = doc.createElement("frame")
        nodeframe.appendChild(doc.createTextNode(imgname[:-4]))

        objects = []

        for obj in tree1.findall("object"):
            obj_struct = {}
            obj_struct["name"] = obj.find("name").text
            obj_struct["pose"] = obj.find("pose").text
            obj_struct["truncated"] = obj.find("truncated").text
            obj_struct["difficult"] = obj.find("difficult").text
            bbox = obj.find("bndbox")
            obj_struct["bbox"] = [int(bbox.find("xmin").text),
                                  int(bbox.find("ymin").text),
                                  int(bbox.find("xmax").text),
                                  int(bbox.find("ymax").text)]
            objects.append(obj_struct)

        for obj in tree2.findall("object"):
            obj_struct = {}
            obj_struct["name"] = obj.find("name").text
            obj_struct["pose"] = obj.find("pose").text
            obj_struct["truncated"] = obj.find("truncated").text
            obj_struct["difficult"] = obj.find("difficult").text          # 有的版本的labelImg改参数为小写difficult
            bbox = obj.find("bndbox")
            obj_struct["bbox"] = [int(int(bbox.find("xmin").text) * scale_w),
                                  int(int(bbox.find("ymin").text) * scale_h),
                                  int(int(bbox.find("xmax").text) * scale_w),
                                  int(int(bbox.find("ymax").text) * scale_h)]
            objects.append(obj_struct)

        for obj in objects:
            nodeobject = doc.createElement("object")
            nodename = doc.createElement("name")
            nodepose = doc.createElement("pose")
            nodetruncated = doc.createElement("truncated")
            nodedifficult = doc.createElement("difficult")
            nodebndbox = doc.createElement("bndbox")
            nodexmin = doc.createElement("xmin")
            nodeymin = doc.createElement("ymin")
            nodexmax = doc.createElement("xmax")
            nodeymax = doc.createElement("ymax")
            nodename.appendChild(doc.createTextNode(obj["name"]))
            nodepose.appendChild(doc.createTextNode(obj["pose"]))
            nodetruncated.appendChild(doc.createTextNode(obj["truncated"]))
            nodedifficult.appendChild(doc.createTextNode(obj["difficult"]))
            nodexmin.appendChild(doc.createTextNode(str(obj["bbox"][0])))
            nodeymin.appendChild(doc.createTextNode(str(obj["bbox"][1])))
            nodexmax.appendChild(doc.createTextNode(str(obj["bbox"][2])))
            nodeymax.appendChild(doc.createTextNode(str(obj["bbox"][3])))

            nodebndbox.appendChild(nodexmin)
            nodebndbox.appendChild(nodeymin)
            nodebndbox.appendChild(nodexmax)
            nodebndbox.appendChild(nodeymax)

            nodeobject.appendChild(nodename)
            nodeobject.appendChild(nodepose)
            nodeobject.appendChild(nodetruncated)
            nodeobject.appendChild(nodedifficult)
            nodeobject.appendChild(nodebndbox)

            root.appendChild(nodeobject)

        fp = open(save_xml + str(cnt) + ".xml", "w")
        doc.writexml(fp, indent='\t', addindent='\t', newl='\n', encoding="utf-8")
        fp.close()

    else:
        xmlfile1 = xml_path + imgname[:-4] + '.xml'
        # print(xmlfile1)
        tree1 = ET.parse(xmlfile1)

        doc = xml.dom.minidom.Document()
        root = doc.createElement("annotation")


        doc.appendChild(root)

        for folds in tree1.findall("folder"):
            folder=doc.createElement("folder")
            folder.appendChild(doc.createTextNode(str(folds.text)))
            root.appendChild(folder)
        for filenames in tree1.findall("filename"):
            filename=doc.createElement("filename")
            filename.appendChild(doc.createTextNode("{}.jpg".format(cnt)))
            root.appendChild(filename)
        for paths in tree1.findall("path"):
            path = doc.createElement("path")
            path.appendChild(doc.createTextNode(str(paths.text)))
            root.appendChild(path)
        for sources in tree1.findall("source"):
            source = doc.createElement("source")
            database = doc.createElement("database")
            database.appendChild(doc.createTextNode(str("Unknow")))
            source.appendChild(database)
            root.appendChild(source)
        for sizes in tree1.findall("size"):
            size = doc.createElement("size")
            width = doc.createElement("width")
            height = doc.createElement("height")
            depth = doc.createElement("depth")
            width.appendChild(doc.createTextNode(str(img_w)))
            height.appendChild(doc.createTextNode(str(img_h)))
            depth.appendChild(doc.createTextNode(str(3)))
            size.appendChild(width)
            size.appendChild(height)
            size.appendChild(depth)
            root.appendChild(size)


        nodeframe = doc.createElement("frame")
        nodeframe.appendChild(doc.createTextNode(imgname[:-4]))
        objects = []

        for obj in tree1.findall("object"):
            obj_struct = {}
            obj_struct["name"] = obj.find("name").text
            obj_struct["pose"] = obj.find("pose").text
            obj_struct["truncated"] = obj.find("truncated").text
            obj_struct["difficult"] = obj.find("difficult").text
            bbox = obj.find("bndbox")
            obj_struct["bbox"] = [int(bbox.find("xmin").text),
                                  int(bbox.find("ymin").text),
                                  int(bbox.find("xmax").text),
                                  int(bbox.find("ymax").text)]
            objects.append(obj_struct)

        for obj in objects:
            nodeobject = doc.createElement("object")
            nodename = doc.createElement("name")
            nodepose = doc.createElement("pose")
            nodetruncated = doc.createElement("truncated")
            nodedifficult = doc.createElement("difficult")
            nodebndbox = doc.createElement("bndbox")
            nodexmin = doc.createElement("xmin")
            nodeymin = doc.createElement("ymin")
            nodexmax = doc.createElement("xmax")
            nodeymax = doc.createElement("ymax")
            nodename.appendChild(doc.createTextNode(obj["name"]))
            nodepose.appendChild(doc.createTextNode(obj["pose"]))
            nodetruncated.appendChild(doc.createTextNode(obj["truncated"]))
            nodedifficult.appendChild(doc.createTextNode(obj["difficult"]))
            nodexmin.appendChild(doc.createTextNode(str(obj["bbox"][0])))
            nodeymin.appendChild(doc.createTextNode(str(obj["bbox"][1])))
            nodexmax.appendChild(doc.createTextNode(str(obj["bbox"][2])))
            nodeymax.appendChild(doc.createTextNode(str(obj["bbox"][3])))

            nodebndbox.appendChild(nodexmin)
            nodebndbox.appendChild(nodeymin)
            nodebndbox.appendChild(nodexmax)
            nodebndbox.appendChild(nodeymax)

            nodeobject.appendChild(nodename)
            nodeobject.appendChild(nodepose)
            nodeobject.appendChild(nodetruncated)
            nodeobject.appendChild(nodedifficult)
            nodeobject.appendChild(nodebndbox)

            root.appendChild(nodeobject)

        fp = open(save_xml + str(cnt) + ".xml", "w")
        doc.writexml(fp, indent='\t', addindent='\t', newl='\n', encoding="utf-8")
        fp.close()

<think>嗯,用户想了解如何实现基于YOLOX的缺陷检测方法。首先,我需要回忆YOLOX的基本结构和特点。YOLOX是YOLO系列的一个改进版本,引入了无锚框(anchor-free)、解耦头(Decoupled Head)和SimOTA动态标签分配等新技术,这些改进应该能提升检测的精度和效率,尤其是在缺陷检测这种可能需要检测小目标的场景里。 接下来,用户可能需要具体的步骤,比如环境配置、数据集准备、模型训练和测试。根据引用[1],安装依赖是关键的一步,使用清华镜像源可以加速安装。然后,数据集的准备需要符合YOLOX的格式,比如VOC或COCO格式,用户可能需要自己标注缺陷数据,或者转换现有数据集。引用[2]提到YOLOX的改动较多,训练速度慢,但模型精度不错,这点需要提醒用户可能需要较长的训练时间,或者考虑使用预训练模型进行微调。 然后,修改配置文件。YOLOX的配置文件通常存放在exps目录下,用户需要根据缺陷类别数修改类别数和调整数据路径。这里可能需要指导用户如何正确修改参数,比如num_classes和data_dir。模型训练时,引用[3]中的命令行参数可以作为参考,比如指定配置文件、预训练权重和设备类型。 在模型测试和部署阶段,引用[3]提供的demo.py脚本可以用来测试单张图像,用户需要调整路径和参数。另外,YOLOX提供的部署工具对工程化有帮助,用户可能关心如何将模型部署到实际应用中,比如使用ONNX或TensorRT。 优化方法方面,引用[2]提到的解耦头、无锚框和SimOTA是关键点,可能需要详细解释这些技术如何提升缺陷检测的效果。此外,数据增强策略也很重要,比如Mosaic和MixUp,但用户需要注意如果缺陷目标较小,可能需要调整这些增强的参数,或者禁用部分可能干扰小目标检测数据增强。 用户可能遇到的问题包括环境配置错误、数据集格式不匹配、训练过程中的参数调整等。需要提醒用户注意检查文件路径、类别标签是否正确,以及硬件资源是否足够支持训练。另外,如果训练速度过慢,建议用户减少输入尺寸或调整批量大小,但可能影响精度,需要权衡。 最后,用户可能需要实际案例或者更详细的教程链接,但根据现有引用,可能没有直接提供,所以建议参考官方文档和社区资源。同时,引用[4]提到的ConvNeXtV2块可能不是YOLOX的一部分,但如果有自定义模型的需求,可能需要指导用户如何集成其他模块,但这可能属于高级内容,暂时不深入。</think>### 基于YOLOX的缺陷检测实现方法 #### 1. **环境配置** - **步骤1**:下载YOLOX源码并安装依赖 从官方仓库克隆代码,执行以下命令安装依赖(建议使用清华镜像加速)[^1]: ```bash pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple ``` - **步骤2**:配置训练设备 支持CPU/GPU训练,GPU需安装CUDA和PyTorch适配版本。 #### 2. **数据集准备** - **数据格式**:需转换为VOC或COCO格式,目录结构如下: ``` dataset/ ├── annotations # 标注文件XML/JSON) ├── images # 图像文件 └── train_val.txt # 训练验证集划分 ``` - **标注要求**:缺陷目标需标注为矩形框,保存为XML(VOC)或JSON(COCO)。 #### 3. **修改配置文件** - **步骤1**:调整模型参数 在`exps/example/yolox_voc/yolox_voc_s.py`中修改类别数: ```python self.num_classes = 1 # 缺陷类别数 ``` - **步骤2**:设置数据路径 修改`data_dir`和`image_sets`指向自定义数据集路径。 #### 4. **模型训练** - **启动训练**: ```bash python tools/train.py -f exps/example/yolox_voc/yolox_voc_s.py -d 1 -b 8 --fp16 -c yolox_s.pth ``` - `-d`: 显卡编号 - `-b`: 批次大小 - `--fp16`: 混合精度训练加速 - `-c`: 预训练权重路径[^2] #### 5. **模型测试与部署** - **单图测试**: ```bash python tools/demo.py image -f exps/example/yolox_voc/yolox_voc_s.py -c best_ckpt.pth --path test.jpg --conf 0.3 --nms 0.5 --tsize 640 --device gpu ``` - `--tsize`: 输入图像尺寸 - `--save_result`: 保存检测结果图[^3] - **部署优化**: YOLOX支持ONNX/TensorRT导出,使用`tools/export_onnx.py`转换模型。 #### 6. **关键优化方法** 1. **数据增强策略**: - 启用Mosaic和MixUp提升小目标检测能力 - 调整HSV增强参数适应工业场景光照变化 2. **动态标签分配(SimOTA)**: 根据目标复杂度动态分配正样本,提升密集缺陷检测效果。 3. **解耦头设计**: 分类与回归任务分离,减少特征冲突[^2]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值