1、yolo转xml
python
from xml.dom.minidom import Document
import os
import cv2
# def makexml(txtPath, xmlPath, picPath): # txt所在文件夹路径,xml文件保存路径,图片所在文件夹路径
def makexml(picPath, txtPath, xmlPath): # txt所在文件夹路径,xml文件保存路径,图片所在文件夹路径
"""此函数用于将yolo格式txt标注文件转换为voc格式xml标注文件
"""
dic = {'0': "plane", # 创建字典用来对类型进行转换
'1': "baseball diamond", # 此处的字典要与自己的classes.txt文件中的类对应,且顺序要一致
'2': "bridge",
'3': "ground track field",
'4': "small vehicle",
'5': "large vehicle",
'6': "ship",
'7': "tennis court",
'8': "basketball court",
'9': "storage tank",
'10': "soccer ball field",
'11': "roundabout",
'12': "harbor",
'13': "swimming pool",
'14': "helicopter",
}
files = os.listdir(txtPath)
for i, name in enumerate(files):
xmlBuilder = Document()
annotation = xmlBuilder.createElement("annotation") # 创建annotation标签
xmlBuilder.appendChild(annotation)
txtFile = open(txtPath + name)
txtList = txtFile.readlines()
img = cv2.imread(picPath + name[0:-4] + ".jpg")
Pheight, Pwidth, Pdepth = img.shape
folder = xmlBuilder.createElement("folder") # folder标签
foldercontent = xmlBuilder.createTextNode("driving_annotation_dataset")
folder.appendChild(foldercontent)
annotation.appendChild(folder) # folder标签结束
filename = xmlBuilder.createElement("filename") # filename标签
filenamecontent = xmlBuilder.createTextNode(name[0:-4] + ".jpg")
filename.appendChild(filenamecontent)
annotation.appendChild(filename) # filename标签结束
size = xmlBuilder.createElement("size") # size标签
width = xmlBuilder.createElement("width") # size子标签width
widthcontent = xmlBuilder.createTextNode(str(Pwidth))
width.appendChild(widthcontent)
size.appendChild(width) # size子标签width结束
height = xmlBuilder.createElement("height") # size子标签height
heightcontent = xmlBuilder.createTextNode(str(Pheight))
height.appendChild(heightcontent)
size.appendChild(height) # size子标签height结束
depth = xmlBuilder.createElement("depth") # size子标签depth
depthcontent = xmlBuilder.createTextNode(str(Pdepth))
depth.appendChild(depthcontent)
size.appendChild(depth) # size子标签depth结束
annotation.appendChild(size) # size标签结束
for j in txtList:
oneline = j.strip().split(" ")
object = xmlBuilder.createElement("object") # object 标签
picname = xmlBuilder.createElement("name") # name标签
namecontent = xmlBuilder.createTextNode(dic[oneline[0]])
picname.appendChild(namecontent)
object.appendChild(picname) # name标签结束
pose = xmlBuilder.createElement("pose") # pose标签
posecontent = xmlBuilder.createTextNode("Unspecified")
pose.appendChild(posecontent)
object.appendChild(pose) # pose标签结束
truncated = xmlBuilder.createElement("truncated") # truncated标签
truncatedContent = xmlBuilder.createTextNode("0")
truncated.appendChild(truncatedContent)
object.appendChild(truncated) # truncated标签结束
difficult = xmlBuilder.createElement("difficult") # difficult标签
difficultcontent = xmlBuilder.createTextNode("0")
difficult.appendChild(difficultcontent)
object.appendChild(difficult) # difficult标签结束
bndbox = xmlBuilder.createElement("bndbox") # bndbox标签
xmin = xmlBuilder.createElement("xmin") # xmin标签
mathData = int(((float(oneline[1])) * Pwidth + 1) - (float(oneline[3])) * 0.5 * Pwidth)
xminContent = xmlBuilder.createTextNode(str(mathData))
xmin.appendChild(xminContent)
bndbox.appendChild(xmin) # xmin标签结束
ymin = xmlBuilder.createElement("ymin") # ymin标签
mathData = int(((float(oneline[2])) * Pheight + 1) - (float(oneline[4])) * 0.5 * Pheight)
yminContent = xmlBuilder.createTextNode(str(mathData))
ymin.appendChild(yminContent)
bndbox.appendChild(ymin) # ymin标签结束
xmax = xmlBuilder.createElement("xmax") # xmax标签
mathData = int(((float(oneline[1])) * Pwidth + 1) + (float(oneline[3])) * 0.5 * Pwidth)
xmaxContent = xmlBuilder.createTextNode(str(mathData))
xmax.appendChild(xmaxContent)
bndbox.appendChild(xmax) # xmax标签结束
ymax = xmlBuilder.createElement("ymax") # ymax标签
mathData = int(((float(oneline[2])) * Pheight + 1) + (float(oneline[4])) * 0.5 * Pheight)
ymaxContent = xmlBuilder.createTextNode(str(mathData))
ymax.appendChild(ymaxContent)
bndbox.appendChild(ymax) # ymax标签结束
object.appendChild(bndbox) # bndbox标签结束
annotation.appendChild(object) # object标签结束
f = open(xmlPath + name[0:-4] + ".xml", 'w')
xmlBuilder.writexml(f, indent='\t', newl='\n', addindent='\t', encoding='utf-8')
f.close()
if __name__ == "__main__":
picPath = "./images/test/" # 图片所在文件夹路径,后面的/一定要带上
txtPath = "./labels/test/" # txt所在文件夹路径,后面的/一定要带上
xmlPath = "./annotations/test/" # xml文件保存路径,后面的/一定要带上
makexml(picPath, txtPath, xmlPath)
xml格式
xml
<?xml version="1.0" encoding="utf-8"?>
<annotation>
<folder>driving_annotation_dataset</folder>
<filename>0.jpg</filename>
<size>
<width>640</width>
<height>640</height>
<depth>3</depth>
</size>
<object>
<name>plane</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>315</xmin>
<ymin>248</ymin>
<xmax>422</xmax>
<ymax>304</ymax>
</bndbox>
</object>
</annotation>
2、xml转dota
python
import os
import xml.etree.ElementTree as ET
def convert_voc_to_dota_simple(xml_folder, output_folder):
# 创建输出文件夹(如果不存在)
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 遍历 XML 文件夹中的所有文件
for xml_file in os.listdir(xml_folder):
if xml_file.endswith('.xml'): # 只处理 XML 文件
# 解析 XML 文件
tree = ET.parse(os.path.join(xml_folder, xml_file))
root = tree.getroot()
# 初始化 DOTA 格式的字符串列表
dota_annotations = []
# 遍历 XML 中的 'object' 元素
for obj in root.iter('object'):
# 获取标准矩形边界框坐标
bndbox = obj.find('bndbox')
# 获取类别和难度级别
category = obj.find('name').text
difficult = obj.find('difficult').text
# 提取矩形边界框的坐标
xmin = int(bndbox.find('xmin').text)
ymin = int(bndbox.find('ymin').text)
xmax = int(bndbox.find('xmax').text)
ymax = int(bndbox.find('ymax').text)
# 将矩形边界框的四个角作为旋转边界框的顶点
coords = [
xmin, ymin, # 左上角
xmax, ymin, # 右上角
xmax, ymax, # 右下角
xmin, ymax # 左下角
]
# 将坐标、类别和难度级别转换为 DOTA 格式
dota_format = ' '.join(map(str, coords + [category, difficult]))
dota_annotations.append(dota_format)
# 写入转换后的信息到 TXT 文件
output_file_path = os.path.join(output_folder, xml_file.replace('.xml', '.txt'))
with open(output_file_path, 'w') as f:
for annotation in dota_annotations:
f.write("%s\n" % annotation) # 每个注释占一行
# 调用函数,传入 XML 文件夹路径和输出文件夹路径
xml_folder = './annotations/val' # 请替换为您的 XML 文件夹路径
output_folder = './DOTA_labels/val' # 请替换为您希望保存输出 TXT 文件的文件夹路径
convert_voc_to_dota_simple(xml_folder, output_folder)
3、验证dota 画框
python
import xml.etree.ElementTree as ET
import os
import math
import cv2
import numpy as np
import dota_utils as util
import random
img_root = r"./images/train/"
label_root = r"./DOTA_labels/train/"
drawed_img_root = r"./DOTA_labels_drawed/train/"
image_name = os.listdir(img_root)
for i in range(len(image_name)):
img_path = os.path.join(img_root, image_name[i])
label_path = os.path.join(label_root, image_name[i].split('.')[0] + '.txt')
drawed_img_path = os.path.join(drawed_img_root, image_name[i])
objects = util.parse_dota_poly(label_path)
print(objects)
img = cv2.imread(img_path)
poly = []
for i in range(len(objects)):
poly.append(np.array(objects[i]['poly'], dtype=np.int32))
print(poly)
cv2.polylines(img, poly, isClosed=True, color=(35, 37, 133), thickness=2)
drawed_img_path = drawed_img_path.replace('.bmp', '.png')
cv2.imwrite(drawed_img_path, img)