python对目标检测数据集xml的操作(统计目标,数量和面比例)

1. 根据xml文件统计目标种类以及数量

import os
import xml.etree.ElementTree as ET
import numpy as np

# np.set_printoptions(suppress=True, threshold=np.nan)
import matplotlib
from PIL import Image


def parse_obj(xml_path, filename):
    tree = ET.parse(xml_path + filename)
    objects = []
    for obj in tree.findall('object'):
        obj_struct = {}
        obj_struct['name'] = obj.find('name').text
        objects.append(obj_struct)
    return objects


def read_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]
    return im_info


if __name__ == '__main__':
    xml_path = 'C:/Users/YANG/Music/VOC2007/Annotations/'
    filenamess = os.listdir(xml_path)
    filenames = []
    for name in filenamess:
        name = name.replace('.xml', '')
        filenames.append(name)
    recs = {}
    obs_shape = {}
    classnames = []
    num_objs = {}
    obj_avg = {}
    for i, name in enumerate(filenames):
        recs[name] = parse_obj(xml_path, name + '.xml')
    for name in filenames:
        for object in recs[name]:
            if object['name'] not in num_objs.keys():
                num_objs[object['name']] = 1
            else:
                num_objs[object['name']] += 1
            if object['name'] not in classnames:
                classnames.append(object['name'])
    for name in classnames:
        print('{}:{}个'.format(name, num_objs[name]))
    print('信息统计算完毕。')

运行结果

 2.根据xml文件统计目标的平均长度、宽度、面积以及每一个目标在原图中的占比

# -*- coding:utf-8 -*-
#统计
# 计算每一个目标在原图中的占比
# 计算目标的平均长度、
# 计算平均宽度,
# 计算平均面积、
# 计算目标平均占比

import os
import xml.etree.ElementTree as ET
import numpy as np

#np.set_printoptions(suppress=True, threshold=np.nan)  #10,000,000
np.set_printoptions(suppress=True, threshold=10000000)  #10,000,000
import matplotlib
from PIL import Image


def parse_obj(xml_path, filename):
    tree = ET.parse(xml_path + filename)
    objects = []
    for obj in tree.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)
    return objects


def read_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]
    return im_info


if __name__ == '__main__':
    image_path = 'C:/Users/YANG/Music/VOC2007/JPEGImages/'
    xml_path = 'C:/Users/YANG/Music/VOC2007/Annotations/'
    filenamess = os.listdir(xml_path)
    filenames = []
    for name in filenamess:
        name = name.replace('.xml', '')
        filenames.append(name)
    print(filenames)
    recs = {}
    ims_info = {}
    obs_shape = {}
    classnames = []
    num_objs={}
    obj_avg = {}
    for i, name in enumerate(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('正在处理信息......')
    for name in filenames:
        im_w = ims_info[name][0]
        im_h = ims_info[name][1]
        im_area = ims_info[name][2]
        for object in recs[name]:
            if object['name'] not in num_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
            if not object['name'] in obs_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])
        if object['name'] not in classnames:
            classnames.append(object['name'])  # 求平均

    for name in classnames:
        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('信息统计计算完毕。')

运行结果如下:

boat的情况如下:*******

  目标平均W=138.7462311557789
  目标平均H=105.48492462311557
  目标平均area=22384.846733668342
  目标平均与原图的W比例=0.28784839249474414
  目标平均与原图的H比例=0.28109636957063827
  目标平均原图面积占比=0.1229097790335352

motorbike的情况如下:*******

  目标平均W=203.0897435897436
  目标平均H=173.74871794871794
  目标平均area=46472.610256410255
  目标平均与原图的W比例=0.4243023316192677
  目标平均与原图的H比例=0.4664647248080359
  目标平均原图面积占比=0.2580258915758285

sofa的情况如下:*******

  目标平均W=284.4964705882353
  目标平均H=192.21411764705883
  目标平均area=63344.17411764706
  目标平均与原图的W比例=0.5975485795482032
  目标平均与原图的H比例=0.514883583915708
  目标平均原图面积占比=0.3556410300606695

sheep的情况如下:*******

  目标平均W=98.98866855524079
  目标平均H=95.05949008498584
  目标平均area=17852.827195467424
  目标平均与原图的W比例=0.20368722580568308
  目标平均与原图的H比例=0.2523693147421427
  目标平均原图面积占比=0.09659868069093198

bus的情况如下:*******

  目标平均W=210.4375
  目标平均H=150.4264705882353
  目标平均area=41728.61397058824
  目标平均与原图的W比例=0.43593299844318156
  目标平均与原图的H比例=0.4061223576740076
  目标平均原图面积占比=0.23529310482617666

bottle的情况如下:*******

  目标平均W=46.34384858044164
  目标平均H=106.68769716088327
  目标平均area=8431.548895899054
  目标平均与原图的W比例=0.10391077558742272
  目标平均与原图的H比例=0.2715329651881007
  目标平均原图面积占比=0.0482003828648926

cow的情况如下:*******

  目标平均W=136.68258426966293
  目标平均H=134.2865168539326
  目标平均area=27112.78370786517
  目标平均与原图的W比例=0.28553066725597426
  目标平均与原图的H比例=0.3664002135560225
  目标平均原图面积占比=0.15297752687191007

信息统计计算完毕。

Process finished with exit code 0

3.修改xml文件中某个目标的名字为另一个名字

#修改xml文件中的目标的名字,
import os, sys
import glob
from xml.etree import ElementTree as ET

# 批量读取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')
for xml in xml_list:
    print(xml)
    per = ET.parse(xml)
    p = per.findall('/object')

    for oneper in p:  # 找出person节点
        child = oneper.getchildren()[0]  # 找出person节点的子节点
        if child.text == 'PinNormal':   #需要修改的名字
            child.text = 'normal bolt'    #修改成什么名字
        if child.text == 'PinDefect':    #需要修改的名字
            child.text = 'defect bolt-1'   #修改成什么名字

    per.write(xml)
    print(child.tag, ':', child.text)

 

版权声明:本文为CSDN博主「Vertira」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Vertira/article/details/121792075

Vertira

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

YOLOX笔记

目录 1. 样本匹配 正负样本划分过程 2. yoloxwarmcos 学习率 3. 无法开启多gpu训练, 或者多gpu训练卡住? 1. 样本匹配 正负样本划分过程 说明: gt_centerbbox是在gt_bbox中心点向四周

yolox 训练问题记录

如果是训练自己的数据,建议按以下几步检查一下问题: pull最新的代码,我们已经在coco数据集上完整验证过,所以还有问题的话可以排除训练代码的问题;检测你的数据集和标注&#