本文为博主原创,转载请注明出处:https://blog.csdn.net/hitzijiyingcai/article/details/81636455
在利用诸如Faster R-CNN等深度学习网络进行目标检测的时候一定需要训练自己的数据集,一般有两种方法:
一般推荐第一种方法,因为第一种方法比较简单而且不容易出错,在制作为VOC2007格式的数据集之前,这里可以下载原始VOC2007数据集:VOC2007数据集,来看看这个数据集到底是什么样的:
解压VOC2007数据集后可以看到VOC2007文件夹下有以下5个文件夹:
1、Annotations
Annotations文件夹中存放的是xml格式的标签文件,每一个xml文件都对应于JPEGImages文件夹中的一张图片。xml文件的解析如下:
VOC2007
2007_000392.jpg //文件名
//图像尺寸(长宽以及通道数)
500
332
3
1 //是否用于分割(在图像物体识别中01无所谓)
2、JPEGImages
JPEGImages 内部存放了PASCAL VOC所提供的所有的图片信息,包括了训练图片和测试图片
这些图像的像素尺寸大小不一,但是横向图的尺寸大约在500*375左右,纵向图的尺寸大约在375*500左右,基本不会偏差超过100。(在之后的训练中,第一步就是将这些图片都resize到300*300或是500*500,所有原始图片不能离这个标准过远。
3、 ImageSets
ImageSets存放的是每一种类型的challenge对应的图像数据。
在这里主要考察Main文件夹。
Main文件夹下包含了每个分类的train.txt、val.txt和trainval.txt。
这些txt中的内容都差不多如下:
000005 -1
000007 -1
000009 1
000016 -1
000019 -1
前面的表示图像的name,后面的1代表正样本,-1代表负样本。
_train中存放的是训练使用的数据
_val中存放的是验证结果使用的数据
_trainval将上面两个进行了合并
需要保证的是train和val两者没有交集,也就是训练数据和验证数据不能有重复,在选取训练数据的时候 ,也应该是随机产生的。
制作自己的VOC2007格式数据集其实不需要上述那么多内容,我们只要做三个部分即可:Annotations文件夹、JPEGImages文件夹、ImageSets文件夹下的Main文件。
step1:JPEGImages
参照原始VOC2007数据集的文件层次创建上述四个文件夹,也就是创建一个VOCdevkit文件夹,下面再创建Annotations、JPEGImages、ImageSets三个文件夹,最后在ImageSets文件夹下再创建一个Main文件夹。
创建好所有文件夹后,我们将自己的数据集图片都放到JPEGImages文件夹下。按照习惯,我们将图片的名字修改为000001.jpg这种格式的(参照原始数据集图片命名规则),统一命名方法,可以参考如下代码:
MATLAB代码:
%%
%图片保存路径为:
%E:\image\car
%E:\image\person
%car和person是保存车和行人的文件夹
%这些文件夹还可以有多个,
%放在image文件夹里就行
%该代码的作用是将图片名字改成000123.jpg这种形式
%%
clc;
clear;
maindir='E:\image\';
name_long=5; %图片名字的长度,如000123.jpg为6,最多9位,可修改
num_begin=1; %图像命名开始的数字如000123.jpg开始的话就是123
subdir = dir(maindir);
n=1;
for i = 1:length(subdir)
if ~strcmp(subdir(i).name ,'.') && ~strcmp(subdir(i).name,'..')
subsubdir = dir(strcat(maindir,subdir(i).name));
for j=1:length(subsubdir)
if ~strcmp(subsubdir(j).name ,'.') && ~strcmp(subsubdir(j).name,'..')
img=imread([maindir,subdir(i).name,'\',subsubdir(j).name]);
imshow(img);
str=num2str(num_begin,'%09d');
newname=strcat(str,'.jpg');
newname=newname(end-(name_long+3):end);
system(['rename ' [maindir,subdir(i).name,'\',subsubdir(j).name] ' ' newname]);
num_begin=num_begin+1;
fprintf('当前处理文件夹%s',subdir(i).name);
fprintf('已经处理%d张图片\n',n);
n=n+1;
pause(0.1);%可以将暂停去掉
end
end
end
end
python代码:
import os
path = "E:\\image"
filelist = os.listdir(path) #该文件夹下所有的文件(包括文件夹)
count=0
for file in filelist:
print(file)
for file in filelist: #遍历所有文件
Olddir=os.path.join(path,file) #原来的文件路径
if os.path.isdir(Olddir): #如果是文件夹则跳过
continue
filename=os.path.splitext(file)[0] #文件名
filetype=os.path.splitext(file)[1] #文件扩展名
Newdir=os.path.join(path,str(count).zfill(6)+filetype) #用字符串函数zfill 以0补全所需位数
os.rename(Olddir,Newdir)#重命名
count+=1
强调两点:第一点是图片的格式,图片需是JPEG或者JPG格式,其他格式需要转换一下。第二点是图片的长宽比,图片长宽比不能太大或太小,这个参考原始VOC2007数据集图片即可。
step2:Annotations
方法一:LabelImg
制作Annotations文件夹下所需要存放的xml文件需要借助图片标注工具LabelImg,在github上有源码:https://github.com/tzutalin/labelImg。关于它的使用,本人采用的是在Linux系统下的操作,Windows系统下的操作在这里附上两个链接需要的自行点开https://blog.csdn.net/zhyj3038/article/details/54923781/,https://blog.csdn.net/jesse_mx/article/details/53606897,而在Linux系统操作如下:
由于Ubuntu系统自带python,这款软件在Ubuntu环境下的安装是最方便的。软件要求python版本在2.6以上,同时需要PyQt和lxml的支持。
sudo apt-get install pyqt4-dev-tools #安装PyQt4
sudo pip install lxml #安装lxml,如果报错,可以试试下面语句
sudo apt-get install python-lxml
接下来位下载github上的安装包,下载地址为https://github.com/tzutalin/labelImg,也可通过以下代码直接获取:
git clone https://github.com/tzutalin/labelImg.git
下载后进入下载目录,copy到home目录下解压,解压后进入目录:
cd labelImg
pyrcc4 -o resources.py resources.qrc
python labelImg.py
即可打开界面:
此软件的使用方法
修改默认的XML文件保存位置,使用快捷键“Ctrl+R”,改为自定义位置,这里的路径一定不能包含中文,否则无法保存。
源码文件夹中使用notepad++打开data/predefined_classes.txt,修改默认类别,比如改成person、car、motorcycle三个类别。
“Open Dir”打开图片文件夹,选择第一张图片开始进行标注,使用“Create RectBox”或者“Ctrl+N”开始画框,单击结束画框,再双击选择类别。完成一张图片后点击“Save”保存,此时XML文件已经保存到本地了。点击“Next Image”转到下一张图片。
标注过程中可随时返回进行修改,后保存的文件会覆盖之前的。
完成标注后打开XML文件,发现确实和PASCAL VOC所用格式一样。
说明:每标注完一张图片后进行保存,保存的xml文件名要与对应图片名一致,大家可以参考原始VOC2007数据集中JPEGImages文件夹下图片的命名和Annotations文件夹中的xml文件命名规则。
方法二:BBox-Label-Tool
进行数据标注的另一个工具即为BBox-Label-Tool,此工具需要在python2.7下运行,且必须安装PIL等包,可在github上下载源码https://github.com/puzzledqs/BBox-Label-Tool,该工具生成的标签格式是:
classname类别名 x2min y2min x2max y2max
下载完成后里面有一个main.py文件,但是直接运行会有一定的问题,以下为修改过的代码:
from __future__ import division
from Tkinter import *
import tkMessageBox
from PIL import Image, ImageTk
import os
import glob
import random
# colors for the bboxes
COLORS = ['red', 'blue', 'yellow', 'pink', 'cyan', 'green', 'black']
# image sizes for the examples
SIZE = 256, 256
classLabels = ['person', 'car', 'bike', 'motorcycle', 'truck', 'cyclist']
class LabelTool():
def __init__(self, master):
# set up the main frame
self.parent = master
self.parent.title("LabelTool")
self.frame = Frame(self.parent)
self.frame.pack(fill=BOTH, expand=1)
self.parent.resizable(width=False, height=False)
# initialize global state
self.imageDir = ''
self.imageList = []
self.egDir = ''
self.egList = []
self.outDir = ''
self.cur = 0
self.total = 0
self.category = 0
self.imagename = ''
self.labelfilename = ''
self.tkimg = None
# initialize mouse state
self.STATE = {}
self.STATE['click'] = 0
self.STATE['x'], self.STATE['y'] = 0, 0
# reference to bbox
self.bboxIdList = []
self.bboxId = None
self.bboxList = []
self.hl = None
self.vl = None
self.currentClass = ''
# ----------------- GUI stuff ---------------------
# dir entry & load
self.label = Label(self.frame, text="Image Dir:")
self.label.grid(row=0, column=0, sticky=E)
self.entry = Entry(self.frame)
self.entry.grid(row=0, column=1, sticky=W + E)
self.ldBtn = Button(self.frame, text="Load", command=self.loadDir)
self.ldBtn.grid(row=0, column=2, sticky=W + E)
# main panel for labeling
self.mainPanel = Canvas(self.frame, cursor='tcross')
self.mainPanel.bind("", self.mouseClick)
self.mainPanel.bind("", self.mouseMove)
self.parent.bind("", self.cancelBBox) # press to cancel current bbox
self.parent.bind("s", self.cancelBBox)
self.parent.bind("a", self.prevImage) # press 'a' to go backforward
self.parent.bind("d", self.nextImage) # press 'd' to go forward
self.mainPanel.grid(row=1, column=1, rowspan=4, sticky=W + N)
# showing bbox info & delete bbox
self.lb1 = Label(self.frame, text='Bounding boxes:')
self.lb1.grid(row=1, column=2, sticky=W + N)
self.listbox = Listbox(self.frame, width=22, height=12)
self.listbox.grid(row=2, column=2, sticky=N)
self.btnDel = Button(self.frame, text='Delete', command=self.delBBox)
self.btnDel.grid(row=3, column=2, sticky=W + E + N)
self.btnClear = Button(self.frame, text='ClearAll', command=self.clearBBox)
self.btnClear.grid(row=4, column=2, sticky=W + E + N)
# select class type
self.classPanel = Frame(self.frame)
self.classPanel.grid(row=5, column=1, columnspan=10, sticky=W + E)
label = Label(self.classPanel, text='class:')
label.grid(row=5, column=1, sticky=W + N)
self.classbox = Listbox(self.classPanel, width=4, height=2)
self.classbox.grid(row=5, column=2)
for each in range(len(classLabels)):
function = 'select' + classLabels[each]
print
classLabels[each]
btnMat = Button(self.classPanel, text=classLabels[each], command=getattr(self, function))
btnMat.grid(row=5, column=each + 3)
# control panel for image navigation
self.ctrPanel = Frame(self.frame)
self.ctrPanel.grid(row=6, column=1, columnspan=2, sticky=W + E)
self.prevBtn = Button(self.ctrPanel, text='<< Prev', width=10, command=self.prevImage)
self.prevBtn.pack(side=LEFT, padx=5, pady=3)
self.nextBtn = Button(self.ctrPanel, text='Next >>', width=10, command=self.nextImage)
self.nextBtn.pack(side=LEFT, padx=5, pady=3)
self.progLabel = Label(self.ctrPanel, text="Progress: / ")
self.progLabel.pack(side=LEFT, padx=5)
self.tmpLabel = Label(self.ctrPanel, text="Go to Image No.")
self.tmpLabel.pack(side=LEFT, padx=5)
self.idxEntry = Entry(self.ctrPanel, width=5)
self.idxEntry.pack(side=LEFT)
self.goBtn = Button(self.ctrPanel, text='Go', command=self.gotoImage)
self.goBtn.pack(side=LEFT)
# example pannel for illustration
self.egPanel = Frame(self.frame, border=10)
self.egPanel.grid(row=1, column=0, rowspan=5, sticky=N)
self.tmpLabel2 = Label(self.egPanel, text="Examples:")
self.tmpLabel2.pack(side=TOP, pady=5)
self.egLabels = []
for i in range(3):
self.egLabels.append(Label(self.egPanel))
self.egLabels[-1].pack(side=TOP)
# display mouse position
self.disp = Label(self.ctrPanel, text='')
self.disp.pack(side=RIGHT)
self.frame.columnconfigure(1, weight=1)
self.frame.rowconfigure(10, weight=1)
# for debugging
## self.setImage()
## self.loadDir()
def loadDir(self, dbg=False):
if not dbg:
s = self.entry.get()
self.parent.focus()
self.category = int(s)
else:
s = r'D:\workspace\python\labelGUI'
## if not os.path.isdir(s):
## tkMessageBox.showerror("Error!", message = "The specified dir doesn't exist!")
## return
# get image list
self.imageDir = os.path.join(r'./Images', '%d' % (self.category))
self.imageList = glob.glob(os.path.join(self.imageDir, '*.png'))
if len(self.imageList) == 0:
print('No .PNG images found in the specified dir!')
return
# set up output dir
self.outDir = os.path.join(r'./Labels', '%d' % (self.category))
if not os.path.exists(self.outDir):
os.mkdir(self.outDir)
labeledPicList = glob.glob(os.path.join(self.outDir, '*.txt'))
for label in labeledPicList:
data = open(label, 'r')
if '0\n' == data.read():
data.close()
continue
data.close()
picture = label.replace('Labels', 'Images').replace('.txt', '.png')
if picture in self.imageList:
self.imageList.remove(picture)
# default to the 1st image in the collection
self.cur = 1
self.total = len(self.imageList)
self.loadImage()
print('%d images loaded from %s' % (self.total, s))
def loadImage(self):
# load image
imagepath = self.imageList[self.cur - 1]
self.img = Image.open(imagepath)
self.imgSize = self.img.size
self.tkimg = ImageTk.PhotoImage(self.img)
self.mainPanel.config(width=max(self.tkimg.width(), 400), height=max(self.tkimg.height(), 400))
self.mainPanel.create_image(0, 0, image=self.tkimg, anchor=NW)
self.progLabel.config(text="%04d/%04d" % (self.cur, self.total))
# load labels
self.clearBBox()
self.imagename = os.path.split(imagepath)[-1].split('.')[0]
labelname = self.imagename + '.txt'
self.labelfilename = os.path.join(self.outDir, labelname)
bbox_cnt = 0
if os.path.exists(self.labelfilename):
with open(self.labelfilename) as f:
for (i, line) in enumerate(f):
if i == 0:
bbox_cnt = int(line.strip())
continue
tmp = [int(t.strip()) for t in line.split()]
## print tmp
self.bboxList.append(tuple(tmp))
tmpId = self.mainPanel.create_rectangle(tmp[0], tmp[1], \
tmp[2], tmp[3], \
width=2, \
outline=COLORS[(len(self.bboxList) - 1) % len(COLORS)])
self.bboxIdList.append(tmpId)
self.listbox.insert(END, '(%d, %d) -> (%d, %d)' % (tmp[0], tmp[1], tmp[2], tmp[3]))
self.listbox.itemconfig(len(self.bboxIdList) - 1,
fg=COLORS[(len(self.bboxIdList) - 1) % len(COLORS)])
def saveImage(self):
with open(self.labelfilename, 'w') as f:
f.write('%d\n' % len(self.bboxList))
for bbox in self.bboxList:
f.write(' '.join(map(str, bbox)) + '\n')
print('Image No. %d saved' % (self.cur))
def mouseClick(self, event):
if self.STATE['click'] == 0:
self.STATE['x'], self.STATE['y'] = event.x, event.y
# self.STATE['x'], self.STATE['y'] = self.imgSize[0], self.imgSize[1]
else:
x1, x2 = min(self.STATE['x'], event.x), max(self.STATE['x'], event.x)
y1, y2 = min(self.STATE['y'], event.y), max(self.STATE['y'], event.y)
if x2 > self.imgSize[0]:
x2 = self.imgSize[0]
if y2 > self.imgSize[1]:
y2 = self.imgSize[1]
self.bboxList.append((self.currentClass, x1, y1, x2, y2))
self.bboxIdList.append(self.bboxId)
self.bboxId = None
self.listbox.insert(END, '(%d, %d) -> (%d, %d)' % (x1, y1, x2, y2))
self.listbox.itemconfig(len(self.bboxIdList) - 1, fg=COLORS[(len(self.bboxIdList) - 1) % len(COLORS)])
self.STATE['click'] = 1 - self.STATE['click']
def mouseMove(self, event):
self.disp.config(text='x: %d, y: %d' % (event.x, event.y))
if self.tkimg:
if self.hl:
self.mainPanel.delete(self.hl)
self.hl = self.mainPanel.create_line(0, event.y, self.tkimg.width(), event.y, width=2)
if self.vl:
self.mainPanel.delete(self.vl)
self.vl = self.mainPanel.create_line(event.x, 0, event.x, self.tkimg.height(), width=2)
if 1 == self.STATE['click']:
if self.bboxId:
self.mainPanel.delete(self.bboxId)
self.bboxId = self.mainPanel.create_rectangle(self.STATE['x'], self.STATE['y'], \
event.x, event.y, \
width=2, \
outline=COLORS[len(self.bboxList) % len(COLORS)])
def cancelBBox(self, event):
if 1 == self.STATE['click']:
if self.bboxId:
self.mainPanel.delete(self.bboxId)
self.bboxId = None
self.STATE['click'] = 0
def delBBox(self):
sel = self.listbox.curselection()
if len(sel) != 1:
return
idx = int(sel[0])
self.mainPanel.delete(self.bboxIdList[idx])
self.bboxIdList.pop(idx)
self.bboxList.pop(idx)
self.listbox.delete(idx)
def clearBBox(self):
for idx in range(len(self.bboxIdList)):
self.mainPanel.delete(self.bboxIdList[idx])
self.listbox.delete(0, len(self.bboxList))
self.bboxIdList = []
self.bboxList = []
def selectperson(self):
self.currentClass = 'person'
self.classbox.delete(0, END)
self.classbox.insert(0, 'person')
self.classbox.itemconfig(0, fg=COLORS[0])
def selectcar(self):
self.currentClass = 'car'
self.classbox.delete(0, END)
self.classbox.insert(0, 'car')
self.classbox.itemconfig(0, fg=COLORS[0])
def selectbike(self):
self.currentClass = 'bike'
self.classbox.delete(0, END)
self.classbox.insert(0, 'bike')
self.classbox.itemconfig(0, fg=COLORS[0])
def selectmotorcycle(self):
self.currentClass = 'motorcycle'
self.classbox.delete(0, END)
self.classbox.insert(0, 'motorcycle')
self.classbox.itemconfig(0, fg=COLORS[0])
def selecttruck(self):
self.currentClass = 'truck'
self.classbox.delete(0, END)
self.classbox.insert(0, 'truck')
self.classbox.itemconfig(0, fg=COLORS[0])
def selectcyclist(self):
self.currentClass = 'cyclist'
self.classbox.delete(0, END)
self.classbox.insert(0, 'cyclist')
self.classbox.itemconfig(0, fg=COLORS[0])
def prevImage(self, event=None):
self.saveImage()
if self.cur > 1:
self.cur -= 1
self.loadImage()
def nextImage(self, event=None):
self.saveImage()
if self.cur < self.total:
self.cur += 1
self.loadImage()
def gotoImage(self):
idx = int(self.idxEntry.get())
if 1 <= idx and idx <= self.total:
self.saveImage()
self.cur = idx
self.loadImage()
if __name__ == '__main__':
root = Tk()
tool = LabelTool(root)
root.mainloop()
main.py
使用方法:
(1) 在BBox-Label-Tool/Images目录下创建保存图片的目录, 目录以数字命名(BBox-Label-Tool/Images/1), 然后将待标注的图片copy到1这个目录下;
(2) 在BBox-Label-Tool目录下执行命令 python main.py
(3) 在工具界面上, Image Dir 框中输入需要标记的目录名(比如 1), 然后点击load按钮, 工具自动将Images/1目录下的图片加载进来;需要说明一下, 如果目录中的图片已经标注过,点击load时不会被重新加载进来.
(4) 该工具支持多类别标注, 画bounding boxs框标定之前,需要先选定类别,然后再画框.
(5) 一张图片标注完后, 点击Next>>按钮, 标注下一张图片, 图片label成功后,会在BBox-Label-Tool/Labels对应的目录下生成与图片文件名对应的label文件.
使用界面如图所示:
以上步骤生成的是txt文件,接下来要做的是将此label转换成VOC数据格式
BBox-Label-Tool工具标注好的bounding box坐标文件转换成VOC数据格式的形式,转换过程包括了两个步骤:
(1)将BBox-Label-Tool下的txt格式保存的bounding box信息转换成VOC数据格式下以xml方式表示;
(2)生成用于训练的数据集和用于测试的数据集。
首先建立一个VOC2007文件夹,在其下面建立JPEGImages,Annotations,label文件夹,将前面生成的所有txt文件转放到label文件夹下,并将所有的图片转移到JPEGImages文件夹下。
建立一个**.py文件,完成txt到xml转换的脚本,放到和label文件夹同一目录下,执行脚本Python **.py,生成xml,此py文件代码如下:
import os
import sys
import cv2
from itertools import islice
from xml.dom.minidom import Document
labels = 'label'
imgpath = 'JPEGImages/'
xmlpath_new = 'Annotations/'
foldername = 'VOC2007'
def insertObject(doc, datas):
obj = doc.createElement('object')
name = doc.createElement('name')
name.appendChild(doc.createTextNode(datas[0]))
obj.appendChild(name)
pose = doc.createElement('pose')
pose.appendChild(doc.createTextNode('Unspecified'))
obj.appendChild(pose)
truncated = doc.createElement('truncated')
truncated.appendChild(doc.createTextNode(str(0)))
obj.appendChild(truncated)
difficult = doc.createElement('difficult')
difficult.appendChild(doc.createTextNode(str(0)))
obj.appendChild(difficult)
bndbox = doc.createElement('bndbox')
xmin = doc.createElement('xmin')
xmin.appendChild(doc.createTextNode(str(datas[1])))
bndbox.appendChild(xmin)
ymin = doc.createElement('ymin')
ymin.appendChild(doc.createTextNode(str(datas[2])))
bndbox.appendChild(ymin)
xmax = doc.createElement('xmax')
xmax.appendChild(doc.createTextNode(str(datas[3])))
bndbox.appendChild(xmax)
ymax = doc.createElement('ymax')
if '\r' == str(datas[4])[-1] or '\n' == str(datas[4])[-1]:
data = str(datas[4])[0:-1]
else:
data = str(datas[4])
ymax.appendChild(doc.createTextNode(data))
bndbox.appendChild(ymax)
obj.appendChild(bndbox)
return obj
def create():
for walk in os.walk(labels):
for each in walk[2]:
fidin = open(walk[0] + '/' + each, 'r')
objIndex = 0
for data in islice(fidin, 1, None):
objIndex += 1
data = data.strip('\n')
datas = data.split(' ')
if 5 != len(datas):
print 'bounding box information error'
continue
pictureName = each.replace('.txt', '.jpg')
imageFile = imgpath + pictureName
img = cv2.imread(imageFile)
imgSize = img.shape
if 1 == objIndex:
xmlName = each.replace('.txt', '.xml')
f = open(xmlpath_new + xmlName, "w")
doc = Document()
annotation = doc.createElement('annotation')
doc.appendChild(annotation)
folder = doc.createElement('folder')
folder.appendChild(doc.createTextNode(foldername))
annotation.appendChild(folder)
filename = doc.createElement('filename')
filename.appendChild(doc.createTextNode(pictureName))
annotation.appendChild(filename)
source = doc.createElement('source')
database = doc.createElement('database')
database.appendChild(doc.createTextNode('My Database'))
source.appendChild(database)
source_annotation = doc.createElement('annotation')
source_annotation.appendChild(doc.createTextNode(foldername))
source.appendChild(source_annotation)
image = doc.createElement('image')
image.appendChild(doc.createTextNode('flickr'))
source.appendChild(image)
flickrid = doc.createElement('flickrid')
flickrid.appendChild(doc.createTextNode('NULL'))
source.appendChild(flickrid)
annotation.appendChild(source)
owner = doc.createElement('owner')
flickrid = doc.createElement('flickrid')
flickrid.appendChild(doc.createTextNode('NULL'))
owner.appendChild(flickrid)
name = doc.createElement('name')
name.appendChild(doc.createTextNode('idaneel'))
owner.appendChild(name)
annotation.appendChild(owner)
size = doc.createElement('size')
width = doc.createElement('width')
width.appendChild(doc.createTextNode(str(imgSize[1])))
size.appendChild(width)
height = doc.createElement('height')
height.appendChild(doc.createTextNode(str(imgSize[0])))
size.appendChild(height)
depth = doc.createElement('depth')
depth.appendChild(doc.createTextNode(str(imgSize[2])))
size.appendChild(depth)
annotation.appendChild(size)
segmented = doc.createElement('segmented')
segmented.appendChild(doc.createTextNode(str(0)))
annotation.appendChild(segmented)
annotation.appendChild(insertObject(doc, datas))
else:
annotation.appendChild(insertObject(doc, datas))
try:
f.write(doc.toprettyxml(indent=' '))
f.close()
fidin.close()
except:
pass
if __name__ == '__main__':
create()
NB:除了这两种方法,网上还有另一种适用于Windows系统的方法,大家根据需要自行查看:https://blog.csdn.net/sinat_30071459/article/details/50723212
step3:ImageSets
接下来为制作ImageSets文件夹下Main文件夹中的4个文件(test.txt、train.txt、trainval.txt、val.txt)。
首先说明一下这四个文件到底是干什么用的:
test.txt:测试集
train.txt:训练集
val.txt:验证集
trainval.txt:训练和验证集
在原始VOC2007数据集中,trainval大约占整个数据集的50%,test大约为整个数据集的50%;train大约是trainval的50%,val大约为trainval的50%。所以我们可参考以下代码来生成这4个txt文件:
import os
import random
trainval_percent = 0.5
train_percent = 0.5
xmlfilepath = '/home/hqd/桌面/VOC2010/Annotations'
txtsavepath = '/home/hqd/桌面/VOC2010/ImageSets/Main'
total_xml = os.listdir(xmlfilepath)
num=len(total_xml)
list=range(num)
tv=int(num*trainval_percent)
tr=int(tv*train_percent)
trainval= random.sample(list,tv)
train=random.sample(trainval,tr)
ftrainval = open(txtsavepath+'/trainval.txt', 'w')
ftest = open(txtsavepath+'/test.txt', 'w')
ftrain = open(txtsavepath+'/train.txt', 'w')
fval = open(txtsavepath+'/val.txt', 'w')
for i in list:
name=total_xml[i][:-4]+'\n'
if i in trainval:
ftrainval.write(name)
if i in train:
ftrain.write(name)
else:
fval.write(name)
else:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest .close()
注意:上述代码中涉及到的路径要写全,另外各个数据集所占比例根据实际数据集的大小调整比例。
至此,我们自己的VOC2007格式数据集就全部制作完成了。
NB:本人在网上还看到另一个教程是关于制作数据集的,但是本人实践的时候遇到了一些问题导致没有运行成功,在这里附上链接https://blog.csdn.net/Best_Coder/article/details/76577544?locationNum=8&fps=1,希望实践成功的小伙伴前来评论指导。