In the target detection task, input the coordinates of a picture and target box. After the annotation tool is completed, the coordinates are usually saved in the xml file. When we need to modify the annotation data according to our own business needs, it is more appropriate to modify the xml file directly because of the high cost of re annotation.
The annotation tool I am currently using is Ubuntu version of LableImg:
github: https://github.com/chinakook/labelImg2
https://github.com/tzutalin/labelImg
First, create an xml file with the following code:
import xml.etree.ElementTree as ET import numpy as np import os path = '../data/Images' label_path = '../data/label' input_path = '../data/Input' annotation_path = '../data/Annotation' for img_path in images: img = cv2.imread(os.path.join(path, img_path)) x = [] y = [] root = ET.Element("annotation") filename = ET.SubElement(root, "filename") filepath = ET.SubElement(root, "filepath") size = ET.SubElement(root, "size") width = ET.SubElement(size, "width") height = ET.SubElement(size, "height") depth = ET.SubElement(size, "depth") object_ = ET.SubElement(root, "object") name = ET.SubElement(object_, "name") bndbox = ET.SubElement(object_, "bndbox") xmin = ET.SubElement(bndbox, "xmin") ymin = ET.SubElement(bndbox, "ymin") xmax = ET.SubElement(bndbox, "xmax") ymax = ET.SubElement(bndbox, "ymax") filename.text = img_path filepath.text = os.path.join(path, img_path) width.text = str(img.shape[0]) height.text = str(img.shape[1]) depth.text = str(img.shape[2]) name.text = "name" # Please modify the value acquisition method of [xmin, ymin, xmax, ymax] according to personal needs for i in range(img.shape[0]): for j in range(img.shape[1]): if img[i][j][0] == 0 and img[i][j][2] == 255: x.append(j) y.append(i) xmin.text = str(np.min(x)) ymin.text = str(np.min(y)) xmax.text = str(np.max(x)) ymax.text = str(np.max(y)) tree = ET.ElementTree(root) tree.write(os.path.join(annotation_path, img_path.split('.')[0]+".xml"))
Modify the xml file:
for xml_file in xml_list: updateTree = ET.parse(os.path.join(xml_dir, xml_file)) root = updateTree.getroot() sub1 = root.findall("object") for object_ in sub1: sub2 = object_.find("name") if sub2.text == 'A': sub2.text = 'B' updateTree.write(os.path.join(xml_dir, xml_file))
To delete the target box of a class:
for xml_path in xml_list: tree = ET.parse(os.path.join(xml_dir_path, xml_path)) root = tree.getroot() for obj in root.findall('object'): if obj.find('name').text == 'B': root.remove(obj) tree.write(os.path.join(xml_dir_path, xml_path))
Remember to overwrite the original xml file with write after modification or deletion