代码:
#!/usr/bin/python # -*- coding: UTF-8 -*- # get annotation object bndbox location import os import cv2 try: import xml.etree.cElementTree as ET #解析xml的c语言版的模块 except ImportError: import xml.etree.ElementTree as ET ##get object annotation bndbox loc start def GetAnnotBoxLoc(AnotPath):#AnotPath VOC标注文件路径 tree = ET.ElementTree(file=AnotPath) #打开文件,解析成一棵树型结构 root = tree.getroot()#获取树型结构的根 ObjectSet=root.findall(\'object\')#找到文件中所有含有object关键字的地方,这些地方含有标注目标 ObjBndBoxSet={} #以目标类别为关键字,目标框为值组成的字典结构 for Object in ObjectSet: ObjName=Object.find(\'name\').text BndBox=Object.find(\'bndbox\') x1 = int(BndBox.find(\'xmin\').text)#-1 #-1是因为程序是按0作为起始位置的 y1 = int(BndBox.find(\'ymin\').text)#-1 x2 = int(BndBox.find(\'xmax\').text)#-1 y2 = int(BndBox.find(\'ymax\').text)#-1 BndBoxLoc=[x1,y1,x2,y2] if ObjName in ObjBndBoxSet: ObjBndBoxSet[ObjName].append(BndBoxLoc)#如果字典结构中含有这个类别了,那么这个目标框要追加到其值的末尾 else: ObjBndBoxSet[ObjName]=[BndBoxLoc]#如果字典结构中没有这个类别,那么这个目标框就直接赋值给其值吧 return ObjBndBoxSet ##get object annotation bndbox loc end def display(objBox,pic): img = cv2.imread(pic) for key in objBox.keys(): for i in range(len(objBox[key])): cv2.rectangle(img, (objBox[key][i][0],objBox[key][i][1]), (objBox[key][i][2], objBox[key][i][3]), (0, 0, 255), 2) cv2.putText(img, key, (objBox[key][i][0],objBox[key][i][1]), cv2.FONT_HERSHEY_COMPLEX, 1, (255,0,0), 1) cv2.imshow(\'img\',img) cv2.imwrite(\'display.jpg\',img) cv2.waitKey(0) if __name__== \'__main__\': pic = r\"./VOCdevkit/VOC2007/JPEGImages/000282.jpg\" ObjBndBoxSet=GetAnnotBoxLoc(r\"./VOCdevkit/VOC2007/Annotations/000282.xml\") print(ObjBndBoxSet) display(ObjBndBoxSet,pic)
输出结果:
{\’chair\’: [[335, 263, 484, 373]], \’person\’: [[327, 104, 476, 300], [232, 57, 357, 374], [3, 32, 199, 374], [58, 139, 296, 374]]}
图示:
补充知识:使用python将voc类型标注xml文件对图片进行目标还原,以及批量裁剪特定类
使用标注工具如labelimg对图片物体进行voc类型标注,会生成xml文件,如何判断别人的数据集做的好不好,可以用以下代码进行目标还原。
import xml.etree.cElementTree as ET import cv2 import os import glob def GetAnnotBoxLoc(AnotPath): tree = ET.ElementTree(file=AnotPath) root = tree.getroot() ObjectSet=root.findall(\'object\') ObjBndBoxSet={} for Object in ObjectSet: ObjName=Object.find(\'name\').text BndBox=Object.find(\'bndbox\') x1 = int(BndBox.find(\'xmin\').text) y1 = int(BndBox.find(\'ymin\').text) x2 = int(BndBox.find(\'xmax\').text) y2 = int(BndBox.find(\'ymax\').text) BndBoxLoc=[x1,y1,x2,y2] if ObjName in ObjBndBoxSet: ObjBndBoxSet[ObjName].append(BndBoxLoc) else: ObjBndBoxSet[ObjName]=[BndBoxLoc] return ObjBndBoxSet def GetAnnotName(AnotPath): tree = ET.ElementTree(file=AnotPath) root = tree.getroot() path=root.find(\'path\').text return path def Drawpic(xml_path,result_path): n = 0 xmls = glob.glob(os.path.join(xml_path, \'*.xml\')) for xml in xmls: n = n + 1 box=GetAnnotBoxLoc(xml) path=GetAnnotName(xml) img = cv2.imread(path) for classes in list(box.keys()): for boxes in box[classes]: if classes == \"bad1\": cv2.rectangle(img,(int(boxes[0]),int(boxes[1])),(int(boxes[2]),int(boxes[3])),(255,0,0),3) #blue if classes == \"bad2\": cv2.rectangle(img,(int(boxes[0]),int(boxes[1])),(int(boxes[2]),int(boxes[3])),(0,255,0),3) #green if classes == \"bad3\": cv2.rectangle(img,(int(boxes[0]),int(boxes[1])),(int(boxes[2]),int(boxes[3])),(0,0,255),3) #red cv2.imwrite(result_path+\"/\"+str(n)+\"_result.jpg\", img) print(path,\"还原成功\") Drawpic(\"/home/wxy/Dashboard/dataset/VOCdevkit/VOC2012/Annotations\",\"/home/wxy/Dashboard/dataset/VOCdevkit/VOC2012/test\")
使用labelimg对图像进行标注,folder目录需要修改一下
import xml.etree.ElementTree as ET import os for i in os.listdir(\'/home/wxy/Dashboard/dataset/VOCdevkit/VOC2012/Annotations\'): tree = ET.parse(\'/home/wxy/Dashboard/dataset/VOCdevkit/VOC2012/Annotations\'+\'/\'+i) root = tree.getroot() print(root.find(\'folder\').text) root.find(\'folder\').text = \'VOC2012\' print(root.find(\'folder\').text) tree.write(\'/home/wxy/Dashboard/dataset/VOCdevkit/VOC2012/Annotations\'+\'/\'+i)
批量裁剪特定类,xml.dom.minidom好像比xml.etree.cElementTree好用啊。
#coding=utf-8 import xml.dom.minidom import cv2 import os for name in os.listdir(\"./Annotations/\"): dom=xml.dom.minidom.parse(\"./Annotations/\"+name) root=dom.documentElement object_name=root.getElementsByTagName(\'name\') if(object_name[0].firstChild.data == \"normal\"): print(name) xmin=root.getElementsByTagName(\'xmin\') ymin=root.getElementsByTagName(\'ymin\') xmax=root.getElementsByTagName(\'xmax\') ymax=root.getElementsByTagName(\'ymax\') x_min = int(xmin[0].firstChild.data) y_min = int(ymin[0].firstChild.data) x_max = int(xmax[0].firstChild.data) y_max = int(ymax[0].firstChild.data) img=cv2.imread(\"./JPEGImages/\"+name[:-4]+\".jpg\") cropped=img[y_min:y_max,x_min:x_max] cv2.imwrite(\"./cut_jpg/\"+name[:-4]+\".jpg\", cropped)
以上这篇Python读取VOC中的xml目标框实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持自学编程网。