Table of contents
1. Introduction to VOC format and YOLO format?
2. Set the file address and image information
3. Traverse and parse YOLO files
4. Create XML file and write information
Preface
This article describes how to convert YOLO format to XML format. See another article for converting XML format to YOLO format.
1. Introduction to VOC format and YOLO format?
1.VOC format
The format of the VOC data set is XML format. The following is an example:
<annotation> <folder>img</folder> <filename>pikaqiu.jpg</filename> <path>E:\cv_code\image_processing\test\img\pikaqiu.jpg</path> <source> <database>Unknown</database> </source> <size> <width>1062</width> <height>974</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>pikaqiu</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>83</xmin> <ymin>74</ymin> <xmax>987</xmax> <ymax>920</ymax> </bndbox> </object> </annotation>
The information we need to use includes the picture name: <filename>pikaqiu.jpg</filename>, the width, height, and channel number information of the picture: <size> <width>1062</width> <height>974</height > <depth>3</depth> </size>, category name: <name>pikaqiu</name>, box information: <xmin>83</xmin> <ymin>74</ymin> <xmax>987< /xmax> <ymax>920</ymax>.
2.YOLO format
(class,xCenter,yCenter,w,h), which respectively represent the internal classification, the center coordinates of the label box, and the relative width and length of the label box.
2. Usage steps
1. Import the library
import xml.etree.ElementTree as ET
import os
2. Set the file address and image information
# Yolo格式文件所在目录
yolo_dir = "E:/cv_code/image_processing/aug_datasets/label/"
# XML文件保存目录
xml_dir = "E:/cv_code/image_processing/aug_datasets/Annotations/"
# 图像尺寸
img_width, img_height = 1062, 974
# 类别数字标签和名称的映射
class_map = {"pikaqiu": 0}
3. Traverse and parse YOLO files
# 遍历Yolo格式文件夹中的所有文件
for yolo_file in os.listdir(yolo_dir):
if not yolo_file.endswith(".txt"):
continue
# 解析Yolo格式文件
with open(os.path.join(yolo_dir, yolo_file), "r") as f:
lines = f.readlines()
# 获取图像名称
img_file = os.path.splitext(yolo_file)[0] + ".jpg"
4. Create XML file and write information
# 创建XML文件
#创建根节点
root = ET.Element("annotation")
#创建子节点
filename = ET.SubElement(root, "filename")
#添加文本
filename.text = img_file
size = ET.SubElement(root, "size")
width = ET.SubElement(size, "width")
width.text = str(img_width)
height = ET.SubElement(size, "height")
height.text = str(img_height)
depth = ET.SubElement(size, "depth")
depth.text = "3"
# 遍历所有目标
for line in lines:
parts = line.strip().split()
if len(parts) < 5:
continue
cls_id = int(parts[0])
if cls_id in class_map:
continue
for k, v in class_map.items():
cls_name = None
if v == cls_id:
cls_name = k
break
# cls_name = class_map[cls_id]
x = float(parts[1])
y = float(parts[2])
w = float(parts[3])
h = float(parts[4])
# 计算边界框坐标
xmin = int((x - w / 2) * img_width)
ymin = int((y - h / 2) * img_height)
xmax = int((x + w / 2) * img_width)
ymax = int((y + h / 2) * img_height)
# 将信息写入XML文件
obj = ET.SubElement(root, "object")
name = ET.SubElement(obj, "name")
name.text = cls_name
bndbox = ET.SubElement(obj, "bndbox")
xmin_node = ET.SubElement(bndbox, "xmin")
xmin_node.text = str(xmin)
ymin_node = ET.SubElement(bndbox, "ymin")
ymin_node.text = str(ymin)
xmax_node = ET.SubElement(bndbox, "xmax")
xmax_node.text = str(xmax)
ymax_node = ET.SubElement(bndbox, "ymax")
ymax_node.text = str(ymax)
#将树写入文件
tree = ET.ElementTree(root)
tree.write(xml_dir + os.path.splitext(yolo_file)[0] + ".xml")
5.Total code
import os
import xml.etree.ElementTree as ET
# Yolo格式文件所在目录
yolo_dir = "E:/cv_code/image_processing/aug_datasets/label/"
# XML文件保存目录
xml_dir = "E:/cv_code/image_processing/aug_datasets/Annotations/"
# 图像尺寸
img_width, img_height = 1062, 974
# 类别数字标签和名称的映射
class_map = {"pikaqiu": 0}
# 遍历Yolo格式文件夹中的所有文件
for yolo_file in os.listdir(yolo_dir):
if not yolo_file.endswith(".txt"):
continue
# 解析Yolo格式文件
with open(os.path.join(yolo_dir, yolo_file), "r") as f:
lines = f.readlines()
# 获取图像文件名
img_file = os.path.splitext(yolo_file)[0] + ".jpg"
# 创建XML文件
#创建根节点
root = ET.Element("annotation")
#创建子节点
filename = ET.SubElement(root, "filename")
#添加文本
filename.text = img_file
size = ET.SubElement(root, "size")
width = ET.SubElement(size, "width")
width.text = str(img_width)
height = ET.SubElement(size, "height")
height.text = str(img_height)
depth = ET.SubElement(size, "depth")
depth.text = "3"
# 遍历所有目标
for line in lines:
parts = line.strip().split()
if len(parts) < 5:
continue
cls_id = int(parts[0])
if cls_id in class_map:
continue
for k, v in class_map.items():
cls_name = None
if v == cls_id:
cls_name = k
break
x = float(parts[1])
y = float(parts[2])
w = float(parts[3])
h = float(parts[4])
# 计算边界框坐标
xmin = int((x - w / 2) * img_width)
ymin = int((y - h / 2) * img_height)
xmax = int((x + w / 2) * img_width)
ymax = int((y + h / 2) * img_height)
# 将信息写入XML文件
obj = ET.SubElement(root, "object")
name = ET.SubElement(obj, "name")
name.text = cls_name
bndbox = ET.SubElement(obj, "bndbox")
xmin_node = ET.SubElement(bndbox, "xmin")
xmin_node.text = str(xmin)
ymin_node = ET.SubElement(bndbox, "ymin")
ymin_node.text = str(ymin)
xmax_node = ET.SubElement(bndbox, "xmax")
xmax_node.text = str(xmax)
ymax_node = ET.SubElement(bndbox, "ymax")
ymax_node.text = str(ymax)
#将数据写入文件
tree = ET.ElementTree(root)
tree.write(xml_dir + os.path.splitext(yolo_file)[0] + ".xml")