Reference:https://blog.csdn.net/jy001227801/article/details/80388192
https://blog.csdn.net/a8039974/article/details/77592395
SSD具有如下主要特点:
- 从YOLO中继承了将detection转化为regression的思路,同时一次即可完成网络训练
- 基于Faster RCNN中的anchor,提出了相似的prior box;
- 加入基于特征金字塔(Pyramidal Feature Hierarchy)的检测方式,相当于半个FPN思路
算法概述:
ssd算法是一种直接预测目标类别和bounding box的多目标检测算法。与传统的faster rcnn相比,该算法没有生成 region proposal 的过程,因此极大提高了检测速度。
ssd算法的结构如下:
- SSD模型的第一环节是特征提取。特征提取可以采用主流的一些卷积模型(如VGG,Inception等),特征提取时的不同卷积层feature map的输出将同时送到到下一环节”检测“。
-
SSD模型的第二环节是检测。SSD使用低层feature map检测小目标,使用高层feature map检测大目标。检测环节采用一系列的小卷积模块(
3*3
,1*1
)来预测物体的类别与坐标。由于上一层输入的不同层数的feature map有不同的感受野,因此检测环节可以认为是对不同尺寸的图像进行回归和分类。检测环节可以细分成如下几个子模块。- box generator: 针对不同卷积层(如
19*19
,10*10
)的feature map cell(feature map中的每个小格子),产生不同尺寸(scale)、不同纵横比(aspect ratios)的default boxes。 - classification: 上述的default boxes通过classification预测对应feature map cell的类别(C+1类别, C为所有分类,1为背景)
- localization:上述的default boxes通过localization预测对应feature map cell的坐标
- box generator: 针对不同卷积层(如
- SSD模型的第三环节是损失计算。该环节主要用于训练过程,损失函数包括Classification loss 和Localization losses。通过损失的最小化,缩短Classification 和Localization的预测误差。
-
SSD模型的第四环节是后处理。 该环节主要用于验证过程,通过NMS(非极大值抑制)筛选出置信度最高、存在目标的区域。
注:后文出现的default box和anchor, anchor box的意思均指同一个box。
Box generator:
SSD是特征图上的每一个点对应一组预选框。然后每一层中每一个点对应的prior box的个数由PriorBox这一层的配置文件决定的。拿conv4-3对应的priorbox来说,caffe的模型配置文件如下:
SSD生成对应的四个priorbox框的生成过程:
- 以feature map上每个点的中点为中心(offset=0.5),生成一些列同心的prior box(然后中心点的坐标会乘以step,相当于从feature map位置映射回原图位置)
- 先以 min_size为宽高生成一个框。(第一个)
- 如果存在max_size则用sqrt(min_size_ * max_size_),生成一个框。(第二个)
- 然后根据 aspect_ratio,再去生成。如上面的配置文件,aspect_ratio=2,那么会自动的再添加一个aspect_ratiod = 1/2,然后根据下面的计算方法:
分别生成两个框,一个对应 ar = 2 一个对应 ar= 1/2。(第三个、第四个)
总结:
min_size和max_size会分别生成一个正方形的框,aspect_ratio参数会生成2个长方形的框。
所以输出框的个数 :prior_box_num = count(min_size)*1+count(max_size)*1+count(aspect_ratio)*2。
注:min_size是必须要有的参数,否则不会进入对应的框的生成过程。
还有一个比较关键的参数,就是step,在conv4-3中设置为8,这个又是怎么来的呢?还是用一个表来看一下:
name | Out_size | Cal_scale | Real_scale |
conv4-3 | 38x38 | 7.8 | 8 |
fc7 | 19x19 | 15.78 | 16 |
conv5-2 | 10x10 | 30 | 32 |
conv7-2 | 5x5 | 60 | 64 |
conv8-2 | 3x3 | 100 | 100 |
conv9-2 | 1x1 | 300 | 300 |
Cal_scale = 300/out_size,实际就是原图与特征图大小的比值,比如conv4-3 width = 38 ,输入的大小为300,那么scale=7.8,所以这里设置的step=8。代码中实现如下:
这一部分的计算过程可以在 prior_box_layer.cpp的Forward_cpu中看到。
Classification & Localization:
从上图可以看到,在conv4_3 feature map网络pipeline分为了3条线路:
后续通过softmax分类+bounding box regression即可从priox box中预测到目标。其实pribox box的与Faster RCNN中的anchor非常类似,都是目标的预设框,没有本质的差异。区别是每个位置的prior box一般是4~6个,少于Faster RCNN默认的9个anchor;同时prior box是设置在不同尺度的feature maps上的,而且大小不同。
- 经过一次batch norm+一次卷积后,生成了[1, num_class*num_priorbox, layer_height, layer_width]大小的feature用于softmax分类目标和非目标(其中num_class是目标类别,SSD 300中num_class = 21)。
- 经过一次batch norm+一次卷积后,生成了[1, 4*num_priorbox, layer_height, layer_width]大小的feature用于bounding box regression(即每个点一组[dxmin,dymin,dxmax,dymax])就是偏移量。
- 生成了[1, 2, 4*num_priorbox]大小的prior box blob,其中2个channel分别存储prior box的4个点坐标和对应的4个variance。
还有一个细节就是上面prototxt中的4个variance,这实际上是一种bounding regression中的权重。在上图线路(2)中,网络输出[dxmin,dymin,dxmax,dymax],即对应下面代码中bbox;然后利用如下方法进行针对prior box的位置回归:
decode_bbox->set_xmin( prior_bbox.xmin() + prior_variance[0] * bbox.xmin() * prior_width);
decode_bbox->set_ymin( prior_bbox.ymin() + prior_variance[1] * bbox.ymin() * prior_height);
decode_bbox->set_xmax( prior_bbox.xmax() + prior_variance[2] * bbox.xmax() * prior_width);
decode_bbox->set_ymax( prior_bbox.ymax() + prior_variance[3] * bbox.ymax() * prior_height);
上述代码可以在SSD box_utils.cpp的void DecodeBBox()函数见到。
Permute,Flatten And Concat
SSD 300是使用包括conv4_3在内的共计6个feature maps一同检测出最终目标的。在网络运行的时候显然不能像图6一样:一个feature map单独计算一次softmax socre+box regression(虽然原理如此,但是不能如此实现)。那么多个feature maps如何协同工作?这时候就要用到Permute,Flatten和Concat这3种层了。其中conv4_3_norm_conf_perm的prototxt定义如下:
layer {
name: "conv4_3_norm_mbox_conf_perm"
type: "Permute"
bottom: "conv4_3_norm_mbox_conf"
top: "conv4_3_norm_mbox_conf_perm"
permute_param {
order: 0
order: 2
order: 3
order: 1
}
}
注:使用CAFFE的同学都知道 ,CAFFE的数据结构是 NCHW的形式(N:样本个数, C:通道数,H:高,W:宽),而SSD的 XX_conf 和 XX_loc层的输出,是用通道来保存特征向量的,所以这里需要将通道数调整到最后,也就是 permute所做的事情,通过该层后,数据的顺序被换成了 NHWC,再通过 flatten拉成一列。如下图所示:
Permute是SSD中自带的层,上面conv4_3_norm_mbox_conf_perm的的定义。Permute相当于交换caffe blob中的数据维度。
在正常情况下caffe blob的顺序为:bottom blob = [batch_num, channel, height, width]
经过conv4_3_norm_mbox_conf_perm后的caffe blob为:top blob = [batch_num, height, width, channel]
上展示了conv4_3和fc7合并在一起的过程中caffe blob shape变化(其他层类似)。
- 对于conv4_3 feature map,conv4_3_norm_priorbox(priorbox层)设置了每个点共有4个prior box。由于SSD 300共有21个分类,所以conv4_3_norm_mbox_conf的channel值为num_priorbox * num_class = 4 * 21 = 84;而每个prior box都要回归出4个位置变换量,所以conv4_3_norm_mbox_loc的channel值为4 * 4 = 16。
- fc7每个点有6个prior box,其他feature map同理。
- 经过一系列图7展示的caffe blob shape变化后,最后拼接成mbox_conf和mbox_loc。而mbox_conf后接reshape,再进行softmax(为何在softmax前进行reshape,Faster RCNN有提及)。
- 最后这些值输出detection_out_layer,获得检测结果。
总结:
SSD的最后几层的输出信息都是保存在Channel这一维度的,而一个LOC+CONF+PRIOR的模块可以认为等效于一个 Faster-rcnn的最后的回归+分类过程,通过将这些子模块的特征拼接起来,得到一组特征向量,达到提取多尺度特征的目的(多个F-RCNN同时工作于同一图片的不同尺度上)。
Loss:
损失函数定义为位置误差(locatization loss, loc)与置信度误差(confidence loss, conf)的加权和。也可以说是:三部分的loss:前景分类的loss、背景分类的loss、位置回归的loss。
- 公式中Lconf (x,c)是前景的分类loss和背景的分类loss的和,Lloc (x,l,g)是所有用于前景分类的anchor的位置坐标的回归loss。
- 公式里的N表示被选择用作前景分类的anchor的数目
- 在源码中把IOU>0.5的anchor都用于前景分类,在IOU<0.5的anchor中选择部分用作背景分类。
- 只选择部分的原因是背景anchor的数目一般远远大于前景anchor,如果都选为背景,就会弱化前景loss的值,造成定位不准确。在作者源码中背景分类的anchor数目定为前景分类anchor数的三倍来保持它们的平衡。
- 权重系数α通过交叉验证设置为1
confidence loss是典型的softmax loss:
其中,当xpij=1时表示第i个先验框与第j个ground truth匹配,并且ground truth的类别为p。c为类别置信度预测值.
location loss是典型的smooth L1 loss:
l为先验框的所对应边界框的位置预测值,而g是ground truth的位置参数。
总结:
整个loss的选取如下图,这只是个示意图,每个点的anchor被定死成了6个来方便演示,实际应用时不同层级是不一样的:
Train:
在训练时,ground-truth boxes 与 default boxes(就是prior boxes) 按照如下方式进行配对:
- 首先,寻找与每一个ground truth box有最大的IoU的default box,这样就能保证每一个groundtruth box与唯一的一个default box对应起来。
- 然后,又将剩余还没有配对的default box与任意一个groundtruth box尝试配对,只要两者之间的IoU大于阈值(SSD 300 阈值为0.5),就认为match。
- 显然配对到GT的default box就是positive,没有配对到GT的default box就是negative。
数据增强
SSD训练过程中使用的数据增强对网络性能影响很大,大约有6.7%的mAP提升。
(1) 随机剪裁:采样一个片段,使剪裁部分与目标重叠分别为0.1, 0.3, 0.5, 0.7, 0.9,剪裁完resize到固定尺寸。
(2) 以0.5的概率随机水平翻转。
是否在基础网络部分的conv4_3进行检测
基础网络部分特征图分辨率高,原图中信息更完整,感受野较小,可以用来检测图像中的小目标,这也是SSD相对于YOLO检测小目标的优势所在。增加对基础网络conv4_3的特征图的检测可以使mAP提升4%。
使用瘦高与宽扁默认框
数据集中目标的开关往往各式各样,因此挑选合适形状的默认框能够提高检测效果。作者实验得出使用瘦高与宽扁默认框相对于只使用正方形默认框有2.9%mAP提升。
使用atrous卷积
通常卷积过程中为了使特征图尺寸特征图尺寸保持不变,通过会在边缘打padding,但人为加入的padding值会引入噪声,因此,使用atrous卷积能够在保持感受野不变的条件下,减少padding噪声,关于atrous参考。本文SSD训练过程中并且没有使用atrous卷积,但预训练过程使用的模型为VGG-16-atrous,意味着作者给的预训练模型是使用atrous卷积训练出来的。使用atrous版本VGG-16作为预训模型比较普通VGG-16要提高0.7%mAP。
Hard negative mining
值得注意的是,一般情况下negative default boxes数量>>positive default boxes数量,直接训练会导致网络过于重视负样本,从而loss不稳定。在训练时会依据confidience score排序default box,挑选其中confidience高的box进行训练,控制positive:negative=1:3。这样会有更快的收敛和更稳定的结果。