一、创建数据集
通常我们文件的存储格式,都会按照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()
本文介绍如何使用LabelImg工具进行图片标注,创建VOC数据集,并通过Python脚本生成训练集、测试集文件名。同时,演示了如何利用voc_annotation.py生成包含图片路径及标注信息的文件。

641

被折叠的 条评论
为什么被折叠?



