目标检测任务中,输入为一张图片以及目标框的坐标,在标注工具标注完成后,通常坐标会保存在xml文件中。当我们根据自己的业务需求,需要修改标注数据时,由于重新标注的成本较高,所以直接修改xml文件较为合适。
当前我使用的标注工具是LableImg的Ubuntu版本:
github:https://github.com/chinakook/labelImg2
https://github.com/tzutalin/labelImg
首先是创建xml文件,代码如下:
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"
# 请根据个人需求修改[xmin, ymin, xmax, ymax]的值的获取方式
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"))
修改xml文件:
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))
删除某个类的目标框:
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))
修改或删除完成后,都要记得使用write覆盖原xml文件