其他文章http://blog.csdn.net/baolinq
上次写了一篇关于使用yolo训练VOC数据集的文章,传送门(http://blog.csdn.net/baolinq/article/details/78724314)。但是总不能只使用一个数据集,多使用几个数据集看看效果。因为我主要在做车辆和行人方面的检测。正好KITTI 数据集是做无人驾驶方面的公开权威数据集,包含大量公路,城市街道等各种路况的数据集,官方网站(http://www.cvlibs.net/datasets/kitti/index.php),很符合我的要求。
1. 下载KITTI 数据集
Kitti数据是利用车顶上的多个相机拍的,我这里只取了leftimage,也就是第一个,链接(http://www.cvlibs.net/datasets/kitti/eval_object.php?obj_benchmark=2d),有点大,12G左右。点击链接会让你填一个邮箱,真正的下载链接会发到你的邮箱,还有label文件。只有训练图片有标签,test图片没有标签,现在还不知道如何使用,有知道大神指导一下。我暂时是这样做的,后面我会把train图片分成train,val,和test三个部分
2. KITTI 数据集转化为VOC数据集格式
如果你没有修改yolo网络的源码,我们知道,它需要的是VOC数据格式的训练集。那么VOC数据集格式是这么样的呢?简单来看一下:
--VOC --Annotations --ImageSets --Main --Layout --Segmentation --JPEGImages --SegmentationClass --SegmentationObject
后面两个是分割用到的,不用管他们。这里面用到的文件夹是Annotation、ImageSets和JPEGImages。其中文件夹Annotation中主要存放xml文件,每一个xml对应一张图像,并且每个xml中存放的是标记的各个目标的位置和类别信息,命名通常与对应的原始图像一样;而ImageSets我们只需要用到Main文件夹,这里面存放的是一些文本文件,通常为train.txt、test.txt等,该文本文件里面的内容是需要用来训练或测试的图像的名字(无后缀无路径);JPEGImages文件夹中放我们已按统一规则命名好的原始图像。
而KITTI数据集又是什么样的呢
Kitti的标记信息是一个txt,里面的内容如下:
Car 0.00 0 -1.67 642.24 178.50 680.14 208.68 1.381.49 3.32 2.41 1.66 34.98 -1.60
Car 0.00 0 -1.75 685.77 178.12 767.02 235.21 1.50 1.62 3.89 3.27 1.67 21.18-1.60
以上内容的含义如下:(截图自https://github.com/NVIDIA/DIGITS/blob/v4.0.0-rc.3/digits/extensions/data/objectDetection/README.md)
这部分参考http://blog.csdn.net/jesse_mx/article/details/65634482,
大概了解了数据的格式,我们就开始转化吧。首先建立一系列的文件夹:
# 在scipts/文件夹下新建KITTIdevkit/KITTI两层子目录,所需文件放在KITTI/中
Annotations/
└── 000000.xml
ImageSets/
└── main/
└── trainval.txt
└── test.txt#等等
JPEGImages/
└── 000000.png
Kitti_Labels/
└── 000000.txt # 自建文件夹,存放原始标注信息,待转化为xml,不属于VOC格式
create_train_test_txt.py# 3个python工具,后面有详细介绍
modify_annotations_txt.py
txt_to_xml.py
截图如下:
代码工具我都会在文末给出下载链接。
第一步,类别转化
PASCAL VOC数据集总共20个类别,如果用于特定场景,20个类别确实多了。此次博主为数据集设置3个类别, ‘Car’,’Cyclist’,’Pedestrian’,只不过标注信息中还有其他类型的车和人,直接略过有点浪费,博主希望将 ‘Van’, ‘Truck’,‘Tram’ 合并到 ‘Car’类别中去,将‘Person_sitting’合并到 ‘Pedestrian’类别中去(‘Misc’和 ‘Dontcare’这两类直接忽略)。这里使用的是modify_annotations_txt.py工具。
对原始txt文件进行上述处理后,接下来需要将标注文件从txt转化为xml,并去掉标注信息中用不上的部分,只留下3类,还有把坐标值从float型转化为int型,最后所有生成的xml文件要存放在Annotations文件夹中。这里使用的是txt_to_xml.py工具,此处是由KITTI_SSD 的代码修改而来,感谢作者的贡献。
用于SSD训练的Pascal VOC格式的数据集总共就是三大块:首先是JPEGImages文件夹,放入了所有png图片;然后是Annotations文件夹,上述步骤已经生成了相应的xml文件;最后就是imagesSets文件夹,里面有一个Main子文件夹,这个文件夹存放的是训练验证集,测试集的相关列表文件,如下图所示:
到这里数据转化已经基本完成。
但是还不能直接训练。在scripts文件夹下有一个voc_label.py文件,我们转化好的数据不能直接使用voc_label.py文件.需要做一些小小的修改。我把它改为kitti_label.py文件,文末有下载的链接。没什么关键的改变,只是为了适应数据集,让它能正确生成图片路径的txt文件。运行这个py文件会重新生成labels文件,txt格式,里面的标记信息都被调整到到与图像成比例的尺寸。会生成label文件夹里面是每个图片的groundtruth的框坐标信息txt格式,还会在scripts目录生成train.txt,val.txt,test.txt文件,记录图片的绝对路径,便于程序批量读入。
再后面就是类似上一篇训练VOC数据集的博客了,根据实际情况调整网络参数,包括cfg文件,names文件,data文件。http://blog.csdn.net/baolinq/article/details/78724314
最后有一个很重要的细节,不要忽略,VOC数据集是jpg格式,而KITTI数据集是png格式的。
我们要看一下源码是如何读取图片和标记信息的txt文件。很简单,之前我们在train.txt文件里面只记录了所有训练图片的绝对路径,并没有记录labels文件的路径,所以我们要通过图片的路径得到labels的路径,因为如果我们是按照标准方式放置的文件,那么labels文件的位置和png文件位置很相近,有规律可寻,只要替换一些文件夹和后缀名就可以了。
到这里应该就可以正常训练了,这次我的maxbatch设置为40000,训练了十几个小时。训练完的检测效果可以看一下:训练命令:darknet.exe detector train data/kitti.data cfg/kitti.cfg pre_model/darknet19_448.conv.23 -gpus 0,1
评估结果,检测recall是77.33%,准确率是89.96%,(数据好像有问题?)看起来还不错,但是在实际检测图片时效果不怎么好,尤其是对kitti以外的数据集。原因待研究,欢迎在评论区指导留言交流。
不同的功能就是detector后面的参数不一样,有train,test,recall,demo等,可以看下源码detector.c
如果你只是测试单张图像,就用test命令,类似darknet.exe detector test data/kitti.data cfg/kitti.cfg weights/kitti_40000.weights -gpus 0,1
如果是测试整个测试集的准确率和recall,就用recall命令。类似这样的darknet.exe detector recall data/kitti.data cfg/kitti.cfg weights/kitti_40000.weights -gpus 0,1
测试视频就用demo命令,类似darknet.exe detector demo data/voc-3.data cfg/yolo-3.cfg weights/yolo-3_final.weights -gpus 1 test_image/123.mp4
参考文献
[1]https://pjreddie.com/darknet/yolo/ 官网提供了很多训练好的模型,很良心
[2]https://arxiv.org/abs/1612.08242 yolo v2论文原文
[3] https://github.com/pjreddie/darknet github源码
[4]http://www.cvlibs.net/datasets/kitti/index.php kitti数据集官网
[5]还有很多优秀的博客,感谢他们的贡献
kitti转为VOC数据集工具代码下载链接http://download.csdn.net/download/baolinq/10181761