python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据

python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据

    • 准备工作
    • 修改代码路径
    • 运行代码
      • 程序bug(没时间看所以还没解决):

准备工作

需在目标文件夹中创建三个子文件夹,如:

20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML
   ├─20190822_Artificial_Flower
   ├─20190822_Artificial_Flower_txt
   └─20190822_Artificial_Flower_xml

其中20190822_Artificial_Flower存放我们的图片,20190822_Artificial_Flower_txt存放我们用(yolo)已经生成的.txt文件,20190822_Artificial_Flower_xml(空文件夹)存放我们将要生成的.xml文件。然后还有一个obj.names文件,存放我们的标注类名。
python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据_第1张图片
python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据_第2张图片
python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据_第3张图片
python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据_第4张图片

修改代码路径

import os
import xml.etree.ElementTree as ET
from PIL import Image
import numpy as np

# img_path = 'C:/Users/jsb/Desktop/TFRecord/JPEGImages/'                   #原图.jpg文件的路径
img_path = 'D:/Yolov3_Tensorflow/LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower/'                   #原图.jpg文件的路径

# labels_path = 'C:/Users/jsb/Desktop/TFRecord/labels/'                    #labels中.txt文件的路径
labels_path = 'D:/Yolov3_Tensorflow/LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_txt/'                    #labels中.txt文件的路径

# annotations_path = 'C:/Users/jsb/Desktop/TFRecord/Annotations/'          #生成的xml文件需要保存的路径
annotations_path = 'D:/Yolov3_Tensorflow\LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_xml/'          #生成的xml文件需要保存的路径

labels = os.listdir(labels_path)
clsnames_path = 'D:/Yolov3_Tensorflow/LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/obj.names'     #names文件的路径
with open(clsnames_path,'r') as f:
    classes = f.readlines()
    classes = [cls.strip('\n') for cls in classes]
def write_xml(imgname,filepath,labeldicts):                     #参数imagename是图片名(无后缀)
    root = ET.Element('Annotation')                             #创建Annotation根节点
    ET.SubElement(root, 'filename').text = str(imgname)         #创建filename子节点(无后缀)
    sizes = ET.SubElement(root,'size')                          #创建size子节点            
    ET.SubElement(sizes, 'width').text = '1280'                 #没带脑子直接写了原图片的尺寸......
    ET.SubElement(sizes, 'height').text = '720'
    ET.SubElement(sizes, 'depth').text = '3'                    #图片的通道数:img.shape[2]
    for labeldict in labeldicts:
        objects = ET.SubElement(root, 'object')                 #创建object子节点
        ET.SubElement(objects, 'name').text = labeldict['name']        #BDD100K_10.names文件中  
                                                                       #的类别名
        ET.SubElement(objects, 'pose').text = 'Unspecified'
        ET.SubElement(objects, 'truncated').text = '0'
        ET.SubElement(objects, 'difficult').text = '0'
        bndbox = ET.SubElement(objects,'bndbox')
        ET.SubElement(bndbox, 'xmin').text = str(int(labeldict['xmin']))
        ET.SubElement(bndbox, 'ymin').text = str(int(labeldict['ymin']))
        ET.SubElement(bndbox, 'xmax').text = str(int(labeldict['xmax']))
        ET.SubElement(bndbox, 'ymax').text = str(int(labeldict['ymax']))
    tree = ET.ElementTree(root)
    tree.write(filepath, encoding='utf-8')


for label in labels:                                           #批量读.txt文件
    with open(labels_path + label, 'r') as f:
        img_id = os.path.splitext(label)[0]
        contents = f.readlines()
        labeldicts = []
        for content in contents:
            img = np.array(Image.open(img_path+label.strip('.txt') + '.jpg'))
            sh,sw = img.shape[0],img.shape[1]                  #img.shape[0]是图片的高度720
                                                               #img.shape[1]是图片的宽度720
            content = content.strip('\n').split()
            x=float(content[1])*sw
            y=float(content[2])*sh
            w=float(content[3])*sw
            h=float(content[4])*sh
            new_dict = {
     'name': classes[int(content[0])],
                        'difficult': '0',
                        'xmin': x+1-w/2,                      #坐标转换公式看另一篇文章....
                        'ymin': y+1-h/2,
                        'xmax': x+1+w/2,
                        'ymax': y+1+h/2
                        }
            labeldicts.append(new_dict)
        write_xml(img_id, annotations_path + label.strip('.txt') + '.xml', labeldicts)

需修改代码中四个路径:

img_path = 'D:/Yolov3_Tensorflow/LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower/'

labels_path = 'D:/Yolov3_Tensorflow/LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_txt/'

annotations_path = 'D:/Yolov3_Tensorflow\LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_xml/'  

clsnames_path = 'D:/Yolov3_Tensorflow/LabelImg/YOLO-TXT_convert_to_PascalVOC-XML/20190822_Artificial_Flower_YOLO-TXT_convert_to_PascalVOC-XML/obj.names'

修改成与自己的路径相对应的即可,需注意的是路径中要用“/”分隔符而不要用“\”分隔符,因为它有可能会被识别成转义字符。

运行代码

然后运行代码,它就会在20190822_Artificial_Flower_xml哗啦哗啦地生成对应的xml文件了:
python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据_第5张图片

参考文章:Python将VOC数据集归一化后的labels(.txt)文件批量转成xml文件

程序bug(没时间看所以还没解决):

貌似代码中有点bug,计算出来的坐标数值比用LabelImg转换出来的值大1。如图框选部分实际应为[563, 495, 696, 618]
这是程序生成的:
python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据_第6张图片
这是用LabelImg转换得到的:
python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据_第7张图片

你可能感兴趣的:(tensorflow)