目标检测方法对比及yolov3实现

YOLOv3简介

目录

一.目标识别的简介... 1

二.各类方法特点简介... 3

1.         R-CNN. 3

2.         Fast R-CNN. 4

3.         Faster R-CNN. 5

4.         SSD. 6

5.         YOLO(v1,v2,v3)... 6

三.YOLO算法训练简介... 9

三.YOLOV3代码实现过程... 13

1.         新建文件目录... 13

2.         把要训练的图片都复制到JPEGImages里面... 14

3.         生成标签文件xml. 14

4.         生成样本及图片定位... 14

5.         修改参数文件yolo3.cfg. 14

6.         yolo3.cfg转换weight文件... 15

7.         修改model_data下文件文件... 15

8.         修改代码,准备训练... 15

9.         预测... 16

 

 

 

 

 

 

 

 

 

 

 

一.目标识别的简介

图像分类模型是将图像划分为单个类别,通常对应于图像中最突出的物体。但是现实世界的很多图片通常包含不只一个物体,此时如果使用图像分类模型为图像分配一个单一标签其实是非常粗糙的,并不准确。对于这样的情况,就需要目标检测模型,目标检测模型可以识别一张图片的多个物体,并可以定位出不同物体(给出边界框)。目标检测在很多场景有用,如无人驾驶和安防系统。

目前主流的目标检测算法主要是基于深度学习模型,其可以分成两大类:(1)two-stage检测算法,其将检测问题划分为两个阶段,首先产生候选区域(region proposals),然后对候选区域分类(一般还需要对位置精修),这类算法的典型代表是基于region proposal的R-CNN系算法,如R-CNN,Fast R-CNN,Faster R-CNN等;(2)one-stage检测算法,其不需要region proposal阶段,直接产生物体的类别概率和位置座标值,比较典型的算法如YOLO。目标检测模型的主要性能指标是检测准确度和速度,对于准确度,目标检测要考虑物体的定位准确性,而不单单是分类准确度。一般情况下,two-stage算法在准确度上有优势,而one-stage算法在速度上有优势。不过,随着研究的发展,两类算法都在两个方面做改进。如下所示为各类方法的准确率以及训练时间的对比图。

二.各类方法特点简介

  1. R-CNN

R-CNN(R. Girshick et al., 2014)是基于region proposal方法的目标检测算法系列开山之作,其先进行区域搜索,然后再对候选区域进行分类。在R-CNN中,选用Selective search方法(J.R.R. Uijlings and al. 2012)来生成候选区域,这是一种启发式搜索算法。它先通过简单的区域划分算法将图片划分成很多小区域,然后通过层级分组方法按照一定相似度合并它们,最后的剩下的就是候选区域(region proposals),它们可能包含一个物体。

对于一张图片,R-CNN基于selective search方法大约生成2000个候选区域,然后每个候选区域被resize成固定大小并送入一个CNN模型中,最后得到一个4096-d的特征向量。然后这个特征向量被送入一个多类别SVM分类器中,预测出候选区域中所含物体的属于每个类的概率值。每个类别训练一个SVM分类器,从特征向量中推断其属于该类别的概率大小。为了提升定位准确性,R-CNN最后又训练了一个边界框回归模型。缺点: 在R-CNN中,每个候选框先resize到统一大小,然后分别作为CNN的输入,这样是很低效的。

  1. Fast R-CNN

在R-CNN选区域都要单独送入CNN模型计算特征向量,这是非常费时的,而对于Fast R-CNN,其CNN模型的输入是整张图片,然后结合RoIs(Region of Interests)pooling和Selective Search方法从CNN得到的特征图中提取各个候选区域的所对应的特征。对于每个候选区域,使用RoI pooling层来从CNN特征图中得到一个固定长和宽的特征图,RoI pooling的原理很简单,其根据候选区域按比例从CNN特征图中找到对应的特征区域,然后将其分割成几个子区域。即将池化层变成可变的。

RoI Pooling层将每个候选区域分为m * n个块。针对每个块执行最大池操作,使得特征映射上不同大小的候选区域被变换为均匀大小的特征向量。然后送入下一层。举例来说,某个ROI区域座标为(x1,y1,x2,y2),那么输入尺寸大小为( y2−y1)∗( x2−x1); 如果合并输出的大小为池高乘池宽,即pooledheight∗pooledwidth,则每个网格的大小都是为

https://img-blog.csdn.net/20180527162409787?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dlbnRlbHlhbmc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

  1. Faster R-CNN

   加入提取边缘的神经网络,将提取候选框的工作交给神经网络来完成(Region Proposal Network(RPN)),提高了生成Region Proposal的速度。

  1. SSD

在Yolov1每个单元预测多个边界框,但是其都是相对这个单元本身(正方块),但是真实目标的形状是多变的,Yolov1在训练过程中自适应目标的形状。而SSD借鉴了Faster R-CNN中anchor的理念,每个单元设置尺度或者长宽比不同的先验框,预测的边界框(bounding boxes)是以这些先验框为基准的,在一定程度上减少训练难度。

  1. YOLO(v1,v2,v3)

在介绍Yolo算法之前,首先先介绍一下滑动窗口技术,这对我们理解Yolo算法是有帮助的。采用滑动窗口的目标检测算法思路非常简单,它将检测问题转化为了图像分类问题。其基本原理就是采用不同大小和比例(宽高比)的窗口在整张图片上以一定的步长进行滑动,然后对这些窗口对应的区域做图像分类,这样就可以实现对整张图片的检测了。但是这个方法有致命的缺点,就是你并不知道要检测的目标大小是什么规模,所以你要设置不同大小和比例的窗口去滑动,而且还要选取合适的步长。但是这样会产生很多的子区域,并且都要经过分类器去做预测,这需要很大的计算量,所以你的分类器不能太复杂,因为要保证速度。解决思路之一就是减少要分类的子区域,这就是R-CNN的一个改进策略,其采用了selective search方法来找到最有可能包含目标的子区域(Region Proposal),其实可以看成采用启发式方法过滤掉很多子区域,这会提升效率。

如果你使用的是CNN分类器,那么滑动窗口是非常耗时的。但是结合卷积运算的特点,我们可以使用CNN实现更高效的滑动窗口方法。这里要介绍的是一种全卷积的方法,简单来说就是网络中用卷积层代替了全连接层,这样一次CNN计算就可以实现窗口滑动的所有子区域的分类预测。这其实是overfeat算法的思路。之所可以CNN可以实现这样的效果是因为卷积操作的特性,就是图片的空间位置信息的不变性,尽管卷积过程中图片大小减少,但是位置对应关系还是保存的。说点题外话,这个思路也被R-CNN借鉴,从而诞生了Fast R-cNN算法。

上面尽管可以减少滑动窗口的计算量,但是只是针对一个固定大小与步长的窗口,这是远远不够的。Yolo算法很好的解决了这个问题,它不再是窗口滑动了,而是直接将原始图片分割成互不重合的小方块,然后通过卷积最后生产这样大小的特征图,基于上面的分析,可以认为特征图的每个元素也是对应原始图片的一个小方块,然后用每个元素来可以预测那些中心点在该小方格内的目标,这就是Yolo算法的朴素思想

YOLOv2相比YOLOv1做了很多方面的改进,这也使得YOLOv2的mAP有显著的提升,并且YOLOv2的速度依然很快,保持着自己作为one-stage方法的优势,YOLOv2和Faster R-CNN, SSD等模型的对比如图

相比YOLOv2,YOLOv3最大的变化包括两点:使用残差模型和采用FPN架构。YOLOv3的特征提取器是一个残差模型,因为包含53个卷积层,所以称为Darknet-53,从网络结构上看,相比Darknet-19网络使用了残差单元,所以可以构建得更深。另外一个点是采用FPN架构(Feature Pyramid Networks for Object Detection)来实现多尺度检测。YOLOv3采用了3个尺度的特征图,VOC数据集上的YOLOv3网络结构,YOLOv3每个位置使用3个先验框,所以使用k-means得到9个先验框,并将其划分到3个尺度特征图上,尺度更大的特征图使用更小的先验框,和SSD类似。

YOLO优点:1、训练速度快并且准确率非常高。2、边界的精确,在各代YOLO逐渐在优化,与其它的差异不大。

缺点:1、尺度较小的目标预测较差

三.YOLO算法训练简介

假设我们要在图片中检测三种目标:行人、汽车和摩托车,同时使用两种不同的Anchor box。

训练集:

输入X:同样大小的完整图片;

目标Y:使用网格划分,输出大小,或者对不同格子中的小图,定义目标输出向量Y。

我们先看看如何构造你的训练集,假设你要训练一个算法去检测三种对象,行人、汽车和摩托车,你还需要显式指定完整的背景类别。这里有 3 个类别标签,如果你要用两个 anchor box,那么输出 y 就是 3×3×2×8,其中 3×3 表示 3×3 个网格,2 是anchorbox 的数量,8 是 向量维度,8 实际上先是 5(pc, bx , by , bℎ , bw)再加上类别的数量(c1, c2, c3)。你可以将它看成是 3×3×2×8,或者 3×3×16。要构造训练集,你需要遍历 9 个格子,然后构成对应的目标 向量y。

所以先看看第一个格子(编号 1),里面没什么有价值的东西,行人、车子和摩托车, 三 个 类 别 都 没 有 出 现 在 左 上 格 子 中 , 所 以 对 应 那 个 格 子 目 标 y就 是 这样 的 , y=[0 ? ? ? ? ? ? ?0 ? ? ? ? ? ? ?]T,第一个 anchor box 的 pc 是 0,因为 没什么和第一个 anchor box 有关的,第二个 anchor box 的 pc 也是 0,剩下这些值是 don’t care-s。所以你这样遍历 9 个格子,遍历 3×3 网格的所有位置,你会得到这样一个向量,得到一个 16 维向量,所以最终输出尺寸就是 3×3×16。和之前一样,简单起见,我在这里用的是 3×3 网格,实践中用的可能是 19×19×16,或者需要用到更多的 anchor box,可能是 19×19×5×8, 即 19×19×40,用了 5 个 anchor box。这就是训练集,然后你训练一个卷积网络,输入是图 片,可能是 100×100×3,然后你的卷积网络最后输出尺寸是,在我们例子中是 3×3×16 或者3×3×2×8。

模型预测:

输入与训练集中相同大小的图片,同时得到每个格子中不同的输出结果:

接下来我们看看你的算法是怎样做出预测的,输入图像,你的神经网络的输出尺寸是这个 3××3×2×8,对于 9 个格子,每个都有对应的向量。对于左上的格子(编号 1),那里没有 任何对象,那么我们希望你的神经网络在那里(第一个pc)输出的是 0,这里(第二个pc)是 0,然后我们输出一些值,你的神经网络不能输出问号,不能输出 don’t care-s,剩下的我 输入一些数字,但这些数字基本上会被忽略,因为神经网络告诉你,那里没有任何东西,所 以输出是不是对应一个类别的边界框无关紧要,所以基本上是一组数字,多多少少都是噪音(输出 y 如编号 3 所示)。

运行非最大值预测(NMS)

最后你要运行一下这个非极大值抑制,为了让内容更有趣一些,我们看看一张新的测试图像,这就是运行非极大值抑制的过程。如果你使用两个 anchor box,那么对于 9 个格子中 任何一个都会有两个预测的边界框,其中一个的概率pc很低。但 9 个格子中,每个都有两个

预测的边界框,比如说我们得到的边界框是是这样的,注意有一些边界框可以超出所在格子 的高度和宽度(编号 1 所示)。接下来你抛弃概率很低的预测,去掉这些连神经网络都说,这里很可能什么都没有,所以你需要抛弃这些(编号 2 所示)。

最后,如果你有三个对象检测类别,你希望检测行人,汽车和摩托车,那么你要做的是,对于每个类别单独运行非极大值抑制,处理预测结果所属类别的边界框,用非极大值抑制来 处理行人类别,用非极大值抑制处理车子类别,然后对摩托车类别进行非极大值抑制,运行三次来得到最终的预测结果。所以算法的输出最好能够检测出图像里所有的车子,还有所有 的行人(编号 3 所示)。

四.YOLOV3代码实现过程

  1. 新建文件目录

https://img-blog.csdn.net/20181017093009220?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3piemNrYWlB/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

logs用于存放训练后的模型,model_data用于存放标签类别数据,Segmentationclass用于生成测试生成的图片,VOC2007用于存放训练数据,JPEGimages用于存放原始图片,Annotations 用于存放生成的xml数据ImageSets用于存放生成的训练文件目录。

(链接:https://pan.baidu.com/s/1EhVeWBiS8YKBD0552g3DLg 提取码:4zhe)

  1. 把要训练的图片都复制到JPEGImages里面
  2. 生成标签文件xml

利用网盘下载的文件labelmodel 对照片进行手动打标签生成xml文件,生成的文件放入Annotations文件中。

  1. 生成样本及图片定位
   ①利用create_label_text.py生成训练测试的图片标签并保存在./VOC2007/ImageSets/Main/文件夹下
②修改voc_annotation.py文件,把class中的class 修改为你需要的分类标签,classes= ['bee','laby..'],将VOCdevkit/路径修改为./(当前目录)
  1. 修改参数文件yolo3.cfg

修改yolo3.cfg参数,ctrl+f搜 yolo, 总共会搜出3个含有yolo的地方,修改上下文中下面三处地方

每个地方都要改3处,filters:3*(5+len(classes));

②classes: len(classes) = 2,这里以bee、ladybug三个颜色为例

③random:原来是1,显存小改为0

  1. yolo3.cfg转换weight文件

利用convert.py 转化权重文件。权重下载地https://pjreddie.com/media/files/yolov3.weights

python convert.py -w yolov3.cfg yolov3.weights model_data/yolo_weights.h5
  1. 修改model_data下文件文件

将文件中的标签改为新的模型标签,coco,voc这两个文件都需要修改。

像这样:

   https://img-blog.csdn.net/20180607210817261?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1BhdHJpY2tfTHhj/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

  1. 修改代码,准备训练

代码以yolo3模型为目标,tiny_yolo(准确率太低)不考虑。

代码会加载预先对coco数据集已经训练完成的yolo3权重文件,

https://img-blog.csdn.net/20180607211237833?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1BhdHJpY2tfTHhj/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70冻结了开始到最后倒数第N层(源代码为N=-2)

https://img-blog.csdn.net/20180607211432467?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1BhdHJpY2tfTHhj/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

③代码中有两处修改batch_size的地方,第一个地方选择16第二个地方选择8(电脑配置内存8g\cpu)第一处为只开放了最后两层进行训练,后面那个是在这个的基础上放开所有隐层,只保留权重重新训练。

  1. 预测

将检测的图片完成的都储存在outdir里,运行yolo_img.py脚本。注:预测的时候要用cmd命令行运行,因为argparse如果不适用默认参数配置,不能jupyter中执行,报错为unrecognized arguments process finished with exit code 2

结果展示:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章