【目标检测实用脚本系列】将labelImg标注的xml标签,按标签名建立文件夹,并将对应的裁切小图保存到文件夹中
目标检测中数据是至关重要的一个环节,使用当前脚本可以快捷的将已经标注好的xml标签,按标签名切分成图像以便查验,切出来的标签图片如下:
脚本如下,只需要将第46、48、50行路径改为自己的路径即可:
import cv2
import xml.etree.ElementTree as ET
import os
import glob
from tqdm import tqdm
import shutil
def count_num(indir):
label_list = []
# 提取xml文件列表
os.chdir(indir)
annotations = os.listdir('.')
annotations = glob.glob(str(annotations) + '*.xml')
# 新建字典,用于存放各类标签名及其对应的数目
dict = {
}
# 遍历xml文件
for i, file in enumerate(annotations):
# actual parsing
in_file = open(file, encoding='utf-8')
tree = ET.parse(in_file)
root = tree.getroot()
# 遍历文件的所有标签
for obj in root.iter('object'):
name = obj.find('name').text
if (name in dict.keys()):
# 如果标签不是第一次出现,则+1
dict[name] += 1
else:
# 如果标签是第一次出现,则将该标签名对应的value初始化为1
dict[name] = 1
# 打印结果
print("各类标签的数量分别为:")
for key in dict.keys():
print(key + ': ' + str(dict[key]))
label_list.append(key)
print("标签类别如下:")
print(label_list)
return label_list
if __name__ == '__main__':
# 原始图片路径
img_path = '/home/lzj/fall_dataset/JPEGImages'
# 原始标签路径
xml_path = '/home/lzj/fall_dataset/Annotations'
# 待存放新图片的路径
obj_img_path = '/home/lzj/fall_dataset/cut_xml'
# 调用函数统计各类标签数目
label_list = count_num(xml_path)
# 判断所在目录下是否有该文件名的文件夹
if not os.path.exists(obj_img_path):
os.makedirs(obj_img_path)
print(f"已经创建文件夹{
obj_img_path}")
# 新建以标签名字命名的文件夹
for label in label_list:
new_label_path = os.path.join(obj_img_path, label)
if not os.path.exists(new_label_path):
os.makedirs(new_label_path)
print(f"已经创建文件夹{
new_label_path}")
# 遍历图片文件夹
for img_file in tqdm(os.listdir(img_path)):
# 判断文件是否为图片格式
if img_file[-4:] in ['.png', '.jpg', '.bmp', '.jpeg']:
# 将图片路径与图片名进行拼接
img_filename = os.path.join(img_path, img_file)
# 读取图片
img_cv = cv2.imread(img_filename)
# 分割出图片名,如“000.png” 图片名为“000”
img_name = (os.path.splitext(img_file)[0])
# 利用标签路径、图片名、xml后缀拼接出完整的标签路径名
xml_name = os.path.join(xml_path, ('%s.xml' % img_name))
# 判断与图片同名的标签是否存在,因为图片不一定每张都打标
if os.path.exists(xml_name):
# 利用ET读取xml文件
root = ET.parse(xml_name).getroot()
# 目标框个数统计,防止目标文件覆盖
count = 0
# 遍历所有目标框
for obj in root.iter('object'):
# 获取目标框名称,即label名
name = obj.find('name').text
# 找到框目标
xmlbox = obj.find('bndbox')
# 将框目标的四个顶点坐标取出
x0 = xmlbox.find('xmin').text
y0 = xmlbox.find('ymin').text
x1 = xmlbox.find('xmax').text
y1 = xmlbox.find('ymax').text
# 把对应标签存放到指定的目录下
now_path = os.path.join(obj_img_path, name)
# cv2裁剪出目标框中的图片
obj_img = img_cv[int(y0):int(y1), int(x0):int(x1)]
# 保存裁剪图片
cv2.imwrite(os.path.join(now_path, ('%s_%s' % (img_name, count) + '.jpg')), obj_img)
count += 1 # 目标框统计值自增1
运行后的结果如下: