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