How to convert YOLO annotations (.txt) to PASCAL VOC (.xml)?
Asked Answered
G

4

9

I have built a dataset to train YOLOv4 and I have all the labels in YOLO format (I used LabelImg). Now I want to train SSD with the same dataset and therefore I need the labels in the PASCAL VOC format. I have seen some ways to do the opposite conversion (voc to yolo) but not the one I am looking for. Since I have thousands of images I want to find a way to automate this whole procedure without having to go through each image/label one by one.

Does anyone have any ideas on how to approach this?

Thanks in advance!

Gasp answered 4/7, 2021 at 14:36 Comment(0)
C
8

I have had the same problem. I wrote a script that will do this conversion for you. You can find a link to the code here: https://github.com/JPM-Tech/Object-Detection/tree/main/Scripts/converters/convert-yolo-to-xml.py. This is a link to some docs that were written on how to use it: https://github.com/JPM-Tech/Object-Detection/tree/main/Scripts/converters#convert-yolo-to-xml. Hopefully this helps you as much as it has helped me.

Copperas answered 11/7, 2021 at 19:38 Comment(0)
D
6

My classmates and I have created a python package called PyLabel to help others with this task and other labelling tasks. You can see an example in this notebook https://github.com/pylabel-project/samples/blob/main/yolo2coco.ipynb.

The general solution is the same as what the others have mentioned above but the code encapsulated in this package so you only have to right minimal code. For example:

!pip install pylabel
from pylabel import importer
dataset = importer.ImportYoloV5(path=path_to_annotations)
dataset.export.ExportToVoc(dataset)

You can find the source code that is used behind the scenes here https://github.com/pylabel-project/pylabel/tree/main/pylabel

Dine answered 27/10, 2021 at 1:36 Comment(1)
Thanks this works. Also dataset.export.ExportToVoc(dataset) should be dataset.export.ExportToVoc(export_dir)?Suberin
J
1

Here is the script for creating an XML, when the relevant information is provided i.e the variables at the start of the script.

import numpy as np
from pathlib import Path
import xml.etree.cElementTree as ET
from PIL import Image
import os

image_path = "" # provide image path
anno_folder = "" # provide .XML folder path
filename = "" # provide image name
#Read each bounding box as a list of dictionary and append it in the list for each file
All_bboxes = "[{"xmin":1433,"xmax":1503,"ymin":1570,"ymax":1700,"skuLabel":"bus"}]" 


img = np.array(Image.open(image_path).convert('RGB'))

annotation = ET.Element('annotation')
ET.SubElement(annotation, 'folder').text = str(anno_folder)
ET.SubElement(annotation, 'filename').text = str(filename)
ET.SubElement(annotation, 'path').text = str(filename)

source = ET.SubElement(annotation, 'source')
ET.SubElement(source, 'database').text = 'Unknown'

size = ET.SubElement(annotation, 'size')
ET.SubElement(size, 'width').text = str (img.shape[1])
ET.SubElement(size, 'height').text = str(img.shape[0])
ET.SubElement(size, 'depth').text = str(img.shape[2])

ET.SubElement(annotation, 'segmented').text = '0'

for item in All_bboxes:
    label = item['Label']
    xmax = item['xmax']
    xmin = item['xmin']
    ymin = item['ymin']
    ymax = item['ymax']

    object = ET.SubElement(annotation, 'object')
    ET.SubElement(object, 'name').text = label
    ET.SubElement(object, 'pose').text = 'Unspecified'
    ET.SubElement(object, 'truncated').text = '0'
    ET.SubElement(object, 'difficult').text = '0'

    bndbox = ET.SubElement(object, 'bndbox')
    ET.SubElement(bndbox, 'xmin').text = str(xmin)
    ET.SubElement(bndbox, 'ymin').text = str(ymin)
    ET.SubElement(bndbox, 'xmax').text = str(xmax)
    ET.SubElement(bndbox, 'ymax').text = str(ymax)

tree = ET.ElementTree(annotation)
xml_file_name = os.path.join(anno_folder, f'{filename.split('.')[0]}.xml')
tree.write(xml_file_name)

In Yolo format, you have x y width height while in PASCAL VOC you have xmin ymin xmax ymax. SO you have to convert that while loading them into the All_bboxes. This function converts .xml format to .txt so it can help you with conversion of co-ordinates.

P.S. You can loops over the above code to make it work for multiple files.

Jimmy answered 6/7, 2021 at 10:49 Comment(0)
R
0

You can use this tool

pip install pascal-voc
from pascal import annotation_from_yolo
from pascal.utils import save_xml

label_map = {
    0: "person",
    1: "dog"
}

if __name__ == "__main__":
    ann = annotation_from_yolo(
        "000001.txt",
        label_map=label_map,
        img_w=353,
        img_h=500)
    
    xml = ann.to_xml()
    save_xml("000001.xml", xml)
Recite answered 24/8, 2023 at 15:13 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.