python:批量统计xml中各类目标的数量案例
之前写了一个matlab的,越用越觉得麻烦,如果不同数据集要改类别数目,而且运行速度慢。所以重新写了一个Python的,直接读取xml文件夹路径就可以,不用预先知道类别,直接能够检测出所有类别的目标名称及其对应的数量。
分享出来给大家。
代码如下:
#-*-coding:utf-8-*-
importos
importxml.etree.ElementTreeasET
importnumpyasnp
np.set_printoptions(suppress=True,threshold=np.nan)
importmatplotlib
fromPILimportImage
defparse_obj(xml_path,filename):
tree=ET.parse(xml_path+filename)
objects=[]
forobjintree.findall('object'):
obj_struct={}
obj_struct['name']=obj.find('name').text
objects.append(obj_struct)
returnobjects
defread_image(image_path,filename):
im=Image.open(image_path+filename)
W=im.size[0]
H=im.size[1]
area=W*H
im_info=[W,H,area]
returnim_info
if__name__=='__main__':
xml_path='C:/Users/nansbas/Desktop/hebin/03/'
filenamess=os.listdir(xml_path)
filenames=[]
fornameinfilenamess:
name=name.replace('.xml','')
filenames.append(name)
recs={}
obs_shape={}
classnames=[]
num_objs={}
obj_avg={}
fori,nameinenumerate(filenames):
recs[name]=parse_obj(xml_path,name+'.xml')
fornameinfilenames:
forobjectinrecs[name]:
ifobject['name']notinnum_objs.keys():
num_objs[object['name']]=1
else:
num_objs[object['name']]+=1
ifobject['name']notinclassnames:
classnames.append(object['name'])
fornameinclassnames:
print('{}:{}个'.format(name,num_objs[name]))
print('信息统计算完毕。')
补充知识:Python对目标检测数据集xml文件操作(统计目标种类、数量、面积、比例等&修改目标名字)
1.根据xml文件统计目标种类以及数量
#-*-coding:utf-8-*-
#根据xml文件统计目标种类以及数量
importos
importxml.etree.ElementTreeasET
importnumpyasnp
np.set_printoptions(suppress=True,threshold=np.nan)
importmatplotlib
fromPILimportImage
defparse_obj(xml_path,filename):
tree=ET.parse(xml_path+filename)
objects=[]
forobjintree.findall('object'):
obj_struct={}
obj_struct['name']=obj.find('name').text
objects.append(obj_struct)
returnobjects
defread_image(image_path,filename):
im=Image.open(image_path+filename)
W=im.size[0]
H=im.size[1]
area=W*H
im_info=[W,H,area]
returnim_info
if__name__=='__main__':
xml_path='/home/dlut/网络/make_database/数据集——合集/VOCdevkit/VOC2018/Annotations/'
filenamess=os.listdir(xml_path)
filenames=[]
fornameinfilenamess:
name=name.replace('.xml','')
filenames.append(name)
recs={}
obs_shape={}
classnames=[]
num_objs={}
obj_avg={}
fori,nameinenumerate(filenames):
recs[name]=parse_obj(xml_path,name+'.xml')
fornameinfilenames:
forobjectinrecs[name]:
ifobject['name']notinnum_objs.keys():
num_objs[object['name']]=1
else:
num_objs[object['name']]+=1
ifobject['name']notinclassnames:
classnames.append(object['name'])
fornameinclassnames:
print('{}:{}个'.format(name,num_objs[name]))
print('信息统计算完毕。')
2.根据xml文件统计目标的平均长度、宽度、面积以及每一个目标在原图中的占比
#-*-coding:utf-8-*-
#统计
#计算每一个目标在原图中的占比
#计算目标的平均长度、
#计算平均宽度,
#计算平均面积、
#计算目标平均占比
importos
importxml.etree.ElementTreeasET
importnumpyasnp
#np.set_printoptions(suppress=True,threshold=np.nan)#10,000,000
np.set_printoptions(suppress=True,threshold=10000000)#10,000,000
importmatplotlib
fromPILimportImage
defparse_obj(xml_path,filename):
tree=ET.parse(xml_path+filename)
objects=[]
forobjintree.findall('object'):
obj_struct={}
obj_struct['name']=obj.find('name').text
bbox=obj.find('bndbox')
obj_struct['bbox']=[int(bbox.find('xmin').text),
int(bbox.find('ymin').text),
int(bbox.find('xmax').text),
int(bbox.find('ymax').text)]
objects.append(obj_struct)
returnobjects
defread_image(image_path,filename):
im=Image.open(image_path+filename)
W=im.size[0]
H=im.size[1]
area=W*H
im_info=[W,H,area]
returnim_info
if__name__=='__main__':
image_path='/home/dlut/网络/make_database/数据集——合集/VOCdevkit/VOC2018/JPEGImages/'
xml_path='/home/dlut/网络/make_database/数据集——合集/VOCdevkit/VOC2018/Annotations/'
filenamess=os.listdir(xml_path)
filenames=[]
fornameinfilenamess:
name=name.replace('.xml','')
filenames.append(name)
print(filenames)
recs={}
ims_info={}
obs_shape={}
classnames=[]
num_objs={}
obj_avg={}
fori,nameinenumerate(filenames):
print('正在处理{}.xml'.format(name))
recs[name]=parse_obj(xml_path,name+'.xml')
print('正在处理{}.jpg'.format(name))
ims_info[name]=read_image(image_path,name+'.jpg')
print('所有信息收集完毕。')
print('正在处理信息......')
fornameinfilenames:
im_w=ims_info[name][0]
im_h=ims_info[name][1]
im_area=ims_info[name][2]
forobjectinrecs[name]:
ifobject['name']notinnum_objs.keys():
num_objs[object['name']]=1
else:
num_objs[object['name']]+=1
#num_objs+=1
ob_w=object['bbox'][2]-object['bbox'][0]
ob_h=object['bbox'][3]-object['bbox'][1]
ob_area=ob_w*ob_h
w_rate=ob_w/im_w
h_rate=ob_h/im_h
area_rate=ob_area/im_area
ifnotobject['name']inobs_shape.keys():
obs_shape[object['name']]=([[ob_w,
ob_h,
ob_area,
w_rate,
h_rate,
area_rate]])
else:
obs_shape[object['name']].append([ob_w,
ob_h,
ob_area,
w_rate,
h_rate,
area_rate])
ifobject['name']notinclassnames:
classnames.append(object['name'])#求平均
fornameinclassnames:
obj_avg[name]=(np.array(obs_shape[name]).sum(axis=0))/num_objs[name]
print('{}的情况如下:*******\n'.format(name))
print('目标平均W={}'.format(obj_avg[name][0]))
print('目标平均H={}'.format(obj_avg[name][1]))
print('目标平均area={}'.format(obj_avg[name][2]))
print('目标平均与原图的W比例={}'.format(obj_avg[name][3]))
print('目标平均与原图的H比例={}'.format(obj_avg[name][4]))
print('目标平均原图面积占比={}\n'.format(obj_avg[name][5]))
print('信息统计计算完毕。')
3.修改xml文件中某个目标的名字为另一个名字
#修改xml文件中的目标的名字,
importos,sys
importglob
fromxml.etreeimportElementTreeasET
#批量读取Annotations下的xml文件
#per=ET.parse(r'C:\Users\rockhuang\Desktop\Annotations\000003.xml')
xml_dir=r'/home/dlut/网络/make_database/数据集——合集/VOCdevkit/VOC2018/Annotations'
xml_list=glob.glob(xml_dir+'/*.xml')
forxmlinxml_list:
print(xml)
per=ET.parse(xml)
p=per.findall('/object')
foroneperinp:#找出person节点
child=oneper.getchildren()[0]#找出person节点的子节点
ifchild.text=='PinNormal':#需要修改的名字
child.text='normalbolt'#修改成什么名字
ifchild.text=='PinDefect':#需要修改的名字
child.text='defectbolt-1'#修改成什么名字
per.write(xml)
print(child.tag,':',child.text)
以上这篇python:批量统计xml中各类目标的数量案例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。