GitHub:
liuyuemaicha/ssd.pytorchgithub.comPython 2.7 Pytorch:0.3.1或0.4.1
注:该代码fork自https://github.com/amdegroot/ssd.pytorch,该代码相比master分支,主要改动有:
- 修改了原代码中发现的bug,如:multibox_loss 中loss_c[pos] = 0并不能直接索引,pos和loss_c的shape不同;此外在训练时loss值容易出现inf情况,也需要修改。
- 去掉了一些可视化辅助插件,便于直接运行。
- 将Python环境从3.0改为2.7
- 对代码做了大量的中文注释
- 去除了COCO数据集读取对pycocotools的依赖
在objects detection算法中,大概可以分为两大方向:One-stage和Two-stage。SSD算法属于One-Stage的一种。
关于One-Stage的另一种算法YOLO V3可转:KevinCK:目标检测——YOLO V3简介及代码注释(附github代码——已跑通)
关于Two-Stage的Faster-RCNN的简介和代码,可以转:KevinCK:目标检测——Faster RCNN简介与代码注释(附github代码——已跑通)
SSD目标检测简介
SSD(Single Shot MultiBox Detector)从名字中可以看到SSD的两个特征,一是SSD属于One-Stage(Single Shot),二是SSD使用多特征图用于检测(MultiBox)。除此之外,SSD发布于Faster-RCNN之后,所以也借鉴了Faster-RCNN重的anchor思想,这里称之为Prior Boxes(感觉这个名字比anchors要更好通俗易懂)。
SSD的模型框架主要由三部分构成:以SSD300为例,有VGG-Base,Extra-Layers和Pred-Layers。VGG-Base作为基础架构用来提取图像的feature;Extra-layers对VGG的feature做进一步处理,增加模型对图像的感受野,使extra-layers得到的特征图承载更多抽象信息。待预测的特征图由6种特征图组成,这6种特征图最终通过Pred-Layers(loc-layer 和conf-layer)来得到预测框的坐标信息(loc-layer),置信度信息(conf-layer)和类别信息(conf-layer)。
6种特征图说明:
- 两个来自VGG部分(38, 19),其特点是特征图尺寸大,意味着丢失信息少,可以识别较小目标;处理层数浅,感受野小,意味着抽象信息少,准确度不高。
- 四个来自Extra部分(10, 5, 3, 1),其特点与VGG部分相反,这也是Extra的意义所在——弥补VGG部分的不足。
代码模型图(模型为SSD300,数据集为VOC(类别+置信度=21)为例)如下:
从上图可以看到六个特征图的尺寸:[38, 19, 10, 5, 3, 1],在Predict Layers中可以看到每个特征图中的每个像素点对应的先验框个数为:[4, 6, 6, 6, 4, 4] 。
模型计算流程:
- 模型通过Base部分得到两个特征图(1, 512, 38, 38)和(1, 1024, 19, 19)
- 通过extra部分得到四个特征图(1, 512, 10, 10),(1, 256, 5, 5),(1, 256, 3, 3)和(1, 256, 1, 1)
- 这6个特征图再通过loc_layers和conf_layers分别得到坐标和置信度:
(1, 512, 38, 38) =》 (1, 4*4, 38, 38) 和 (1, 4*21, 38, 38)
(1, 1024, 19, 19) =》 (1, 6*4, 19, 19) 和 (1, 6*21, 19, 19)
(1, 512, 10, 10) =》 (1, 6*4, 10, 10) 和 (1, 6*21, 10, 10)
(1, 256, 5, 5) =》 (1, 6*4, 5, 5) 和 (1, 6*21, 5, 5)
(1, 256, 3, 3) =》 (1, 4*4, 3, 3) 和 (1, 4*21, 3, 3)
(1, 256, 1, 1) =》 (1, 4*4, 1, 1) 和 (1, 4*21, 1, 1)
- 最终得到所有预测框的loc:(1, 8732, 4)和conf:(1, 8732, 21)
- 输出有预测框的loc_p:(1, 8732, 4),con_p:(1, 8732, 21)和先验框anchors:(8732, 4)
- 根据上步输出的先验框anchors和训练数据的标签信息(坐标和类别),得到先验框转为真实坐标的偏移系数(loc_t)和先验框的置信度/类别(conf_t)
计算目标实体框与先验框anchors的IOU shape: [box_a.size(0), box_b.size(0)] => [num_objs, 8732]
获取每个目标实体框对应的最优先验框anchor shape: [1, num_objs]
获取每个先验框对应的最优目标实体框truth shape: [1, 8732]
IOU值的范围是[0, 1],为了突出针对ground_truth的最优anchors,将最优anchors的IOU值设置为2
每个先验框anchor对应目标ground_truth的真实坐标 Shape: [8732, 4]
每个先验框anchor对应目标ground_truth的类别标签 Shape: [8732](每个先验框的值对应一个类别)
把IOU小于阈值的设置为非置信先验框
根据ground_truth坐标信息和先验框坐标信息,得到先验框坐标转为ground_truth坐标的偏移系数(offsets)
- 根据以上得到的loc_p(置信先验框转为ground_truth预测的偏移系数),loc_t(置信先验框转为ground_truth真实的偏移系数)计算偏移系数损失
- 根据以上得到的con_p(预测先验框的置信度和类别),conf_t(真实先验框的置信度和类别)计算类别损失。
更加详细介绍见GitHub代码
参考:
小小将:目标检测|SSD原理与实现
小纸屑:SSD物体检测算法详解