本教程以YOLO_v2为例,检测三种不同的剪刀。 系统:Ubuntu16.04, 基于 Darknet。
安装Darknet
darknet官网都有很详细的步骤darknet
在终端输入:
git clone https://github.com/pjreddie/darknet
cd darknet
make
数据集的准备
图片和标签
(1) 采用jpg格式的图像,在名字上最好像使用voc一样类似000001.jpg、000002.jpg 。
(2)标记信息的格式xml,命名和图片一一对应,标记内容格式与VOC中标记信息的格式类似,标注工具有labe image,某一xml中具体内容如下:
<annotation>
<folder>Image</folder>
<filename>0000</filename>
<source>
<database>Pedestrian_ultrared</database>
</source>
<size>
<width>384</width>
<height>288</height>
</size>
<object>
<name>n00000001</name>
<bndbox>
<xmin>232</xmin>
<xmax>248</xmax>
<ymin>161</ymin>
<ymax>203</ymax>
</bndbox>
</object>
</annotation>
2.制作标签txt文件
在准备好上述数据后按照voc数据集的结构放置图像文件。Voc的结构如下:
1. --VOC
2. --Annotations
3. --ImageSets
4. --Main
5. --Layout
6. --Segmentation
7. --JPEGImages
8. --SegmentationClass
9. --SegmentationObject
这里面用到的文件夹是Annotation、ImageSets 和 JPEGImages 。其中文件夹Annotation中主要存放xml文件,每一个xml对应一张图像,并且每个xml中存放的是标记的各个目标的位置和类别信息,命名与对应的原始图像一样;而 ImageSets 我们只需要用到Main文件夹,这里面存放的是一些文本文件,通常为 train.txt、test.txt 等,该文本文件里面的内容是需要用来训练或测试的图像的名字(无后缀无路径);JPEGImages文件夹中放我们已按统一规则命名好的原始图像。在ImageSets文件夹中,新建三个空文件夹Layout、Main、Segmentation,然后把写了训练或测试的图像的名字的文本拷到Main文件夹下。
在制作标签txt 前需要得到所有图片的命名文本,一张图片的名字为一行,且训练集和验证集(train.txt,test.txt)分为两个文本文件,放在上述的Main文件夹下,形如:
生成标签 txt 可以参考官网提供的 voc_label.py
如上图:第10行修改为你的类别名,26行为.xml文件的路径,27行为保存标签txt的路径,52行为上述图片命名(Main)的路径,56行为图片的路径。运行voc_label.py,最后会得到每张图片的标签的信息文件和图片的路径文件(生成train.txt和test.txt,文本中保存的为每张图片的路径,且train.txt 和test.txt 保存在和Annotation、ImageSets、JPEGImages同一级目录下)。如下图:
labels文件夹中为每张图片的标签信息:
每个txt中保存的是该图片的标签信息: 类别、x、y、w、h 。
画风如下:
生成的train.txt和test.txt中是每张图片的路径,应该是这样的:
上述都准备好了,就代表我们的数据集准备工作完成了。核对一下有哪些内容:图片.jpg、标签.xml、每张图片的标签.txt、图片路径(train.txt、test.txt),并保证他们在对应的文件夹下。
修改配置文件
接下来就可以根据不同的网络设置(cfg文件)来训练了。在文件夹cfg中有很多.cfg文件,应该跟caffe中的prototxt文件是一个意思。这里以yolo_v2.cfg为例,我们修改名字my_yolov2.cfg。主要修改参数如下:
(1).cfg中:
网络层的最后一个卷积层(region上)中的filters需要修改,计算公式是自己数据的类别数:
filters=num×(classes + coords + 1)=5×(1+4+1)=40(我这里是3类,coords设定好的是4)
(2)接下来修改data文件下的voc.names。打开voc.names文件可以看到有20类的名称,我们只有3类。修改成我们的类别名称,一类一行。注意:这里类别的顺序要和之前voc_label.py第10行修改类别名的顺序保持一致。
(3)修改cfg文件夹下的voc.data
1. classes= 1 //类别数
2. train = /home/xm/darknet/dataset/train.txt //训练样本的绝对路径文件,也就是上文通过voc_label.py生成的 train.txt
3. valid = /home/xm/darknet/dataset /test.txt // 验证样本的绝对路径文件,也就是上文通过voc_label.py生成的 test.txt
4. names = data/voc.names //上一步修改的voc.names文件
5. backup = backup//指示训练后生成的权重放在哪
(4)修改example/darknet.c文件的第440行,将“cfg/coco.data”改为“cfg/voc.data”,如下
这一步如果不修改,最后执行darknet命令去检测的时候,得到的BoundingBox显示的类名会跟实际检测到的物体“风马牛不相及”。
(5)如果需要调用gpu、opencv则在Makefile文件中修改:
上述修改并保存后,在终端输入make clean 结束后再输入make,make 结束不报错就可以进行训练了。
(6)如果想修改迭代次数等修改.cfg 文件中的 max_batches。其他参数可以在网上查找yolo源码解析。
训练
训练命令为:
./darknet detector train cfg/my_voc.data cfg/ my_yolov2.cfg
也可以在官网上找到一些预训练的模型作为参数初始值,下载预训练模型放在darknet文件夹下,这里使用的是官网的预训练模型darknet19_448.conv.23做初始化,则训练命令为:
./darknet detector train cfg/my_voc.data cfg/ my_yolov2.cfg darknet19_448.conv.23
训练好的模型存放在darknet /backup文件中。
注:如果训练中出现学习率为一直为0时,修改.cfg中的burn_in参数,训练数据少的话,可以改小。训练时一开始的损失很大,这个是正常的。
测试
在终端输入:
./darknet detect cfg/my_yolov2.cfg backup/my_yolov2_final.weights data/2.jpg
结果: