YOLO target detection data set txt format to xml format

YOLO target detection data set txt format to xml format

    • 1. txt format before conversion
    • 2. txt format to xml format code
      • 2.1 Source code
      • 2.2 What needs to be modified
    • 3. Converted xml format

Code resources:
txt2xml.py

1. txt format before conversion

If we use the LabelImg tool to label the data set, the generated txt file is as follows:

Each line represents (category, center x relative coordinates, center y relative coordinates, relative width, relative height)

2.txt format to xml format code

2.1 Source code

from xml.dom.minidom import Document
import os
import cv2
from tqdm import tqdm


# def makexml(txtPath, xmlPath, picPath): # The folder path where txt is located, the path where the xml file is saved, and the folder path where the picture is located
def makexml(picPath, txtPath, xmlPath, datasetName): # Path to the folder where txt is located, path to save the xml file, path to the folder where the picture is located
    """This function is used to convert yolo format txt annotation file to voc format xml annotation file
    Create three subfolders under your own marked picture folder, named picture, txt, xml respectively
    """
    dic = {<!-- -->'0': "zero", # Create a dictionary to convert types
           '1': "one", # The dictionary here should correspond to the classes in your own classes.txt file, and the order should be consistent
           '2': "two",
           '3': "three",
           '4': "four",
           '5': "five",
           '6': "six",
           '7': "seven",
           '8': "eight",
           '9': "nine",
           }
    files = os.listdir(txtPath)
    for i, name in enumerate(tqdm(files)):
        if name == 'classes.txt':
            continue
        xmlBuilder = Document()
        annotation = xmlBuilder.createElement("annotation") # create annotation tag
        xmlBuilder.appendChild(annotation)
        txtFile = open(os. path. join(txtPath, name))
        txtList = txtFile. readlines()
        img = cv2.imread(os.path.join(picPath, name.replace('txt', 'jpg')))
        Pheight, Pwidth, Pdepth = img.shape

        folder = xmlBuilder.createElement("folder") #folder label
        foldercontent = xmlBuilder.createTextNode(datasetName)
        folder.appendChild(foldercontent)
        annotation.appendChild(folder) # end of folder label

        filename = xmlBuilder.createElement("filename") # filename tag
        filenamecontent = xmlBuilder.createTextNode(name[0:-4] + ".jpg")
        filename.appendChild(filenamecontent)
        annotation.appendChild(filename) # end of filename tag

        size = xmlBuilder.createElement("size") # size tag
        width = xmlBuilder.createElement("width") # size subtag width
        widthcontent = xmlBuilder. createTextNode(str(Pwidth))
        width.appendChild(widthcontent)
        size.appendChild(width) # size sub-label width ends

        height = xmlBuilder.createElement("height") # size sub-tag height
        heightcontent = xmlBuilder. createTextNode(str(Pheight))
        height.appendChild(heightcontent)
        size.appendChild(height) # size sub-label height ends

        depth = xmlBuilder.createElement("depth") # size sub-tag depth
        depthcontent = xmlBuilder.createTextNode(str(Pdepth))
        depth.appendChild(depthcontent)
        size.appendChild(depth) # size sub-label depth ends

        annotation.appendChild(size) # size tag ends

        for j in txtList:
            oneline = j.strip().split(" ")
            object = xmlBuilder.createElement("object") # object tag
            picname = xmlBuilder.createElement("name") # name tag
            namecontent = xmlBuilder.createTextNode(dic[oneline[0]])
            picname.appendChild(namecontent)
            object.appendChild(picname) # end of name tag

            pose = xmlBuilder.createElement("pose") # pose tag
            posecontent = xmlBuilder.createTextNode("Unspecified")
            pose.appendChild(posecontent)
            object.appendChild(pose) # end of pose label

            truncated = xmlBuilder.createElement("truncated") # truncated label
            truncatedContent = xmlBuilder.createTextNode("0")
            truncated.appendChild(truncatedContent)
            object.appendChild(truncated) # truncated label ends

            difficult = xmlBuilder.createElement("difficult") # difficult label
            difficultcontent = xmlBuilder.createTextNode("0")
            difficult.appendChild(difficultcontent)
            object.appendChild(difficult) # end of difficult tag

            bndbox = xmlBuilder.createElement("bndbox") # bndbox tag
            xmin = xmlBuilder.createElement("xmin") # xmin tag
            mathData = int(((float(oneline[1])) * Pwidth + 1) - (float(oneline[3])) * 0.5 * Pwidth)
            xminContent = xmlBuilder.createTextNode(str(mathData))
            xmin.appendChild(xminContent)
            bndbox.appendChild(xmin) # end of xmin label

            ymin = xmlBuilder.createElement("ymin") # ymin label
            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 label ends

            xmax = xmlBuilder.createElement("xmax") # xmax label
            mathData = int(((float(oneline[1])) * Pwidth + 1) + (float(oneline[3])) * 0.5 * Pwidth)
            xmaxContent = xmlBuilder.createTextNode(str(mathData))
            xmax.appendChild(xmaxContent)
            bndbox.appendChild(xmax) # end of xmax label

            ymax = xmlBuilder.createElement("ymax") # ymax label
            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 label ends

            object.appendChild(bndbox) # end of bndbox label

            annotation.appendChild(object) # object tag end

        f = open(os.path.join(xmlPath, name.replace('txt', 'xml')), 'w')
        xmlBuilder.writexml(f, indent='\t', newl='\\
', addindent='\t', encoding='utf-8')
        f. close()


if __name__ == "__main__":
    picPath = r"original picture folder path" # original picture folder path
    txtPath = r"original txt label folder path" # original txt label folder path
    xmlPath = r"save xml folder path" # save xml folder path
    datasetName = r'MyDataset' # dataset name
    os.makedirs(xmlPath) if not os.path.exists(xmlPath) else None
    makexml(picPath, txtPath, xmlPath, datasetName)

    # tasks = ['train', 'test', 'val'] # current task
    # for task in tasks:
    # picPath = r"...\images\{}".format(task) # Original image folder path
    # txtPath = r"...\labels\{}".format(task) # Original txt label folder path
    # xmlPath = r"...\labels\{}_xml".format(task) # save the xml folder path
    # datasetName = r'MyDataset'
    # os.makedirs(xmlPath) if not os.path.exists(xmlPath) else None
    # makexml(picPath, txtPath, xmlPath, datasetName)

2.2 What needs to be modified

  • Type of goal
    LabelImg will generate “classes.txt” after labeling, the following are the real category names, and the category codes from top to bottom are 0, 1, 2, …

    Therefore, a dictionary mapping needs to be established to map the category codes 0, 1, 2… (the left column below) to the real category names of classes.txt (the right column below)
  • Modify the dataset path
    Just modify it to your own dataset path and name

3. Converted xml format