SSD 实时目标检测

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

SSD 实时目标检测 SSD是为了实现实时目标检测而设计的。Faster R­CNN使用一个区域建议网络 region proposal network (RPN)产生可能包含物体的建议区域(一般训练时2000,测试时600),并且利用这些建议区域进行微调对物体进行分类和定位。Faster RCNN 整个处理过程大约是每秒 7 帧,这远远不能满足实时性。SSD通过取消 RPN 来加速处理过程。为了弥补精度上的损失,SSD采取了一些改进方法如:

1. 提取了不同尺度的特征图来做检测,大尺度特征图(较靠前的特征图)可以用来检测小物体,而小尺度特征图(较靠后的特征图)用来检测大物体。这些改进方法允许SSD使用较低分辨率的图像就可以达到Faster R­CNN的精度,而且处理速度更快。从下图可以看出,SSD达到了实时处理的速度并且精度还强于Faster R­CNN。(精度的评价指标是mAP­预测平均精度)。

2. 采用了不同尺度和长宽比的先验框(Prior boxes, Default boxes,在 Faster R­CNN 中叫做锚,Anchors)。

3. 采用CNN来直接进行检测,而不是像 Faster RCNN Y olo 那样在全连接层之后做检测,实现了全卷积

4. 将空洞卷积应用于目标检测。

这些改进方法使得 SSD 在使用较低分辨率的图像( lower resolution images)就可以达到 Faster R­CNN 的精度,而且处理速度更快。从下图可以看出,SSD达到了实时处理的速度并且精度还超过了 Faster R­CNN。SSD is a class aware RPN with a lot of bells and whistles.

SSD SSD 包含两个部分:

提取特征图

应用卷积核检测物体

Model mAP Training Command

Training log SSD 使用 VGG16 作为特征提取网络 backbone ,当然你也可以用其他的 backbone ,例如 mobilenet ,resnet 等等,不过奇怪的是使用 resnet 貌似提升不大。不过其实对于物体较大的简单任务,使用mobilenet 还是其他什么的区别不

是很大,因此具体选哪个得看自己的任务了。

下面是 GluonCV 得到的结果,使用了一些 tricks 得到了超越原论文的表现:

https://gluon­cv.mxnet.io/model_zoo/detection.html#ssd

ssd_300_vgg16_atrous_voc [1]77.6shell script log

ssd_512_vgg16_atrous_voc [1]79.2shell script log

ssd_512_resnet50_v1_voc [1]80.1shell script log

ssd_512_mobilenet1.0_voc [1]75.4shell script log

可以看到由 VGG 换为 resnet50提升只有 0.9%,甚至有时候还会下降,这点比较奇怪。而 Faster RCNN 由 VGG16 变为 ResNet101 可以提升 5%。VGG 太大了,由上面的图可以看到,基本没有比 VGG 还大的了。

SSD 使用 Conv4_3 的卷积层(VGG 下采样16倍之前的所有网络层)来检测物体。为了方便说明,我们假设图片经过 Conv4_3 变成了一个 8×8 的特征图(它应该是38×38,因为下采样了 8 倍)。对于每个 cell (也称为location),它进行了 4 个预测。

左:原始图片 右:每个 cell 4 个预测。

每个预测结果包含一个边界框 bbox 以及这个bbox 属于这 21 个类别的得分(其中一个是背景类别),我们选择其中最高的得分所属类别作为该bbox的分类类别。Conv4_3 总共会做出 38x38x4 个预测:每个 cell 4 个预测,跟特征图的深度无关。显然,很多预测结果中都不包含物体。SSD 将这些不包含物体的归类为0。

每个预测结果包含一个边界框 bbox 以及这个bbox 属于这 21 个类别的得分(其中一个是背景类别)

VGG 网络部分源码:

# vgg(base['300'], 3) SSD 中的VGG16配置:# base['300'] = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'C', 512, 512, 512, 'M',512, 512, 512]# VGG16 官方的特征提取部分配置:# [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M']# 可以看到去掉了最后的maxpooling 层,并且对于其中一个maxpooling 改变了ceil_mode ,这在 75 进行maxpooling 时会使得# 75 ==> 37.5 ==> 38 而不是变成 37# 不太明白为什么要这样,不过应该没太大的影响,可能还是为了尺寸方面考虑# 300 ==> 150 ==> 75 ==> 38 ==> 19"""'M':表示使用 kernel size = 2,stride = 2 的 max pooling 'C':表示与‘M’相同的 max pooling ,但 ceil_mode = True ,需要注意的是这与原始的VGG 不同,原始的VGG 没有这个选项"""def vgg (cfg , i , batch_norm =False ): """ (vgg): ModuleList( (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) Conv1_1 (1): ReLU(inplace) (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))Conv1_2 (3): ReLU(inplace) (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) Conv2_1 (6): ReLU(inplace) (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) Conv2_2 (8): ReLU(inplace) (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) Conv3_1 (11): ReLU(inplace) (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) Conv3_2 (13): ReLU(inplace) (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) Conv3_3

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

相关文档
最新文档