YOLOv3代码详解之创建数据集

本文介绍如何使用LabelImg工具进行图片标注,创建VOC数据集,并通过Python脚本生成训练集、测试集文件名。同时,演示了如何利用voc_annotation.py生成包含图片路径及标注信息的文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、创建数据集
        通常我们文件的存储格式,都会按照VOC数据集的那种格式,如下:
在这里插入图片描述
        其中的JPEGImages文件夹用来存放图片,Annotations文件夹用来存放标注文件,图片的文件名和标注文件的文件名是一样的,ImageSets中的Main文件夹用来存放训练集、测试集的文件名。下面就介绍如何产生标注文件,通过使用LabelImg进行图片的标注。
        使用LabelImg进行标注非常方便,下面就对一张图片的标注进行演示:
在这里插入图片描述

        标注完成之后,在Annotations文件夹下就产生了相应的标注文件.xml,下面就通过代码来产生ImageSets中的Main文件夹中的训练集、测试集文件名文件:

voc2yolo3.py:

import os
import random

# Annotations文件夹路径
xmlfilepath = "E:/Desktop/detection/keras/yolo3-keras-master/VOCdevkit/VOC2007/Annotations"
# ImageSets中的Main文件夹路径
saveBasePath = "E:/Desktop/detection/keras/yolo3-keras-master/VOCdevkit/VOC2007/ImageSets/Main/"

# 用来调整train、trainval两个文件里的样本的个数
trainval_precent = 1
train_precent = 1

# 读取Annotations文件夹所有文件的文件名
temp_xml = os.listdir(xmlfilepath)
# 用来保存xml文件的文件名
total_xml = []
for xml in temp_xml:
	if xml.endswith(".xml"):  # 判断文件名是不是以.xml结尾
		total_xml.append(xml)
# 一共有多少个xml文件
num = len(total_xml)

# 0-num-1:每个数字代表一个xml文件
list = range(num)

tv = int(num*trainval_precent)
tr = int(tv*train_precent)

# 在list当中随机的取出tv个样本,放到trainval中
trainval = random.sample(list, tv)
# 在trainval当中随机的取出tr个样本,放到train中
train = random.sample(trainval, tr)

# 打印trainval、train当中有多少个样本
print("trainval size:", len(trainval))
print("train size:", len(train))

# 在ImageSets中的Main文件夹下创建四个txt文件:trainval、test、train、val
ftrainval = open(os.path.join(saveBasePath, 'trainval.txt'), 'w')
ftest = open(os.path.join(saveBasePath, 'test.txt'), 'w')
ftrain = open(os.path.join(saveBasePath, 'train.txt'), 'w')
fval = open(os.path.join(saveBasePath,  'val.txt'), 'w')

# 这里的i肯定都是在trainval、train当中,所以trainval、train这两个文件会存储所有的xml文件名,而test和val文件里是空的
for i in list:
    name = total_xml[i][:-4]+'\n'  # 去掉.xml后缀,一行存一个xml文件名
    if i in trainval:  # 判断是不是在trainval列表当中
        ftrainval.write(name)  
        if i in train:  # 判断是不是在train列表当中
            ftrain.write(name)  
        else:  
            fval.write(name)  
    else:  
        ftest.write(name)  
        
ftrainval.close()  
ftrain.close()  
fval.close()  
ftest .close()

        通过voc2yolo3.py就可以产生ImageSets中的Main文件夹中的训练集、测试集文件名,上述代码会产生test.txt、train.txt、trainval.txt、val.txt四个文件,其中的test和val是空的,是由于这两个变量trainval_precent = 1、train_precent = 1导致的,如果想要他们中也包含样本,可对上述代码做一点小改动即可。
        之后,我们需要通过调用voc_annotation.py来产生包含图片路径以及标注信息的文件2007_train.txt:

import xml.etree.ElementTree as ET
from os import getcwd

sets = [('2007', 'train'), ('2007', 'val'), ('2007', 'test')]

# 所使用的数据集的分类种类,必须和你的数据集一致
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]

def convert_annotation(year, image_id, list_file):
    # 打开图片对应的标注文件
    in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))

    tree = ET.parse(in_file)
    root = tree.getroot()

    for obj in root.iter('object'):
        difficult = obj.find('difficult').text  # difficult表示的是物体是否难以识别
        cls = obj.find('name').text  # 这个物体的名字
        # 判断这个物体是不是在分类当中,如果不在或者难以识别,就跳过
        if cls not in classes or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)  # 获得这个物体对应的种类的标签,比如bird--》2
        xmlbox = obj.find('bndbox')  # 获得这个物体的标注的位置信息,左上角、右下角
        # 将位置信息提取出来
        b = (int(float((xmlbox.find('xmin').text))), int(float(xmlbox.find('ymin').text)), int(float(xmlbox.find('xmax').text)), int(float(xmlbox.find('ymax').text)))
        # 把位置信息和类别,写入文件当中
        list_file.write(" " + ",".join([str(a) for a in b]) + ',' + str(cls_id))

# 当前工作目录的路径
wd = getcwd()

# sets = [('2007', 'train'), ('2007', 'val'), ('2007', 'test')]
for year, image_set in sets:
    # 打开VOCdevkit/VOC2007/ImageSets/Main/train.txt
    # .strip()用于删除字符串头尾指定的字符(默认为空格或换行符)或字符序列
    # .split()通过指定分隔符对字符串进行分割,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等
    # 得到包含所有文件名的字符串列表
    image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()

    # 创建一个文件:2007_train.txt
    list_file = open('%s_%s.txt'%(year, image_set), 'w')

    for image_id in image_ids:
        # 把图片的完整路径,保存到这个文件中
        list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg'%(wd, year, image_id))
        convert_annotation(year, image_id, list_file)
        # 写完一张图片,就换行
        list_file.write('\n')
    list_file.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值