SSD也是one stage的检测。one stage的特点是:均匀的在图片的不同位置进行密集抽样,抽样采用不同的尺寸和长宽比,然后利用CNN提取特征之后,直接进行回归和分类。整个过程只有一步。它的优势是速度快,但是密集采样会导致正负样本(前景和背景)及其不均衡,使得模型准确度较低。下面来看看two stage和one stage在mAP和speed上的差异。
SSD采用CNN直接进行检测。不像YOLO1在全连接层之后再做检测。SSD相比于YOLO1还有两个亮点:
YOLO1的缺点是难以检测小物体,SSD的这些改进点可以克服这些缺点。
首先详细说说SSD的特点:
CNN网络的特征图会渐渐降低大小,比较靠前的特征图尺度比较大,靠后的特征图尺度较小。较大的特征图可以检测小物体:大的特征图可以划分出更多的小单元;较小的可以检测大物体
首先全连接层会有大量的参数,而且需要固定输入。这样就没烦恼啦
每个检测单元都会根据其特征图的大小设置4或6个prior box。而且不同于YOLO1,YOLO1中每个cell预测的bbox都只能预测一个类别,但这里的prior box都会输出一套独立的检测值:
SSD本已VGG16作为基础,然后增加了新的卷积层获得更多特征用于检测。
分别将VGG16的全连接层fc6和fc7转换成 3 × \times × 3 卷积层 conv6和 1 × \times × 1 卷积层conv7,同时将池化层pool5由原来的stride=2的 2 × \times × 2 变成stride=1的 3 × \times × 3 (猜测是不想reduce特征图大小),为了配合这种变化,采用了一种Atrous Algorithm,其实就是conv6采用扩展卷积或带孔卷积(Dilation Conv),扩展率为6。然后移除dropout层和fc8层,并新增一系列卷积层,在检测数据集上做finetuing。
Conv4_3层作为检测的第一个特征图38 × \times × 38.但是他比较靠前,norm比较大,在其后增加了一个L2 Normalization层:它在channel维度上对每个像素点做归一化,而BN是在[batch,height,width]三个维度上做归一化。
从后面新增的卷积层中提取Conv7,Conv8_2,Conv9_2,Conv10_2,Conv11_2作为检测所用的特征图,加上Conv4_3层,共提取了6个特征图。不同特征图上先验框数目不同。先验框的设置,包括尺度(或者说大小)和长宽比两个方面。对于先验框的尺度:
以feature map上每个点的中点为中心,生成一些列同心的prior box
正方形prior box最小边长为和最大边长为:
m i n s i z e min_size minsize
m i n s i z e ∗ m a x s i z e \sqrt{min_size*max_size} minsize∗maxsize
设置一个aspect ratio,会程程两个长方形:
长: a s p e c t r a t i o ∗ m i n s i z e \sqrt{aspect ratio}*min_size aspectratio∗minsize
宽: 1 / a s p e c t r a t i o ∗ m i n s i z e 1/\sqrt{aspect ratio}*min_size 1/aspectratio∗minsize
每个feature map对应prior box的min_size和max_size由以下公式决定:
公式中的 m 是指进行预测时使用feature map的数量,如SSD300使用conv4-3等6个feature maps进行预测,所以 m=6 。同时原文设定s m i n _{min} min=0.2 ,s m a x _{max} max=0.9 。
则:
对于conv4-3: k=1 , m i n _ s i z e = s 1 ∗ 300 min\_size=s_1 *300 min_size=s1∗300 , m a x _ s i z e = s 2 ∗ 300 max\_size=s_2*300 max_size=s2∗300
对于conv-7:k=2 , m i n _ s i z e = s 2 ∗ 300 min\_size=s_2 *300 min_size=s2∗300 , m a x _ s i z e = s 3 ∗ 300 max\_size=s_3*300 max_size=s3∗300
但是SSD300中prior box设置有些不同:
SSD使用感受野小的feature map检测小目标,使用感受野大的feature map检测更大目标。
他的过程和faster RCNN过程差不多,都是先softmax选择前景,然后通过bbox regression,然后再编码生成bbox。不同的是,她每个featuremap都只有4或者6个prior box,而且每一层的box大小都不一样。PS只有第2,3,4个feature map有6个prior box。
在训练过程中,首先要确定训练图片中的ground truth(真实目标)与哪个先验框来进行匹配,与之匹配的先验框所对应的边界框将负责预测它。在Yolo中,ground truth的中心落在哪个单元格,该单元格中与其IOU最大的边界框负责预测它。但是在SSD中却完全不一样,SSD的先验框与ground truth的匹配原则主要有两点。首先,对于图片中每个ground truth,找到与其IOU最大的先验框,该先验框与其匹配,这样,可以保证每个ground truth一定与某个先验框匹配。通常称与ground truth匹配的先验框为正样本,反之,若一个先验框没有与任何ground truth进行匹配,那么该先验框只能与背景匹配,就是负样本。一个图片中ground truth是非常少的, 而先验框却很多,如果仅按第一个原则匹配,很多先验框会是负样本,正负样本极其不平衡,所以需要第二个原则。第二个原则是:对于剩余的未匹配先验框,若某个ground truth的 IOU \text{IOU} IOU 大于某个阈值(一般是0.5),那么该先验框也与这个ground truth进行匹配。这意味着某个ground truth可能与多个先验框匹配,这是可以的。但是反过来却不可以,因为一个先验框只能匹配一个ground truth,如果多个ground truth与某个先验框 IOU \text{IOU} IOU 大于阈值,那么先验框只与IOU最大的那个先验框进行匹配。第二个原则一定在第一个原则之后进行,仔细考虑一下这种情况,如果某个ground truth所对应最大 IOU \text{IOU} IOU 小于阈值,并且所匹配的先验框却与另外一个ground truth的 IOU \text{IOU} IOU 大于阈值,那么该先验框应该匹配谁,答案应该是前者,首先要确保某个ground truth一定有一个先验框与之匹配。但是,这种情况我觉得基本上是不存在的。由于先验框很多,某个ground truth的最大 IOU \text{IOU} IOU 肯定大于阈值,所以可能只实施第二个原则既可以了,这里的TensorFlow版本就是只实施了第二个原则,但是这里的Pytorch两个原则都实施了。
首先,寻找与每一个ground truth box有最大的jaccard overlap的default box,这样就能保证每一个groundtruth box与唯一的一个default box对应起来
SSD之后又将剩余还没有配对的default box与任意一个groundtruth box尝试配对,只要两者之间的jaccard overlap大于阈值,就认为match(SSD 300 阈值为0.5)。
显然配对到GT的default box就是positive,没有配对到GT的default box就是negative。
尽管一个ground truth可以与多个先验框匹配,但是ground truth相对先验框还是太少了,所以负样本相对正样本会很多。为了保证正负样本尽量平衡,SSD采用了hard negative mining,就是对负样本进行抽样,抽样时按照置信度误差(预测背景的置信度越小,误差越大)进行降序排列,选取误差的较大的top-k作为训练的负样本,以保证正负样本比例接近1:3。
其中 N 是先验框的正样本数量。这里 xp i j _{ij} ij ∈ \in ∈ {1,0}为一个指示参数,当 xp i j _{ij} ij= 1 时表示第 i 个先验框与第 j 个ground truth匹配,并且ground truth的类别为 p 。c 为类别置信度预测值。 l 为先验框的所对应边界框的位置预测值,而 g 是ground truth的位置参数。对于位置误差,其采用Smooth L1 loss,定义如下:
置信度误差,采用softmax loss:
采用数据扩增(Data Augmentation)可以提升SSD的性能,主要采用的技术有水平翻转(horizontal flip),随机裁剪加颜色扭曲(random crop & color distortion),随机采集块域(Randomly sample a patch)(获取小目标训练样本),如下图所示:
对于每个预测框,首先根据类别置信度确定类别(置信度最大值)与置信度值,过滤掉背景的预测框。然后根据置信度阈值过滤掉置信度值较低的预测框。对留下的预测框进行解码,解码之后一般还需要裁剪,防止预测框位置超出图片。解码之后,根据置信度进行降序排列,保留前K个,最后使用NMS算法,过滤掉重叠度较大的预测框。