一、VOC2007介绍
在利用诸如Faster R-CNN等深度学习网络进行目标检测的时候一定需要训练自己的数据集,一般有两种方法:
- 按照VOC2007的格式修改自己的数据格式
- 根据自己的数据格式修改代码
一般推荐第一种方法,因为第一种方法比较简单而且不容易出错,在制作为VOC2007格式的数据集之前,这里可以下载原始VOC2007数据集:VOC2007数据集,来看看这个数据集到底是什么样的:
1. 注释
**Annotations文件夹中存放的是xml格式的标签文件,每一个xml文件都对应于JPEGImages文件夹中的一张图片。xml文件的解析如下:
<annotation>
<folder>VOC2007</folder>
<filename>2007_000392.jpg</filename> //文件名
<source> //图像来源(不重要)
<database>The VOC2007 Database</database>
<annotation>PASCAL VOC2007</annotation>
<image>flickr</image>
</source>
<size> //图像尺寸(长宽以及通道数)
<width>500</width>
<height>332</height>
<depth>3</depth>
</size>
<segmented>1</segmented> //是否用于分割(在图像物体识别中01无所谓)
<object> //检测到的物体
<name>horse</name> //物体类别
<pose>Right</pose> //拍摄角度
<truncated>0</truncated> //是否被截断(0表示完整)
<difficult>0</difficult> //目标是否难以识别(0表示容易识别)
<bndbox> //bounding-box(包含左下角和右上角xy坐标)
<xmin>100</xmin>
<ymin>96</ymin>
<xmax>355</xmax>
<ymax>324</ymax>
</bndbox>
</object>
<object> //检测到多个物体
<name>person</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>198</xmin>
<ymin>58</ymin>
<xmax>286</xmax>
<ymax>197</ymax>
</bndbox>
</object>
</annotation>
2.JPEGImages
**
JPEGImages内部存放了PASCAL VOC所提供的所有的图片信息,包括了训练图片与测试图片
图片的像素尺寸不一样。(在我的数据中由于是裁剪的图片,所以图片大小都是600x1000)
3.ImageSets
**
由于我们只是关注目标检测,所以只需要知道Main文件夹中各个文件的含义:
Main文件夹下包含了每个分类的train.txt、val.txt和trainval.txt。
我们制作数据集时也是需要将图片的名称划分为这几个。
二、制作PASCAL VOC形式的数据集
制作自己的VOC2007格式数据集其实不需要那么多内容,我们只要做三个部分即可:Annotations文件夹、JPEGImages文件夹、ImageSets文件夹下的Main文件。
Step 1 : JPEGImages
**
首先我们需要在faster-rcnn.pytorch-pytorch-1.0这个文件下面创建一个data文件夹,然后在data文件夹下面创建一个VOCdevkit2007的文件夹,然后再在这个文件夹中创建VOC2007的文件夹。
/**faster-rcnn.pytorch-pytorch-1.0/data/VOCdevkit2007/**VOC2007/
**
然后再VOC2007这个文件夹下面,创建Annotations、JPEGImages、ImageSets三个文件夹,最后在ImageSets文件夹下再创建一个Main文件夹。
创建好所有文件夹后,我们将自己的数据集图片都放到JPEGImages文件夹下。
注意:按照习惯,最好将所有的图片按照一定的规则重写命名,这样更好进行处理。一般,如果名称在后续没有什么特殊使用,可以按照原数据集里的名称规则命名。
代码:
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
Step 2 : Annotations
**
标注工具我推荐:LabelImg
github地址:https://github.com/tzutalin/labelImg,有详细安装教程。
下载后进入下载目录,copy到home目录下解压,解压后进入目录:
cd labelImg
python labelImg.py
即可打开界面,进入你存储图片的文件夹,设置标注文件的保存位置Annotations。
此软件的使用方法:
**
修改默认的XML文件保存位置,使用快捷键“Ctrl+R”,改为自定义位置,这里的路径一定不能包含中文,否则无法保存。
源码文件夹中使用notepad++打开data/predefined_classes.txt,修改默认类别,比如改成person、car、motorcycle三个类别。
“Open Dir”打开图片文件夹,选择第一张图片开始进行标注,使用“Create RectBox”或者“Ctrl+N”开始画框,单击结束画框,再双击选择类别。完成一张图片后点击“Save”保存,此时XML文件已经保存到本地了。点击“Next Image”转到下一张图片。
标注过程中可随时返回进行修改,后保存的文件会覆盖之前的。
完成标注后打开XML文件,发现确实和PASCAL VOC所用格式一样。
step 3: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文件:
# !/usr/bin/python
# -*- coding: utf-8 -*-
import os
import random
path = '/home/hans/Documents/optical surface data/Pre_processing data/'
trainval_percent = 0.8 # trainval占比例多少
train_percent = 0.7 # test数据集占比例多少
xmlfilepath = path + 'Annotations'
txtsavepath = path + '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(path + 'ImageSets/Main/trainval.txt', 'w')
ftest = open(path + 'ImageSets/Main/test.txt', 'w')
ftrain = open(path + 'ImageSets/Main/train.txt', 'w')
fval = open(path + 'ImageSets/Main/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()
Step 4 : 统计相关数据
在制作自己的数据集成功过后,如果想要统计以下你图片中的标注种类,以及Bounding Box的数量时,可以使用并且修改以下代码进行统计:
import re
import os
import xml.etree.ElementTree as ET
class1 = 'xxxxx'
class2 = 'xxxxx'
annotation_folder = '/Annotations'
def file_name(file_dir):
L = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if os.path.splitext(file)[1] == '.xml':
L.append(os.path.join(root, file))
return L
total_number1 = 0
total_number2 = 0
total = 0
total_pic = 0
pic_num1 = 0
pic_num2 = 0
flag1 = 0
flag2 = 0
xml_dirs = file_name(annotation_folder)
for i in range(0, len(xml_dirs)):
# print(xml_dirs[i])
annotation_folder = open(xml_dirs[i]).read()
root = ET.fromstring(annotation_folder)
total_pic = total_pic + 1
for obj in root.findall('object'):
label = obj.find('name').text
if label == class1:
total_number1 = total_number1 + 1
flag1 = 1
total = total + 1
if label == class2:
total_number2 = total_number2 + 1
flag2 = 1
total = total + 1
if flag1 == 1:
pic_num1 = pic_num1 + 1
flag1 = 0
if flag2 == 1:
pic_num2 = pic_num2 + 1
flag2 = 0
print("class:", class1, "pic_num:", pic_num1, "BB_num", total_number1)
print("class:", class2, "pic_num:", pic_num2, "BB_num", total_number2)
print("total_pic", total_pic, "total_BB:", total)
三、使用Pytorch版Faster R-CNN训练自己数据集
使用代码来自:https://github.com/jwyang/faster-rcnn.pytorch/tree/pytorch-1.0
确保已经编译好相关的代码,能够直接训练。
我们在回到/**faster-rcnn.pytorch-pytorch-1.0/data**文件夹中,在这个文件夹里面主要存储的是
- 训练数据集 ----VOCdevkit2007
- 骨干网络的预训练模型 ---- pretrained_model
- Faster R-CNN模型参数的保存 ---- cache (进行训练之后才会被创建)
骨干网络的预训练模型下载:
vgg16 :https://filebox.ece.vt.edu/~jw2yang/faster-rcnn/pretrained-base-models/vgg16_caffe.pth
Resnet101:https://filebox.ece.vt.edu/~jw2yang/faster-rcnn/pretrained-basemodels/resnet101_caffe.pth
训练命令示例(单GPU训练):
CUDA_VISIBLE_DEVICES=$GPU_ID python trainval_net.py \
--dataset pascal_voc --net res101 \
--bs $BATCH_SIZE --nw $WORKER_NUMBER \
--lr $LEARNING_RATE --lr_decay_step $DECAY_STEP \
--cuda
'''
GPU_ID : 有的电脑默认为0,有点电脑默认为1
--dataset pascal_voc : 训练数据集类型pascal_voc
--net : 骨干网络选择VGG16,ResNet101
--bs : batch_size 默认为1
–nw : worker number,取决于你的Gpu能力
--lr : learning rate : 一般选取默认值就行,也可以自己选取
--lr_decay_step : 同上
'''
如果使用多GPU训练:
python trainval_net.py --dataset pascal_voc --net vgg16 \
--bs 24 --nw 8 \
--lr $LEARNING_RATE --lr_decay_step $DECAY_STEP \
--cuda --mGPUs
训好的model会存到models文件夹底下。
如果想要训练自己的数据集,开始前一定要确保data/cache中没有文件,因为这里要保存一些训练用的中间数据。
最后我们只需要将/faster-rcnn.pytorch/lib/datasets/pascal_voc.py中的这行代码:
//类别
self._classes = ('__background__', # always index 0
'aeroplane', 'bicycle', 'bird', 'boat',
'bottle', 'bus', 'car', 'cat', 'chair',
'cow', 'diningtable', 'dog', 'horse',
'motorbike', 'person', 'pottedplant',
'sheep', 'sofa', 'train', 'tvmonitor','plane')
除了第一个background之外,将自己数据的标注类别填写上去,就能够进行训练了。