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').text
	if name in category_to_index:
		category_index = category_to_index[name]
	else:
		continue  # 如果name不在指定类别中,跳过该object
	bndbox = 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 - ymin

x = 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').text
			if name in category_to_index:
				category_index = category_to_index[name]
			else:
				continue  # 如果name不在指定类别中,跳过该object

			bndbox = 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.0
			y_center = (ymin + ymax) / 2.0
			w = xmax - xmin
			h = ymax - ymin

			# 归一化
			x = x_center / width
			y = y_center / height
			w = w / width
			h = h / height

			objects.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').text
			names_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').text
			if name in category_to_index:
				category_index = category_to_index[name]
			else:
				continue  # 如果name不在指定类别中,跳过该object
			bndbox = 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.0
			y_center = (ymin + ymax) / 2.0
			w = xmax - xmin
			h = ymax - ymin
			# 归一化
			x = x_center / width
			y = y_center / height
			w = w / width
			h = h / height
			objects.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')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/747384.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

信息学奥赛初赛天天练-36-CSP-J2021阅读程序-ASCII、运算符优先级、二进制补码存储、模拟算法应用

PDF文档公众号回复关键字:20240626 2021 CSP-J 阅读程序2 1 阅读程序(判断题1.5分 选择题3分 共计40分 ) #include<stdio.h> #include<string.h>char base[64]; char table[256]; char str[256]; char ans[256];void init() {for(int i0;i<26;i) base[i]Ai;fo…

49、基于归一化感知器的输入向量分类(matlab)

1、基于归一化感知器的输入向量分类的原理及流程 归一化感知器是一种分类算法&#xff0c;其原理基于感知器算法&#xff0c;但是在输入向量上进行了归一化处理&#xff0c;以提高算法的性能和稳定性。 流程如下&#xff1a; 输入向量归一化&#xff1a;对每个输入向量进行归…

图解HTTP笔记整理(前六章)

图解HTTP 第一章 web使用HTTP &#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;协议作文规范&#xff0c;完成从客户端到服务器端等一系列运作流程。 协议&#xff1a;计算机与网络设备要相互通信&#xff0c;双方就必须基于相同的方法。比如…

JetBrains Rider 2024安装教程

一、下载Rider 1、进入官网&#xff0c;点击“下载” 2、下载完毕 二、安装Rider 1、双击下载的exe文件 2、点击“下一步” 3、可以点击“浏览”选择安装路径&#xff0c;之后点击“下一步” 4、选中图中四项&#xff0c;点击“下一步” 5、选中图中四项&#xff0c;点击“下…

Superset二次开发之导入导出功能源码解读

可导出的类型 支持 看板(Dashboard)、图表(Charts)、数据集(Datasets)、SQL(saved_query)、数据库(Database connection) 单次或批量的导出,和单次导入操作 看板(Dashboard) 图表(Charts) 数据集(Datasets) SQL (saved_query) 数据库(database connections)…

4.任务调度

1.基本知识 2.任务的状态 FreeRTOS中任务共存在4种状态&#xff1a;Running 运行态 当任务处于实际运行状态称之为运行态&#xff0c;即CPU的使用权被这个任务占用&#xff08;同一时间仅一个任务处于运行态&#xff09;。Ready 就绪态 处于就绪态的任务是指那些能够运行&…

声场合成新方法:基于声波传播的框架

声场合成是指在房间内的麦克风阵列上&#xff0c;根据来自房间内其他位置的声源信号&#xff0c;合成每个麦克风的音频信号。它是评估语音/音频通信设备性能指标的关键任务&#xff0c;因为它是一种成本效益高的方法&#xff0c;用于数据生成以替代真实的数据收集&#xff0c;后…

Java知识点整理 13 — Hutool工具库

在开发时经常需要编写很多与业务无关的代码&#xff0c;比如获取指定日期对象、获取本机 IP 地址、数据加密等。通常我们会将这些代码独立出来&#xff0c;放到 utils 目录下&#xff0c;作为工具类供其它代码调用。 但如果遇到一个从未接触过的领域知识&#xff0c;开发一个新…

Spring Boot如何实现跨域资源共享(CORS)?

&#x1f345; 作者简介&#xff1a;哪吒&#xff0c;CSDN2021博客之星亚军&#x1f3c6;、新星计划导师✌、博客专家&#x1f4aa; &#x1f345; 哪吒多年工作总结&#xff1a;Java学习路线总结&#xff0c;搬砖工逆袭Java架构师 &#x1f345; 技术交流&#xff1a;定期更新…

01_02_Mybatis的配置文件与基于XML的使用

1、引入日志 在这里我们引入SLF4J的日志门面&#xff0c;使用logback的具体日志实现&#xff1b;引入相关依赖&#xff1a; <!--日志的依赖--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version&g…

Spring Boot整合RocketMQ实现延迟消息消费

导包 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.0.3</version></dependency>添加配置信息 application配置文件 # rocketMq地址 rocketmq.name…

数据采集与预处理复习资料

目录 第一章 简答 1.简述Hadoop各个组件及其功能 2.Hadoop在大数据技术体系中的地位和作用&#xff08;来自文心一言&#xff09; 3.Hadoop 启动命令&#xff0c;停止命令 4.pig 加载HDFS 数据 5.数据采集的方法&#xff08;来自ppt&#xff09; 6.数据分析过程&#xf…

GO sync包——读写锁

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

引导过程与服务器控制

一、引导过程 1.开机自检 服务器主机开机以后&#xff0c;将根据主板 BIOS 中的设置对 CPU&#xff08;Central Processing Unit&#xff0c; 中央处理器&#xff09;、内存、显卡、键盘等设备进行初步检测&#xff0c;检测成功后根据预设的启动顺序移 交系统控制权&#xff0c…

ChatGPT在程序开发中的应用:提升生产力的秘密武器

在当今飞速发展的科技时代&#xff0c;程序开发已经成为许多企业和个人必不可少的技能。然而&#xff0c;编写代码并非总是顺风顺水&#xff0c;面对复杂的算法、繁琐的调试、持续不断的需求变更&#xff0c;程序员们常常感到压力山大。在这种情况下&#xff0c;ChatGPT应运而生…

C#学习系列之DataGrid无故添加空行

C#学习系列之DataGrid无故添加空行 前言解决前解决后总结 前言 采用别人的轮子&#xff0c;想在基础上改界面&#xff0c;但是copy后&#xff0c;无论怎么样都会有空行&#xff0c;实在是绑定数据的输入没有任何赋值。 解决前 绑定的数据中输入三组数据&#xff0c;但是没有第…

【osgEarth】Ubuntu 22.04 源码编译osgEarth 3.5

下载源代码 git clone --depth1 https://dgithub.xyz/gwaldron/osgearth -b osgearth-3.5 下载子模块 git submodule update --init 如果下载不过来&#xff0c;就手动修改下.git/config文件&#xff0c;将子模块的地址替换成加速地址 (base) yeqiangyeqiang-Default-string…

openlayers性能优化——开启图层预加载、减少空白等待时间

使用切片图层时、地图拖拽会有空白图片&#xff0c;为了减少空白等待时间&#xff0c;我们可以开始图层预加载。 const map_top new Map({layers: [new TileLayer({preload:Infinity, //预加载source: new StadiaMaps({layer: "outdoors",}),}),],target: "ma…

点云处理实战 PCL求解点云表面曲率

目录 一、什么是曲率 二、曲率计算过程 三、pcl 求解点云局部曲率 四、思考?为何曲率计算会使用协方差矩阵? 五、推荐阅读 一、什么是曲率 曲率是几何学中用来描述曲线或曲面形状变化的一个量。它反映了曲线或曲面的弯曲程度。在不同的上下文中,曲率的定义和计算方式有…

uniapp 微信小程序端使用百度地图API

1、登录百度地图开放平台 https://lbsyun.baidu.com/&#xff08;没有账号则先去创建一个百度账号&#xff09; 2、进入百度地图开放平台控制台&#xff08;导航栏“控制台”&#xff09;&#xff0c;点击“应用管理”-“我的应用” 3、选择“创建应用”&#xff0c;应用模块选…