从RCNN, fast RCNN, 到faster RCNN, YOLO, 以及最新的YOLO2, 检测的速度是越来越快了, 最新的YOLO2据作者说可以达到67Fps, 支持的种类达9000.想看效果的请戳这里YOLO2 .
这么快速度,当然很多人估计跟我一样,想把它用来检测特定类的物体。这里,我将根据自己查找的一些资料,以及自己的实践,告诉大家怎么在YOLO2中增加识别自己需要的物体。
主要分为2部分, 第一部分介绍如何制作自己的训练集和测试集。第二部分,介绍如何进行训练和测试。
一、用BBox-Label-Tool制作训练集
1. 下载BBox-Label-Tool
下载地址BBox-Lable-Tool
2. 修改main.py
1) 将126行self.category = int(s)
改为self.category = s
2) 将133行self.imageDir = os.path.join(r'./Images', '%03d' %(self.category))
改为self.imageDir = os.path.join(r'./Images', '%s' %(self.category))
3) 将144行self.outDir = os.path.join(r'./Labels', '%03d' %(self.category))
改为self.outDir = os.path.join(r'./Labels', '%s' %(self.category))
这样我们可以在Images目录下使用英文名目录而不是只有数字, Images目录下创建自己的目录用于放置你需要进行标注的图片集,比如在Images下创建myobject目录,然后把你要标注的图片(最少300张)放到myobject目录下。
3. 准备图片集
图片的话,300张左右大概就够了,当然越多越好。注意,BBox只能对JPEG文件进行识别(坑爹),所以如果你的图片是其他格式的话,要转成JPEG。Window下你可以找些批处理的转码软件,
这里我们就把需要进行标注的图片放到了Images/myobject目录下。我们就可以使用BBox进行标注了。
4. 生成标注数据
BBox-Label-Tool需要python2.7和PIL-1.1.7.win32-py2.7
安装完成后,执行python27 main.py(因为我的电脑是3.5和2.7都有装),在Image Dir中输入myobject,然后点击load加载需要标注的图片集,如下图
用鼠标确定一个方框后,右边会有对应坐标, 一张图片允许框选多个方框, 框选完成后点击next就会处理下一张图片,同时上一张图片的标注信息会出现在Lables目录下
5. 将标注数据转成YOLO可识别格式
因为YOLO的lable数据要求是object-class x y width height, 像这种
0 0.73 0.511070110701 0.41 0.616236162362, 而我们之前的标注数据格式是这样
1
210 55 374 222
所以需要转换一下,这里有个脚本,这个脚本下载完后还需要我们改动几个地方。
1)将13行的classes的值改为classes = ["myobject"]
2)将35行改为cls = "myobject"
3)将32,33行改为
mypath = "Labels/myobject/"
这里的outpath改为你自己的临时目录。
outpath = "traindata/lables/"
4)如果你在window下跑这个py,那么你还需要改58行,lines = txt_file.read().split('\n')
把\r\n改为\n.
最后执行这个脚本python27 convert.py,输出如下信息
然后你就可以在outpath下找到转换后的标注信息。
我们已经得到了一个图像集,在你的Images/myobject目录下, 一个对该图像集的标注信息,在你的outpath目录下, 现在把这2个目录下的jpeg和txt文件合并到一个文件夹,我这里是放到darkne目录下的data\myobject目录下, 下一步我们就要配置YOLO来进行训练了。
二、配置YOLO
YOLO的配置主要为3个文件myobj.data, myobj.name, myobj.cfg.
1. myobj.data
我的myobj.data内容如下
classes= 1
train = data/myobject/train.txt
valid = data/myobject/test.txt
names = data/myobject/myobj.names
backup = backup
classes为你要detect的目标种类个数, 检测一种的话就是1。 train指向一个txt文件,用于描述训练时用哪些图片进行训练。 valid用于描述测试时用哪些图片进行测试。这两个文件可以使用如下脚本生成
import glob, os
# Current directory
current_dir = os.path.dirname(os.path.abspath(__file__))
# 图片的存储目录
path_data = 'data/myobject/'
# Percentage of images to be used for the test set percentage_test = 10;
# Create and/or truncate train.txt and test.txt file_train = open('train.txt', 'w') file_test = open('test.txt', 'w') # Populate train.txt and test.txt counter = 1 index_test = round(100 / percentage_test) for pathAndFilename in glob.iglob(os.path.join(current_dir, "*.jpg")): title, ext = os.path.splitext(os.path.basename(pathAndFilename)) #file = open(title + '.txt', 'w') #file.write('0 0.5 0.5 1 1') #file.close() if counter == index_test: counter = 1 file_test.write(path_data + title + '.jpg' + "\n") else: file_train.write(path_data + title + '.jpg' + "\n") counter = counter + 1
把该脚本放到data/myobject目录下,然后执行,就会在该目录生成2个txt文件。
2.myobj.names
这个文件只有一行,也就是你要检测物体的名称, 他会在检测完后显示在图片上,每行对应一种物体。我们这里是myobj
3.myobj.cfg
这个文件用于描述网络结构, 我们可以直接拿cfg/yolo-voc.cfg来使用, 不过要改几个地方.
1) batch改为合适值, 一般64,如果你内存不够的话跑起来发现内存分配失败,可以改下点,比如32,16
2)subdivisions, 与上面类似,可以试试8,4,2,越小需要内存越大。
3)classes=1
4)倒数的第一个filters=(classes + 5)*5,这里我们就是30
三、 训练YOLO
训练前我们先去YOLO官网下载已经训练好的权值文件darknet19_448.conv.23(76M)
然后运行命令./darknet detector train data/myobject/myobj.data data/myobject/myobj.cfg darknet19_448.conv.23
默认情况下,每1000次会将训练好的权值存放到backup/myobj_1000.weights文件里, 所以下次开始训练时,可以从上一次训练结果中继续训练,命令如下
./darknet detector train data/myobject/myobj.data data/myobject/myobj.cfg backup/myobj_2000.weights, 这里我们从第2000次开始继续进行训练。
四、何时停止训练
请戳这里搬运工, 一般来讲2000次左右基本就够了, 当然如果你要更好的精度,那么需要观察avg这个值的变化, 如果这个值基本不再变小,那么训练就可以停止了。此时,你需要观察前几次的avg的值,选出几个最小的,然后根据avg最前面的数字,找到对应backup目录下的权值文件,之后执行如下命令
darknet detector recall data/myobject/myobj.data data/myobject/myobj.cfg backup\yolo-obj_XXXX.weights
根据输出IOU和Recall 值, 找到最好的weight文件。一般IOU越大越好,Recall也是越大越好。
五、小结
到这里我们已经可以使用YOLO对某一类物体进行检测了, 在此感谢国外友人Nils Tijtgat
的文章, 另:CPU跑慢的要死,一次要10分钟, 我看国外那哥们的贴图,只要2s, 喵生灰暗。想把darknet在GPU上运行,请戳这里。除了Bbox-lable-tool外,这里还有个YoloMark也可以用于bbox的生成,大家有兴趣可以看看。