VOC格式转YOLO格式,xml文件转txt文件简单通用代码
目录
前言
思路介绍
代码
完整代码
拓展代码
前言
很多人在进行目标检测训练时习惯将得到的数据标注为XML文件的VOC格式,或者在网上获取的数据集被标注为XML文件,但是不同的标注工具进行的标注会产生不同的标注xml文件,这里我写了一种通用的针对含有最基本图片和标注坐标信息的xml进行转换,在这里简单介绍并分享出来
思路介绍
xml文件中最基本需要含有的信息为size,object下的name和bndbox,具体示例如下图(如果xml文件中没有size也就是图片的宽和高则需要单独对每个图片进行读取,感兴趣可以私聊,这里不展开介绍)

可以看到这几个标签下包含了标注的全部信息,接着进行转换
代码
核心代码为,提取所需要的信息
size = root.find('size')
width = int(size.find('width').text)
height = int(size.find('height').text)
# 存储name和对应的归一化坐标
objects = []
# 遍历XML中的object标签
for obj in root.findall('object'):name = obj.find('name').textif name in category_to_index:category_index = category_to_index[name]else:continue # 如果name不在指定类别中,跳过该objectbndbox = obj.find('bndbox')xmin = int(bndbox.find('xmin').text)ymin = int(bndbox.find('ymin').text)xmax = int(bndbox.find('xmax').text)ymax = int(bndbox.find('ymax').text)
归一化代码如下,这也是YOLO格式的通用归一化代码
x_center = (xmin + xmax) / 2.0
y_center = (ymin + ymax) / 2.0
w = xmax - xmin
h = ymax - yminx = x_center / width
y = y_center / height
w = w / width
h = h / height
这里最下边四行代码即为txt中每一行后四位数字
完整代码
完整代码如下
import os
import xml.etree.ElementTree as ET# 定义类别顺序
categories = ['eggplant']
category_to_index = {category: index for index, category in enumerate(categories)}# 定义输入文件夹和输出文件夹
input_folder = r'D:\Annotations' # 替换为实际的XML文件夹路径
output_folder = r'D:\labels' # 替换为实际的输出TXT文件夹路径# 确保输出文件夹存在
os.makedirs(output_folder, exist_ok=True)# 遍历输入文件夹中的所有XML文件
for filename in os.listdir(input_folder):if filename.endswith('.xml'):xml_path = os.path.join(input_folder, filename)# 解析XML文件tree = ET.parse(xml_path)root = tree.getroot()# 提取图像的尺寸size = root.find('size')width = int(size.find('width').text)height = int(size.find('height').text)# 存储name和对应的归一化坐标objects = []# 遍历XML中的object标签for obj in root.findall('object'):name = obj.find('name').textif name in category_to_index:category_index = category_to_index[name]else:continue # 如果name不在指定类别中,跳过该objectbndbox = obj.find('bndbox')xmin = int(bndbox.find('xmin').text)ymin = int(bndbox.find('ymin').text)xmax = int(bndbox.find('xmax').text)ymax = int(bndbox.find('ymax').text)# 转换为中心点坐标和宽高x_center = (xmin + xmax) / 2.0y_center = (ymin + ymax) / 2.0w = xmax - xminh = ymax - ymin# 归一化x = x_center / widthy = y_center / heightw = w / widthh = h / heightobjects.append(f"{category_index} {x} {y} {w} {h}")# 输出结果到对应的TXT文件txt_filename = os.path.splitext(filename)[0] + '.txt'txt_path = os.path.join(output_folder, txt_filename)with open(txt_path, 'w') as f:for obj in objects:f.write(obj + '\n')
拓展代码
这个代码类别还需要自己获取并填写,这里给出一种更简单的方法,可以省去填写标签列表的环节并且自动类别编号,完整代码如下
import os
import xml.etree.ElementTree as ET
names_set = set()input_folder = r'D:\Annotations' # 替换为实际的XML文件夹路径
output_folder = r'D:\labels' # 替换为实际的输出TXT文件夹路径for filename in os.listdir(input_folder):if filename.endswith('.xml'):tree = ET.parse(os.path.join(input_folder, filename))root = tree.getroot()for obj in root.findall('object'):name = obj.find('name').textnames_set.add(name)
# 输出所有的name
categories = []
for name in names_set:categories.append(name)
print(categories)category_to_index = {category: index for index, category in enumerate(categories)}
os.makedirs(output_folder, exist_ok=True)# 遍历输入文件夹中的所有XML文件
for filename in os.listdir(input_folder):if filename.endswith('.xml'):xml_path = os.path.join(input_folder, filename)# 解析XML文件tree = ET.parse(xml_path)root = tree.getroot()# 提取图像的尺寸size = root.find('size')width = int(size.find('width').text)height = int(size.find('height').text)# 存储name和对应的归一化坐标objects = []# 遍历XML中的object标签for obj in root.findall('object'):name = obj.find('name').textif name in category_to_index:category_index = category_to_index[name]else:continue # 如果name不在指定类别中,跳过该objectbndbox = obj.find('bndbox')xmin = int(bndbox.find('xmin').text)ymin = int(bndbox.find('ymin').text)xmax = int(bndbox.find('xmax').text)ymax = int(bndbox.find('ymax').text)# 转换为中心点坐标和宽高x_center = (xmin + xmax) / 2.0y_center = (ymin + ymax) / 2.0w = xmax - xminh = ymax - ymin# 归一化x = x_center / widthy = y_center / heightw = w / widthh = h / heightobjects.append(f"{category_index} {x} {y} {w} {h}")# 输出结果到对应的TXT文件txt_filename = os.path.splitext(filename)[0] + '.txt'txt_path = os.path.join(output_folder, txt_filename)with open(txt_path, 'w') as f:for obj in objects:f.write(obj + '\n')
相关文章:
VOC格式转YOLO格式,xml文件转txt文件简单通用代码
目录 前言 思路介绍 代码 完整代码 拓展代码 前言 很多人在进行目标检测训练时习惯将得到的数据标注为XML文件的VOC格式,或者在网上获取的数据集被标注为XML文件,但是不同的标注工具进行的标注会产生不同的标注xml文件,这里我写了一种通用…...
STL迭代器的基础应用
STL迭代器的应用 迭代器的定义方法: 类型作用定义方式正向迭代器正序遍历STL容器容器类名::iterator 迭代器名常量正向迭代器以只读方式正序遍历STL容器容器类名::const_iterator 迭代器名反向迭代器逆序遍历STL容器容器类名::reverse_iterator 迭代器名常量反向迭…...
【SQL】数据操作语言(DML) - 删除数据:精细管理数据的利刃
目录 前言 DELETE语句的基础使用 删除指定记录 清空表与删除表数据的区别 注意 前言 在数据库管理的日常工作中,数据的删除是一项需要格外小心的操作,因为一旦数据被删除,往往难以恢复。数据操作语言(DML)中的DELETE语句&am…...
异步复制,主库宕机后,数据可能丢失吗?
异步复制是数据库复制的一种方式,它允许主数据库(主库)在不等待从数据库(从库)完成数据同步的情况下继续处理事务。这种方式可以提高数据库的性能,因为主库不需要等待数据复制到从库。然而,异步…...
如何在Spring Boot中优雅处理异常
如何在Spring Boot中优雅处理异常 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨在Spring Boot应用程序中如何优雅地处理异常,以…...
1.3.数据的表示
定点数 原码 最高位是符号位,0表示正号,1表示负号,其余的n-1位表示数值的绝对值。 数值0的原码表示有两种形式: [0]原0 0000000 [-0]原1 0000000 例:1010 最高位为1表示这是一个负数, 其它三位 010…...
【进阶篇-Day4:使用JAVA编写石头迷阵游戏】
目录 1、绘制界面2、打乱石头方块3、移动业务4、游戏判定胜利5、统计步数6、重新游戏7、完整代码: 1、绘制界面 上述思路是:使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。 代码如下: package com.itheima.s…...
探索 LLamaWorker:基于LLamaSharp的.NET本地大模型服务
LLamaWorker 是一个基于 LLamaSharp 项目开发的 HTTP API 服务器。它提供与 OpenAI 兼容的 API,使得开发者可以轻松地将大型语言模型(LLM)集成到自己的应用程序中。 1. 背景 在人工智能领域,大型语言模型(LLM…...
Qt开发 | Qt控件 | QTabWidget基本用法 | QListWidget应用详解 | QScrollArea应用详解
文章目录 一、QTabWidget基本用法二、QListWidget应用详解1.列表模式1.1 基本操作1.2 添加自定义item1.3 如何添加右键菜单1.4 QListWidget如何删除item 2.图标模式 三、QScrollArea应用详解 一、QTabWidget基本用法 QTabWidget 是 Qt 框架中的一个类,它提供了一个选…...
2023年 AI APT可持续攻击的调查研究报告
总览 随着网络技术的不断发展,网络安全威胁也日益严峻。高级持续性威胁(APT)攻击以其目标明确、手段多样、隐蔽性强等特点,成为网络安全领域的重要挑战。本文分析2023年当前 APT 攻击的主要特点、活跃组织、攻击趋势以及漏洞利用…...
Leetcode 102.目标和
给定一个正整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 ‘’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 : 例如,nums [2, 1] ,可以在 2 之前添加 ‘’ ,在 1 之前添加 ‘-’ &…...
LLM AI工具和Delphi名称的起源
LLM AI工具和Delphi名称的起源 使用ChatGPT,直接或通过微软工具,以及其他基于llm的引擎。我很欣赏他们提供好的总结和比较的能力,并且还编写了一些样板代码。与此同时,当你问一些重要的问题时,你会得到一些令人惊讶的好…...
打破数据分析壁垒:SPSS复习必备(十一)
一、方差分析 方差分析的应用条件如下: (1)独立,各组数据相互独立,互不相关; (2)正态:即各组数据符合正态分布; (3)方差齐性&…...
【十六】【QT开发应用】Menu菜单,contextMenuEvent,setContextMenuPolicy,addAction
在 Qt 框架中,QMenu 类用于创建和管理菜单。菜单是用户界面的一部分,可以包含多个选项或动作,用户可以选择这些选项来执行特定的功能。菜单通常显示在菜单栏、上下文菜单(右键菜单)或工具栏中。 基本用法 创建菜单对象…...
华为DCN技术:M-LAG
M-LAG(Multichassis Link Aggregation Group)即跨设备链路聚合组,是一种实现跨设备链路聚合的机制。M-LAG主要应用于普通以太网络、VXLAN和IP网络的双归接入,可以起到负载分担或备份保护的作用。相较于另一种常见的可靠性接入技术…...
k8s持久化之emptyDir使用
目录 概述实践代码 概述 理解emptyDir使用,是后续k8s持久化进阶,高阶使用的基础。 实践 代码 详细说明在代码中 # 缓存数据,可以让多个容器共享数据 # 删除 Pod 时,emptyDir 数据同步消失 # 定义 initContainer -> 下载数据…...
Java露营基地预约小程序预约下单系统源码
轻松开启户外探险之旅 🌟 露营热潮来袭,你准备好了吗? 随着人们对户外生活的热爱日益增加,露营已成为许多人周末和假期的首选活动。但你是否曾因找不到合适的露营基地而烦恼?或是因为繁琐的预约流程而错失心仪的营地…...
七天速通javaSE:第四天 java方法
文章目录 前言一、什么是方法?二、方法的定义与调用1. 方法的定义2. 方法的调用3. 练习:定义比大小方法并调用 三、方法的重载四、递归五、可变参数拓展:命令行传递参数 前言 本章将学习java方法。 一、什么是方法? java方法是用…...
jupyter notebook的markdown语法不起作用
在这个界面编辑,发现markdown你编辑的是什么就是什么,不起作用,然而点一下: 右上角“Notebook转发”,就会单独跳出一个jupyter notebook的界面,此时就会奏效:...
Redis 学习笔记(2)
目录 1 Redis的持久化1.1 RDB持久化方案1.2 AOF持久化方案 2 Redis架构2.1 主从复制架构2.2 哨兵集群设计2.3 哨兵集群设计 3 Redis事务机制4 Redis过期策略与内存淘汰机制4.1 过期策略4.2 内存淘汰机制 5 Redis高频面试题4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩 1 Redis的持久化…...
Duix.Avatar本地部署实战:从零搭建AI数字人视频生成平台
Duix.Avatar本地部署实战:从零搭建AI数字人视频生成平台 【免费下载链接】Duix-Avatar 项目地址: https://gitcode.com/GitHub_Trending/he/Duix-Avatar 你是否希望在自己的电脑上拥有一个专属的AI数字人助手?Duix.Avatar作为硅基智能推出的开源…...
Vue3+Vant4移动端架构设计:现代化移动应用工程实践
Vue3Vant4移动端架构设计:现代化移动应用工程实践 【免费下载链接】vue3-vant4-mobile 👋👋👋 基于Vue3.2、vite3、vant4、pinia2、Typescript、windicss 等主流技术开发,集成 Dark Mode(暗黑)模式和系统主题色&#x…...
UniAD高版本环境实战:CUDA11.6+PyTorch1.12避坑全记录(附完整依赖清单)
UniAD高版本环境实战:CUDA11.6PyTorch1.12避坑全记录(附完整依赖清单) 当计算机视觉工程师尝试复现前沿论文时,环境配置往往成为第一道门槛。UniAD作为自动驾驶领域的统一大模型,其官方文档推荐的环境配置(…...
手把手教你用CH32V208开发板实现蓝牙BLE5.3通信(附完整工程源码)
基于CH32V208开发板的蓝牙BLE5.3实战开发指南 在物联网设备爆发式增长的今天,低功耗蓝牙(BLE)技术因其低功耗、低成本的优势,成为短距离无线通信的首选方案之一。作为一款集成了BLE5.3模块的RISC-V微控制器,CH32V208为…...
Wan2.2-I2V-A14B绿色AI实践:显存优化降低35%功耗的碳足迹测算
Wan2.2-I2V-A14B绿色AI实践:显存优化降低35%功耗的碳足迹测算 1. 引言:绿色AI的迫切需求 在AI技术快速发展的今天,大模型训练和推理带来的能源消耗问题日益突出。Wan2.2-I2V-A14B作为一款先进的文生视频模型,通过显存优化技术实…...
CanCanCan控制器助手终极指南:load_and_authorize_resource深度解析与最佳实践
CanCanCan控制器助手终极指南:load_and_authorize_resource深度解析与最佳实践 【免费下载链接】cancancan The authorization Gem for Ruby on Rails. 项目地址: https://gitcode.com/gh_mirrors/ca/cancancan CanCanCan是Ruby on Rails最强大的授权gem&…...
TwinCAT3进阶指南:台达A2伺服扭矩读取与回零实战
1. TwinCAT3与台达A2伺服的基础配置 在开始扭矩读取和回零操作之前,我们需要先完成TwinCAT3与台达A2伺服的基础配置。这部分工作看似简单,但却是后续所有高级功能的基础。我遇到过不少开发者因为基础配置没做好,导致后面各种奇怪的问题。 首先…...
STM32CubeMX 6.4.0 + STM32F407ZGT6 实战:基于YT8512C PHY的lwIP以太网配置与调试
1. 环境准备与硬件连接 最近在做一个物联网项目时,发现正点原子探索者开发板的PHY芯片从常见的DP83848换成了YT8512C,导致之前能跑通的以太网代码突然失效了。经过一番折腾,终于用STM32CubeMX 6.4.0完成了配置。先说说硬件准备: 开…...
告别环境混乱:Python3.9镜像实战教程,独立环境管理如此简单
告别环境混乱:Python3.9镜像实战教程,独立环境管理如此简单 1. 为什么需要Python3.9镜像 在Python开发中,最令人头疼的问题莫过于环境冲突。想象一下这样的场景:你正在开发一个需要TensorFlow 2.4的项目,但同时还要维…...
别再手动传文件了!用MinIO Java SDK的预签名URL功能,5分钟搞定安全文件分享
别再手动传文件了!用MinIO Java SDK的预签名URL功能,5分钟搞定安全文件分享 上周团队新来的架构师老张给我看了一个令人后怕的日志:某个内部系统的文件下载接口在24小时内被调用了17万次,而实际业务需求只有不到200次。调查发现是…...
