VOC格式数据集转适用YOLOv8格式

2023-11-18

直接设置VOC数据集的文件夹目录、生成的v8格式数据集存放目录以及标签的名字就行了

直接执行后就会是下面这图这样重新创建一个文件夹存放符合yolov8格式的数据集,yolov8直接加载那个yaml文件就行
在这里插入图片描述

我下边只有一类,注意最后的yaml文件,里面存放的是train.txtval.txttest.txt的绝对路径,我这边默认是获取当前路径加相对路径作为其值的,想放在别的地方也可以手动更改或者把里面的当前路径wd替换掉

还有一个要注意的是数据集的划分,是split_dataset_by_xml函数进行划分的,我默认是90%用于训练,10%用于验证,请根据自己需求更改参数

# -*- coding: utf-8 -*-
# xml解析包
import random
import xml.etree.ElementTree as ET
import pickle
import os
import shutil
from os import listdir, getcwd
from os.path import join
from PIL import Image
import yaml


def convert_images_to_jpg(source_folder, destination_folder):
    # 检查目标文件夹是否存在,如果不存在则创建
    if not os.path.exists(destination_folder):
        os.makedirs(destination_folder)

    # 遍历源文件夹中的所有文件
    for file_name in os.listdir(source_folder):
        source_file = os.path.join(source_folder, file_name)

        # 检查文件是否为图像文件
        if os.path.isfile(source_file) and any(
                file_name.lower().endswith(extension) for extension in ['.jpg', '.jpeg', '.png', '.gif', '.bmp']):
            # 打开图像文件
            image = Image.open(source_file)

            # 将图像文件转换为 JPG 格式
            image = image.convert('RGB')

            # 构造目标文件路径
            destination_file = os.path.join(destination_folder,
                                            file_name.lower().replace('.png', '.jpg').replace('.jpeg', '.jpg').replace(
                                                '.gif', '.jpg').replace('.bmp', '.jpg'))

            # 保存图像文件为 JPG 格式
            image.save(destination_file, 'JPEG')

    print("Image conversion completed.")


def split_dataset_by_xml(xml_dir='data/Annotations', output_dir='data/ImageSets', train_percent=0.9, trainval_percent=1):
    """
    根据xml文件划分符合yolo格式的txt,输入voc格式数据集的Annotations文件夹路径,以及要存放的txt路径,还有训练验证比例,剩下的作为测试
    Args:
        xml_dir:
        output_dir:
        train_percent:
        trainval_percent:

    Returns:

    """
    xml_files = os.listdir(xml_dir)

    num = len(xml_files)
    tv = int(num * trainval_percent)
    tr = int(tv * train_percent)

    trainval = random.sample(xml_files, tv)
    train = random.sample(trainval, tr)

    with open(os.path.join(output_dir, 'trainval.txt'), 'w') as ftrainval, \
            open(os.path.join(output_dir, 'train.txt'), 'w') as ftrain, \
            open(os.path.join(output_dir, 'val.txt'), 'w') as fval, \
            open(os.path.join(output_dir, 'test.txt'), 'w') as ftest:

        for xml_file in xml_files:
            name = xml_file[:-4] + '\n'
            if xml_file in trainval:
                ftrainval.write(name)
                if xml_file in train:
                    ftrain.write(name)
                else:
                    fval.write(name)
            else:
                ftest.write(name)


# 进行归一化操作
def convert(size, box):  # size:(原图w,原图h) , box:(xmin,xmax,ymin,ymax)
    dw = 1. / size[0]  # 1/w
    dh = 1. / size[1]  # 1/h
    x = (box[0] + box[1]) / 2.0  # 物体在图中的中心点x坐标
    y = (box[2] + box[3]) / 2.0  # 物体在图中的中心点y坐标
    w = box[1] - box[0]  # 物体实际像素宽度
    h = box[3] - box[2]  # 物体实际像素高度
    x = x * dw  # 物体中心点x的坐标比(相当于 x/原图w)
    w = w * dw  # 物体宽度的宽度比(相当于 w/原图w)
    y = y * dh  # 物体中心点y的坐标比(相当于 y/原图h)
    h = h * dh  # 物体宽度的宽度比(相当于 h/原图h)
    return (x, y, w, h)  # 返回 相对于原图的物体中心点的x坐标比,y坐标比,宽度比,高度比,取值范围[0-1]


# year ='2012', 对应图片的id(文件名)
def convert_annotation(root, image_id, classes):
    '''
    将对应文件名的xml文件转化为label文件,xml文件包含了对应的bunding框以及图片长款大小等信息,
    通过对其解析,然后进行归一化最终读到label文件中去,也就是说
    一张图片文件对应一个xml文件,然后通过解析和归一化,能够将对应的信息保存到唯一一个label文件中去
    labal文件中的格式:calss x y w h  同时,一张图片对应的类别有多个,所以对应的bunding的信息也有多个
    '''
    # 对应的通过year 找到相应的文件夹,并且打开相应image_id的xml文件,其对应bund文件
    in_file = open(f'{root}/Annotations/%s.xml' % (image_id), encoding='utf-8')
    # 准备在对应的image_id 中写入对应的label,分别为
    # <object-class> <x> <y> <width> <height>
    out_file = open(f'{root}/labels/%s.txt' % (image_id), 'w', encoding='utf-8')
    # 解析xml文件
    tree = ET.parse(in_file)
    # 获得对应的键值对
    root = tree.getroot()
    # 获得图片的尺寸大小
    size = root.find('size')
    # 如果xml内的标记为空,增加判断条件
    if size != None:
        # 获得宽
        w = int(size.find('width').text)
        # 获得高
        h = int(size.find('height').text)
        # 遍历目标obj
        for obj in root.iter('object'):
            # 获得difficult ??
            difficult = obj.find('difficult').text
            # 获得类别 =string 类型
            cls = obj.find('name').text
            # 如果类别不是对应在我们预定好的class文件中,或difficult==1则跳过
            if cls not in classes or int(difficult) == 1:
                continue
            # 通过类别名称找到id
            cls_id = classes.index(cls)
            # 找到bndbox 对象
            xmlbox = obj.find('bndbox')
            # 获取对应的bndbox的数组 = ['xmin','xmax','ymin','ymax']
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            print(image_id, cls, b)
            # 带入进行归一化操作
            # w = 宽, h = 高, b= bndbox的数组 = ['xmin','xmax','ymin','ymax']
            bb = convert((w, h), b)
            # bb 对应的是归一化后的(x,y,w,h)
            # 生成 calss x y w h 在label文件中
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')




if __name__ == '__main__':
    # ------------------------------------------ 参数 ------------------------------------------------------------------
    voc_path = r'E:\zby\bottle_project\objectdet\up_bottle_body\dataVOC'          # 原来存放voc数据集的目录 !!!
    cur_path = 'data/up_bottle_body_data'                                         # 当前数据集目录 !!!
    sets = ['train', 'test', 'val']                                               # 数据集的划分名字,一般不用改
    classes = ['ng']                                                              # 标签名字!!!

    # 返回当前工作目录
    wd = getcwd()
    print(wd)

    # 先把xml文件、图片文件复制过去,由于我原本的图片是bmp的,太大,所以转成jpg再复制过去
    # shutil.copytree 函数在复制文件夹时要求目标文件夹不存在
    if os.path.exists(cur_path + '/Annotations'):
        shutil.rmtree(cur_path + '/Annotations')
    shutil.copytree(voc_path + '/Annotations', cur_path + '/Annotations')
    convert_images_to_jpg(voc_path + '/JPEGImages', cur_path + '/images')
    suffix = 'jpg'
    # 创建labels,ImageSets文件夹
    if not os.path.exists(f'{cur_path}/labels/'):
        os.makedirs(f'{cur_path}/labels/')
    if not os.path.exists(f'{cur_path}/ImageSets/'):
        os.makedirs(f'{cur_path}/ImageSets/')

    # 划分数据集,事后重新划分也可单独执行这一函数
    split_dataset_by_xml(xml_dir=voc_path + '/Annotations',
                         output_dir=cur_path + '/ImageSets',
                         train_percent=0.9,
                         trainval_percent=1)

    # 根据划分的几个txt去各自进行坐标转化
    for image_set in sets:
        '''
        对所有的文件数据集进行遍历
        做了两个工作:
        1.将所有图片文件都遍历一遍,并且将其所有的全路径都写在对应的txt文件中去,方便定位
        2.同时对所有的图片文件进行解析和转化,将其对应的bundingbox 以及类别的信息全部解析写到label 文件中去
             最后再通过直接读取文件,就能找到对应的label 信息
        '''

        # 读取在ImageSets/Main 中的train、test..等文件的内容
        # 包含对应的文件名称
        image_ids = open(f'{cur_path}/ImageSets/%s.txt' % (image_set)).read().strip().split()
        # 打开对应的2012_train.txt 文件对其进行写入准备
        list_file = open(f'{cur_path}/%s.txt' % (image_set), 'w')
        # 将对应的文件_id以及全路径写进去并换行

        for image_id in image_ids:
            list_file.write(f'{cur_path}/images/%s.{suffix}\n' % (image_id))
            # 调用  year = 年份  image_id = 对应的文件名_id
            convert_annotation(cur_path, image_id, classes)
        # 关闭文件
        list_file.close()

    # 写入到yaml
    data = {
        'train': f'{wd}/{cur_path}/train.txt',
        'val': f'{wd}/{cur_path}/val.txt',
        'test': f'{wd}/{cur_path}/test.txt',
        'nc': len(classes),
        'names': classes
    }

    # 将内容写入YAML文件
    with open(f'{cur_path}/data_config.yaml', 'w') as file:
        yaml.dump(data, file, default_flow_style=False)


这是使用示例

from ultralytics import YOLO


if __name__ == '__main__':
    # 1 模型训练
    model = YOLO("yolov8s.pt", task='detect')  # n,s,m,l [detect、segment、classification]

    model.train(
        name='down_bottle_body',  # 用于保存训练文件夹名,默认exp,依次累加
        data="data/down_bottle_body_data/data_config.yaml",
        imgsz=480,
        epochs=200,
        batch=4,
        pretrained=True,
        optimizer='SGD',  # [‘SGD’, ‘Adam’, ‘AdamW’, ‘RMSProp’]
        lr0=0.01,  # 初始学习率(SGD=1E-2, Adam=1E-3)
        lrf=0.01,  # 最终学习率(lr0 * lrf)
        exist_ok=True,  # 是否覆盖现有保存文件夹,默认Flase
        save=True,  # 是否需要保存训练的模型和预测结果
    )
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VOC格式数据集转适用YOLOv8格式 的相关文章

  • 如何把父母和孩子联系起来?

    有两个简单的类 一个只有parent属性 并且两者兼而有之parent and children属性 这意味着同时具备两者的人parent and children继承自唯一的parent 这是只有parent属性 我们就这样称呼它吧Chi
  • Flask-SocketIO redis 订阅

    我在用着https github com miguelgrinberg Flask SocketIO https github com miguelgrinberg Flask SocketIO实现 WebSocket 服务器 我需要从另一
  • 如何替换Python字符串中的正确字母

    任务是 您的任务是纠正数字化文本中的错误 您只需处理以下错误 S 被误解为 5 O 被误解为 0 I 被误解为 1 我的代码 def correct string for i in string if 5 in string string
  • DynamodB:如何更新排序键?

    该表有两个键 filename 分区键 和eventTime 排序键 我要更新eventTime对于某些filename Tried put item and update item 发送相同的filename与新的eventTime但这些
  • 使用管理员权限打开cmd(Windows 10)

    我有自己的 python 脚本来管理我的计算机上的 IP 地址 它主要在命令行 Windows 10 中执行netsh命令 您必须具有管理员权限 这是我自己的计算机 我是管理员 运行脚本时我已经使用管理员类型的用户 Adrian 登录 我无
  • Python:json_normalize pandas 系列给出 TypeError

    我在 pandas 系列中有数万行像这样的 json 片段df json IDs lotId 1 Id 123456 date 2009 04 17 bidsCount 2 IDs lotId 2 Id 123456 date 2009 0
  • 将整数系列转换为交替(双元)二进制系列

    我不知道如何最好地表达这个问题 因为在这里谷歌搜索和搜索总是让我找到更复杂的东西 我很确定这是基本的东西 但对于我的生活来说 我找不到一个好的方法来做到这一点下列 给定一个整数序列 比如说 for x in range 0 36 我想将这些
  • Python3将模块从文件夹导入到另一个文件夹

    我的结构字典是 mainFolder folder1 init py file1 py file2 py folder2 init py file3 py file4 py setup py init py 我需要将 file4 py 从f
  • Python speedtest.net,或等效的[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 是否有一个 Python 库可以实现 SpeedTest net 测试或等效的互联网连接速度测试 GitHub上有一个项目叫速度检查 https gi
  • 如何找到多个 pandas 数据框中一对列与任意顺序对的交集?

    我有多个 pandas 数据框 为了简单起见 假设我有三个 gt gt df1 col1 col2 id1 A B id2 C D id3 B A id4 E F gt gt df2 col1 col2 id1 B A id2 D C id
  • 使用 scikit 时 scipy.sparse 矩阵的缩放问题

    在使用 scikit learn 解决机器学习问题时 我需要在使用 SVM 进行训练之前对 scipy sparse 矩阵进行缩放 但在文档 http scikit learn org stable modules preprocessin
  • 在 Python 中从 Excel 复制 YEARFRAC() 函数

    因此 我使用 python 来自动执行一些必须在 Excel 中执行的重复任务 我需要做的计算之一需要使用yearfrac 这在Python中被复制了吗 I found this https lists oasis open org arc
  • Pandas 字典键到列[重复]

    这个问题在这里已经有答案了 我有一个像这样的数据框 index column1 e1 u c680 5 u c681 1 u c682 2 u c57 e2 u c680 6 u c681 2 u c682 1 u c57 e3 u c68
  • 使用 python 脚本更改 shell 中的工作目录

    我想实现一个用户态命令 它将采用其参数之一 路径 并将目录更改为该目录 程序完成后 我希望 shell 位于该目录中 所以我想实施cd命令 但需要外部程序 可以在 python 脚本中完成还是我必须编写 bash 包装器 Example t
  • Flymake的临时文件可以在系统临时目录下创建吗?

    我目前正在使用以下代码在 emacs 中连接 Flymake 和 Pyflakes defun flymake create temp in system tempdir filename prefix make temp file or
  • Eclipse/PyDev 中未使用导入警告,尽管已使用

    我正在我的文件中导入一个绘图包 如下所示 import matplotlib pyplot as plt 稍后我会在我的代码中成功使用此导入 fig plt figure figsize 16 10 然而 Eclipse 告诉我 未使用的导
  • 哪种方式最适合Python工厂注册?

    这是一个关于这些方法中哪一种被认为是最有效的问题 Pythonic 我不是在寻找个人意见 而是在寻找惯用的观点 我的背景不是Python 所以这会对我有帮助 我正在开发一个可扩展的 Python 3 项目 这个想法类似于工厂模式 只不过它是
  • 如何将 URL 添加到 Telegram Bot 的 InlineKeyboardButton

    我想制作一个按钮 可以从 Telegram 聊天中在浏览器中打开 URL 外部超链接 目前 我只开发了可点击的操作按钮 update message reply text Subscribe to us on Facebook and Te
  • 在Python中使用pil读取tif图像时出现值错误?

    我必须读取尺寸的tif图像2200 2200并输入 uint16 我将 PIL 库与 anaconda python 一起使用 如下所示 from PIL import Image img Image open test tif img i
  • 从 Django 运行 shell 命令

    我正在 Django 中开发一个网页 使用 apache 服务器 需要调用 shell 命令来启用 禁用一些守护进程 我尝试这样做 os system service httpd restart 1 gt HOME out 2 gt HOM

随机推荐

  • 人工智能方向毕业设计_人工智能时代,理工科专业的毕业设计都被安排了

    我是16年上半年从软件开发转到算法工程师的 这些年AI 我亲眼见证了从 黑科技 跌入 俗学 的过程 早些年 在模式识别领域 例如人脸识别 语音识别等 大家都发力在数学算法 基于机器学习 的时候 虽然努力多年 但是因为技术缺陷精度却一直上不去
  • Oracle数据库的闪回技术

    当 Oracle 数据库发生逻辑损坏时 可以使用闪回技术简单快捷地进行数据库的恢复 闪回数据库使用闪回日志执行闪回 闪回删除使用回收站 其它所有技术都使用还原数据 并不 是所有闪回功能都会修改数据库 有些功能只是一些用来查询数据以往版本的方
  • 左程云 Java 笔记--链表

    文章目录 1哈希表 2有序表 3链表 3 1打印两个有序链表的公共部分 3 2判断一个链表是否为回文结构 3 3将单向链表按某值划分成左边小 中间相等 右边大的形式 3 4复制含有随机指针节点的链表 3 4 1使用哈希表 3 4 2方法二
  • Tachyou alluxio初识

    Tachyou是基于内存的分布式文件系统 如果把hdfs上层再弄一层Tachyou去存储数据 那么速度将会更快 Tachyou现在改名为Tachyou alluxio
  • 【数字电源】数字电源核心理论-"伏妙平衡"与"安秒平衡"

    1 聊一聊 今天跟大家分享的是迈克在本公众号的第三首歌曲 在bug菌心里迈克的歌早就不仅仅只是一首歌曲了 更是件值得一直品味的艺术品 本文开启数字电源的第一篇原创文章 数字电源核心理论 伏秒和安秒平衡 2 主题前言 在公众号简介中bug菌跟
  • 为什么要进行埋点?如何理解数据埋点

    我们在做网站运营 APP运营的时候 要关注事件级分析 比如按钮点击事件 漏斗转化率 只看PV UV是无法得到行动指导的 UV多了一点少了一点 无法能反映出来 我们流量的多与少 与用户真正的完成转化还差很多 举例 我们想看加入购物车和提交订单
  • Qt中 gui 模块和 widgets 模块的区别

    1 gui 模块提供了基本的图形系统抽象层 包括QPaintDevice QPainter等类 这些类构成了Qt的绘图基础 2 widgets 模块在 gui 模块的基础上 提供了完整的桌面级用户界面控件 如按钮 列表 滑块等 这些控件继承
  • VS最新安装教程

    1 访问Visual Studio官方网站 下载 Visual Studio Tools 免费安装 Windows Mac Linux microsoft com https visualstudio microsoft com zh ha
  • .NET 发展历程

    早期 NET NET Framework 1 0 4 8 1 时间 2002 02 2019 04 2002 年 2 月 23 日最早的 NET Framework 1 0 发布 终止于 2022 年 8 月 9 日发布的 NET Fram
  • ie11对象不支持此属性和方法 ie11的缓存问题

    更改eclipse的js代码 在ie11上调试 发现调用新更改的方法 在ie11的console输出里 一直提示 对象不支持此属性和方法 点击右上角设置图标 然后点击Internet选项 在常规选项卡里的 浏览器历史记录 点击设置 在弹出的
  • 【分布式系统搭建】Zookeeper完全分布式集群的搭建

    Zookeeper完全分布式集群的搭建 一 集群模式 1 单机模式 用于测试环境 在zoo cfg中只配置一个server id就是单机模式了 2 伪分布式 用于测试环境 在zoo cfg中配置多个server id 其中ip都是当前机器
  • AntV-f2开发文档

    安装 浏览器引入 复制代码 npm 安装 安装 npm install antv f2 save复制代码 引入 const F2 require antv f2 复制代码 上手 步骤 创建 Chart 图表对象 指定图表 ID 指定图表的宽
  • Qt开发经验(转载)

    0 前言说明 本文转载于https qtchina blog csdn net type blog feiyangqingyun的博客 感谢大佬的经验分析 1 开发经验 01 001 010 当编译发现大量错误的时候 从第一个看起 一个一个
  • C++ 常量引用

    黑马程序员C P94 常量引用 感觉这部分有很多内容 但目前我的理解就是在形参前加上const 防止误操作 先占个坑后面再补充
  • 第二章节:期货市场组织结构与投资者

    各组织的性质 职能 形式 组织架构 权利 义务等 期货结算制度 期货投资者种类等 第一节 期货交易所 本节考点 一 期货交易所的性质 宗旨与职能 重点掌握 二 期货交易所的组织结构 重点掌握 三 我国境内期货交易所 重点掌握 一 期货交易所
  • Java中的static关键字解析

    一 static关键字的用途 在 Java编程思想 P86页有这样一段话 static方法就是没有this的方法 在static方法内部不能调用非静态方法 反过来是可以的 而且可以在没有创建任何对象的前提下 仅仅通过类本身来调用static
  • HDU-7304 2023“钉耙编程”杭电多校赛(3)Out of Control

    2023 钉耙编程 中国大学生算法设计超级联赛 3 Out of Control 题目大意 有 n n n个数 x 1 x
  • 区块链三加一:深度论区块链的联盟链意义与作用

    随着区块链技术的发展 越来越受个人及企业的关注 而和区块链联系最为紧密的 恐怕就是金融行业了 然而虽然区块链大受热捧 但毕竟区块链是属于公有区块链 公有区块链有着其不可编辑 不可篡改的特点 这就使得公有链并不适合企业使用了 毕竟如果某金融企
  • UE4右键菜单(上篇ContentBrowser的补充)

    在上篇中我们讲到拓展我们的ContentBrowser的文件夹右键菜单 看回上篇代码可以发现其实真正起实现拓展 看到效果 的代码就只有一行 在代码中我们可以看到 MenuBuilder 这个东西是可以为我们创建一个菜单的 今天我们继续来改造
  • VOC格式数据集转适用YOLOv8格式

    直接设置VOC数据集的文件夹目录 生成的v8格式数据集存放目录以及标签的名字就行了 直接执行后就会是下面这图这样重新创建一个文件夹存放符合yolov8格式的数据集 yolov8直接加载那个yaml文件就行 我下边只有一类 注意最后的yaml