完整程式码!

https://github.com/yu-ken0207/PascalVOCtoYolo

将Pascal VOC格式的标注转换为YOLO格式

要将Pascal VOC格式的标注转换为YOLO格式,您可以按照以下步骤进行:

1. 理解两种格式的区别

  • Pascal VOC格式:标注信息存储在XML文件中,包含对象的类别和边界框坐标。边界框以像素为单位,使用左上角和右下角坐标表示,即xmin、ymin、xmax、ymax。
  • YOLO格式:标注信息存储在文本文件中,每行代表一个对象,格式如下:

<class_id> <x_center> <y_center> <width> <height>

其中,x_center、y_center、width、height都是相对于图像宽度和高度的正规化的值,范围在0到1之间。

2. 转换步骤

对于每个标注对象,执行以下步骤:

获取图像尺寸(宽度和高度):

  • image_width
  • image_height

提取边界框坐标:

  • xmin
  • ymin
  • xmax
  • ymax

计算边界框的宽度和高度:

bbox_width = xmax - xmin
bbox_height = ymax - ymin

计算边界框中心点坐标:

x_center = xmin + (bbox_width / 2)
y_center = ymin + (bbox_height / 2)

正归化座标:

x_center_norm = x_center / image_width
y_center_norm = y_center / image_height
bbox_width_norm = bbox_width / image_width
bbox_height_norm = bbox_height / image_height

获取类别ID:

  • 将类别名称映射为整数ID(从0开始)。

3. 范例程式码

使用此资料集为例Monkey, Cat and Dog detectionhttps://www.kaggle.com/datasets/tarunbisht11/yolo-animal-detection-small/data

Pascal VOC 格式:

  • 将 Pascal VOC 格式的标注文件(XML)转换为 YOLO 格式的标注文件(TXT)

在使用yolo进行训练时需要使用以下格式:

1. 汇入所需的模组

import os
import xml.etree.ElementTree as ET

  • os:提供与作业系统互动的功能,例如档案和目录操作。
  • xml.etree.ElementTree:Python 内建的 XML 解析器,用来处理 XML 文件中的结构与数据。

2. 定义转换函数

def convert_bbox(size, box):
dw = 1. / size[0]
dh = 1. / size[1]
x = (box[0] + box[2]) / 2.0 - 1
y = (box[1] + box[3]) / 2.0 - 1
w = box[2] - box[0]
h = box[3] - box[1]
x = x * dw
w = w * dw
y = y * dh
h = h * dh
return (x, y, w, h)

  • convert_bbox(size, box):这个函数将 XML 标注的边界框转换为 YOLO 格式。
  • size:图像的宽度和高度。
  • box:包含 Pascal VOC 格式的边界框,四个数值分别是左上角和右下角的 (xmin, ymin, xmax, ymax)。
  • 公式计算:中心座标 (x, y) 和宽高 (w, h) 会根据 YOLO 的要求进行归一化(相对于图像尺寸)。

3. 设定资料夹路径

xml_folder = \'C:/Users/ken50/OneDrive/桌面/yolo-animal-detection-small/test\'
txt_folder = \'C:/Users/ken50/OneDrive/桌面/yolo-animal-detection-small/test\'

xml_folder:存放 Pascal VOC 格式标注文件的资料夹路径。txt_folder:存放转换为 YOLO 格式后的标注文件的资料夹路径。

4. 检查并建立 TXT 资料夹

if not os.path.exists(txt_folder):
os.makedirs(txt_folder)

检查 txt_folder 是否存在。如果不存在,则建立这个资料夹,确保转换后的 TXT 标注可以被储存。

5. 定义类别名称

classes = ["cat", "monkey", "dog"]

定义类别清单,这些类别名称必须与 YAML 文件中的类别名称一致,并且顺序也要保持一致。

6. 遍历 XML 文件

for file in os.listdir(xml_folder):
if file.endswith(".xml"):
tree = ET.parse(os.path.join(xml_folder, file))
root = tree.getroot()

os.listdir(xml_folder):列出 xml_folder 中所有的文件。if file.endswith(".xml"):只处理副档名为 .xml 的文件。ET.parse():解析 XML 文件并生成树状结构。root:XML 树的根节点,这里用来寻找图像的大小和标注的物件。

7. 读取图像尺寸

size = root.find(\'size\')
w = int(size.find(\'width\').text)
h = int(size.find(\'height\').text)

透过 XML 文件中的 标籤,取得图像的 width(宽度)和 height(高度),这些数值会用于转换边界框的尺寸。

8. 建立对应的 TXT 文件

txt_file = os.path.join(txt_folder, file.replace(\'.xml\', \'.txt\'))
with open(txt_file, \'w\') as out_file:

为每个 XML 文件创建一个相应的 TXT 文件,并将其命名为与原来的 XML 文件相同,但副档名为 .txt。使用 open() 函数以写入模式打开该文件。

9. 处理每个物件(bounding box)

for obj in root.iter(\'object\'):
cls = obj.find(\'name\').text
if cls not in classes:
continue
cls_id = classes.index(cls)
xmlbox = obj.find(\'bndbox\')
b = (float(xmlbox.find(\'xmin\').text), float(xmlbox.find(\'ymin\').text),
float(xmlbox.find(\'xmax\').text), float(xmlbox.find(\'ymax\').text))
bbox = convert_bbox((w, h), b)
out_file.write(f"{cls_id} {\' \'.join([str(a) for a in bbox])}\\n")

遍历 XML 文件中每个 标籤,这些标籤表示图像中的物体。取得物件的类别名称 cls,并确认该名称是否在预定义的 classes 清单中,如果不在则跳过。找到类别对应的 ID (cls_id)。取得物件的边界框座标 ,转换成 YOLO 格式,并写入到对应的 TXT 文件中。

总结

这段程式码的主要目的是自动将 Pascal VOC 格式的 XML 文件转换为 YOLO 格式的 TXT 文件,使用者只需指定资料夹路径和类别名称,即可进行大批量的格式转换。