SSD详解

       目标检测就是要找到一张图中所有的物体和它们的位置,人们通常的做法是先用一些传统视觉的方法如selective search找到proposal,即比较可能是物体的一个区域,然后再用CNN判断这个物体究竟是不是物体,是哪个物体,以及用CNN去优化这个框的位置,这种方法最典型的代表就是RCNN和Fast-RCNN。

selective search

        目标识别(objec recognition)是指明一幅输入图像中包含那类目标。其输入为一幅图像,输出是该图像中的目标属于哪个类别(class probability)。而目标检测(object detection)除了要告诉输入图像中包含了哪类目前外,还要框出该目标的具体位置(bounding boxes)。

      在目标检测时,为了定位到目标的具体位置,通常会把图像分成许多子块(sub-regions / patches),然后把子块作为输入,送到目标识别的模型中。分子块的最直接方法叫滑动窗口法(sliding window approach)。滑动窗口的方法就是按照子块的大小在整幅图像上穷举所有子图像块。和滑动窗口法相对的是另外一类基于区域(region proposal)的方法。selective search就是其中之一!

selective search算法流程

step0:生成区域集R(R中的每个元素都包含了该区域的位置,尺寸,颜色特征,纹理特征等信息)具体参见论文《Efficient Graph-Based Image Segmentation》

step1:获得原始区域集R中相交的区域。计算两个原始区域集R中相交区域的相似度S={s1,s2,…} 
step2:找出相似度最高的两个区域(设为(a, b)),将其合并为新集c,添加进R 
step3:从S中移除所有与step2中有关的子集 ,即将所有包含a或b的区域对(设为(a, x),(b, y),(a, b))及对应的相似度,从S中移除。
step4:计算新集与所有子集的相似度 ,即分别计算区域c与x,y的相似度,并将(c, x): similarity_1和(c, y): similarity_2添加到S中。

step5:跳至step2,直至S为空,我们得到了完整的区域集R’

论文考虑了颜色、纹理、尺寸和空间交叠这4个参数。

颜色相似度(color similarity)

将色彩空间转为HSV,每个通道下以bins=25计算直方图,这样每个区域的颜色直方图有25*3=75个区间。 对直方图除以区域尺寸做归一化后使用下式计算相似度:

                                                 

纹理相似度(texture similarity)

      论文采用方差为1的高斯分布在8个方向做梯度统计,然后将统计结果(尺寸与区域大小一致)以bins=10计算直方图。直方图区间数为8*3*10=240(使用RGB色彩空间)。

                                                  
其中,是直方图中第个bin的值。

尺寸相似度(size similarity)

                                              

保证合并操作的尺度较为均匀,避免一个大区域陆续“吃掉”其他小区域。

例:设有区域a-b-c-d-e-f-g-h。较好的合并方式是:ab-cd-ef-gh -> abcd-efgh -> abcdefgh。 不好的合并方法是:ab-c-d-e-f-g-h ->abcd-e-f-g-h ->abcdef-gh -> abcdefgh。

交叠相似度(shape compatibility measure)

                             

                                 

最终的相似度:

                  

from :https://blog.csdn.net/guoyunfei20/article/details/78723646


      Faster-RCNN解决的问题是省去了selective search,直接用CNN得到最后的结果,并且性能比之前的方法有很大提升。这篇文章主要介绍一下Faster-RCNN中替换掉selective search的RPN(Region Proposal Network)以及对RPN的改进:SSD(Single Shot MultiBox Detector)。

      Faster-RCNN由RPN和Fast-RCNN组成,RPN负责寻找proposal,Fast-RCNN负责对RPN的结果进一步优化。其实RPN已经可以找到图片中每个物体的种类和位置,如果更注重速度而不是精度的话完全可以只使用RPN。RPN是一个全卷积网络(FCN),由于没有全连接层,所以可以输入任意分辨率的图像,经过网络后就得到一个feature map,然后怎么利用这个feature map得到物体的位置和类别那?

       这里要先介绍一下文章中提到的anchor这个概念,把这个feature map上的每一个点映射回原图,得到这些点的坐标,然后着这些点周围取一些提前设定好的区域,如选取每个点周围5x5的一个区域,这些选好的区域可以用来训练RPN。假设我们对feature map上的每个点选取了K个anchor,feature map的大小为H*W*C,那么我们再对这个feature map做两次卷积操作,输出分别是H*W*num_class*K和H*W*4*K,分别对应每个点每个anchor属于每一类的概率以及它所对应的物体的坐标,那么怎么训练这个网络那?

     这个网络的loss function就是一个用于分类的softmax loss和一个用于回归的smooth L1 loss,输出对应的ground truth也很好得到,对于每个anchor,如果它和图片中某个物体的IOU(面积的交/面积的并)大于一个阈值,就认为它属于这一类,否则认为是背景,对于那些是背景的anchor回归的loss就是0,其他anchor位置的ground truth就是它们所对应的物体的位置。RPN其实也很简单,关键的地方就在于选取了一些anchor然后进行pixel-wise的学习。


       但是RPN也有缺点,最大的问题就是对小物体检测效果很差,假设输入为512*512,经过网络后得到的feature map是32*32,那么feature map上的一个点就要负责周围至少是16*16的一个区域的特征表达,那对于在原图上很小的物体它的特征就难以得到充分的表示,因此检测效果比较差。去年年底的工作SSD: Single Shot MultiBox Detector很好的解决了这个问题。

      SSD可以理解为multi-scale版本的RPN,它和RPN最大的不同在于RPN只是在最后的feature map上预测检测的结果,而最后一层的feature map往往都比较抽象,对于小物体不能很好地表达特征,而SSD允许从CNN各个level的feature map预测检测结果,这样就能很好地适应不同scale的物体,对于小物体可以由更底层的feature map做预测。这就是SSD和RPN最大的不同,其他地方几乎一样。下图是SSD的网络结构:

      SSD算法是一种直接预测目标类别和bounding box的多目标检测算法。针对不同大小的目标检测,传统的做法是先将图像转换成不同大小(图像金字塔),然后分别检测,最后将结果综合起来(NMS)。SSD算法则利用不同卷积层的 feature map 进行综合也能达到同样的效果。算法的主网络结构是VGG16,将最后两个全连接层改成卷积层,并随后增加了4个卷积层来构造网络结构。对其中5种不同的卷积层的输出feature map分别用两个不同的 3×3 的卷积核进行卷积,一个输出分类用的confidence,每个default box 生成21个类别confidence;一个输出回归用的 localization,每个 default box 生成4个坐标值(x, y, w, h)。此外,这5个feature map还经过 PriorBox 层生成 prior box(生成的是坐标)。上述5个feature map中每一层的default box的数量是给定的(8732个)。最后将前面三个计算结果分别合并然后传给loss层。

多尺度特征图(Mult-scale Feature Map For Detection)

在图像Base Network基础上,将Fc6,Fc7变为了Conv6,Conv7两个卷积层,添加了一些卷积层(Conv8,Conv9,Conv10,Conv11),这些层的大小逐渐减小,可以进行多尺度预测。

 卷积预测器(Convolutional Predictors For Detection)

     每个新添加的卷积层和之前的部分卷积层,使用一系列的卷积核进行预测。对于一个大小为m*n大小,p通道的卷积层,使用3*3的p通道卷积核作为基础预测元素进行预测,在某个位置上预测出一个值,该值可以是某一类别的得分,也可以是相对于Default Bounding Boxes的偏移量,并且在图像的每个位置都将产生一个值。

默认框和比例(Default Boxes And Aspect Ratio)

     在特征图的每个位置预测K个Box。对于每个Box,预测C个类别得分,以及相对于Default Bounding Box的4个偏移值,这样需要(C+4)*k个预测器,在m*n的特征图上将产生(C+4)*k*m*n个预测值。这里,Default Bounding Box类似于Faster-RCNN中Anchors。
 

Default box

     文章的核心之一是作者同时采用lower和upper的feature map做检测。如图所示,这里假定有8×8和4×4两种不同的feature map。第一个概念是feature map cell,feature map cell 是指feature map中每一个小格子,如图中分别有64和16个cell。

      另外有一个概念:default box,是指在feature map的每个小格(cell)上都有一系列固定大小的box,如下图有4个(下图中的虚线框,仔细看格子的中间有比格子还小的一个box)。假设每个feature map cell有k个default box,那么对于每个default box都需要预测c个类别score和4个offset,那么如果一个feature map的大小是m×n,也就是有m*n个feature map cell,那么这个feature map就一共有(c+4)*k * m*n 个输出。

    这些输出个数的含义:采用3×3的卷积核对该层的feature map卷积时卷积核的个数,包含两部分(实际code是分别用不同数量的3*3卷积核对该层featuremap进行卷积):数量c*k*m*n是confidence输出,表示每个default box的confidence,也就是类别的概率;数量4*k*m*n是localization输出,表示每个default box回归后的坐标

      训练中还有一个东西:prior box,是指实际中选择的default box(每一个feature map cell 不是k个default box都取)。也就是说default box是一种概念,prior box则是实际的选取。训练中一张完整的图片送进网络获得各个feature map,对于正样本训练来说,需要先将prior box与ground truth box做匹配,匹配成功说明这个prior box所包含的是个目标,但离完整目标的ground truth box还有段距离,训练的目的是保证default box的分类confidence的同时将prior box尽可能回归到ground truth box。 举个列子:假设一个训练样本中有2个ground truth box,所有的feature map中获取的prior box一共有8732个。那个可能分别有10、20个prior box能分别与这2个ground truth box匹配上。训练的损失包含定位损失和回归损失两部分。

在上图中,在8*8的feature map只能检测出猫,不能检测出狗。因为在8*8 的default box尺寸中没有狗的尺寸。

(a)SSD在训练期间仅需要每个对象的输入图像和地面实况框。以卷积方式,我们在几个具有不同形状尺寸的特征图(例如,8×8 和4×4 (b)和(c))中的每个位置处评估一组不同宽高比的小集(例如4个)。对于每个默认框,我们预测形状偏移和所有目标类别的置信度(c_{1},c_{2},...,c_{p})。在训练时,我们首先将这些默认框与地面实况框匹配。例如,我们将两个默认框一个与cat匹配,一个与dog匹配,它们被视为正例,其余的为负例(即与地面实况框匹配上的为正例,否则为负例)。模型损失是定位损失(例如smooth L1)和置信度损失(例如Softmax)之间的加权和。

注:同一层的所有特征图共享一组默认框。

PriorBox

      SSD网络中的PriorBox层完成的是给定一系列feature map后如何在上面生成prior box。部署特征图中每个位置(像素点)处的默认框(即计算每个默认框相对于网络输入层输入图像的归一化左上角和右下角坐标以及设置的坐标variance值

      对于输入大小是W×H的feature map,生成的prior box中心就是W×H个,均匀分布在整张图上,在每个中心上,可以生成多个不同长宽比的prior box,如[1/3, 1/2, 1, 2, 3]。所以在一个feature map上可以生成的prior box总数是W×H×length_of_aspect_ratio,对于比较大的feature map,如VGG的conv4_3,生成的prior box可以达到数千个。虽然prior box的位置是在W×H的格子上,但prior box的大小并不是跟格子一样大,而是人工指定的,原论文中随着feature map从底层到高层,prior box的大小在0.2到0.9之间均匀变化。 

     default box 和Faster RCNN中的 anchor 很像。 default box的scale(大小)和aspect ratio(横纵比)要怎么定呢?

      以feature map上每个点的中点为中心(offset=0.5),生成一些列同心的prior box(然后中心点的坐标会乘以step,相当于从feature map位置映射回原图位置)
正方形prior box最小边长为min_size,最大边长为:
每在prototxt设置一个aspect ratio,会生成2个长方形,长宽为 和

                   

      假设我们想要使用m个特征图进行预测。而每个特征图feature map对应de 默认框prior box的尺寸min_size和max_size由以下公式决定:

                            s_{k}=s_{min}+\frac{s_{max}-s_{min}}{m-1}(k-1), k\in [1,m]   

    其中,s_{min} 取为0.2,s_{max} 取为0.9,表示最低层的尺度为0.2,最高层的尺度为0.9,其间的所有层都是规则间隔的。我们对默认框施加不同的宽高比,记为a_{r}\in\left \{ 1,2,3,\frac{1}{2},\frac{1}{3} \right \},由此能够计算每一个默认框的宽度(w_{k}^{a}=s_{k}\sqrt{a_{r}})和高度(h_{k}^{a}=s_{k}/\sqrt{a_{r}})。对于宽高比为1时,我们还添加了一个默认框,其尺寸为 ,由此在每个特征图位置处产生6个默认框。我们设置每个默认框的中心为(\frac{i+0.5}{\left | f_{k} \right |},\frac{j+0.5}{\left | f_{k} \right |}) ,其中 \left | f_{k} \right | 表示第k个方形特征图的大小(即特征图的长/宽)。

    可以看出这种default box在不同的feature层有不同的scale,在同一个feature层又有不同的aspect ratio,因此基本上可以覆盖输入图像中的各种形状和大小的object!通过结合来自多个特征图的所有位置的具有不同尺寸和宽高比的所有默认框的预测,我们具有多种预测,涵盖各种输入目标尺寸和形状。

  • SSD 300(conv4_3、fc7、conv6_2、conv7_2、conv8_2、conv9_2都生成feature map )
  • SSD使用低层feature map检测小目标,使用高层feature map检测大目标

具体到每一个feature map上获得prior box时,会从这6种中进行选择。如下表和图所示最后会得到(38*38*4 + 19*19*6 + 10*10*6 + 5*5*6 + 3*3*4 + 1*1*4)= 8732个prior box。

caffe中设置的参数

layer {
  name: "fc7_mbox_priorbox"
  type: "PriorBox"
  bottom: "fc7"
  bottom: "data"
  top: "fc7_mbox_priorbox"
  prior_box_param {
    min_size: 60.0
    max_size: 111.0
    aspect_ratio: 2
    aspect_ratio: 3
    flip: true
    clip: false
    variance: 0.1  #4个variance,这实际上是一种bounding regression中的权重
    variance: 0.1
    variance: 0.2
    variance: 0.2
    step: 16
    offset: 0.5
  }

    step参数本质上是该层的特征图相对于网络输入层输入图像的下采样率,用于计算当前特征图上某一位置处所有默认框中心坐标在网络输入层输入图像坐标系下的坐标。举个例子,就是你在缩放一幅图像时,对于缩放后的图像,其上每一像素点的像素值是通过插值得到的,那如何有效插值就需要用到后向计算,即需要找出当前像素点坐标值对应于原始图像上的坐标值,由原始图像上这一坐标值来最邻近或双线性插值,重点就在于需要找出原始图像上的坐标值。而这里的step就是用来计算特征图上某一位置处所有默认框中心坐标在网络输入层输入图像坐标系下的坐标,对应的就是下采样率,拿conv4_3而言,下采样率为38/300约为8(实际上就是8,因为经过三次最大池化操作,但由于caffe中的池化采用向上取整,导致约等于8),故step=8。

网络结构

                  

  SSD的结构在VGG16网络的基础上进行修改,训练时同样为conv1_1,conv1_2,conv2_1,conv2_2,conv3_1,conv3_2,conv3_3,conv4_1,conv4_2,conv4_3(38*38*512),conv5_1,conv5_2,conv5_3;

fc6经过3*3*1024的卷积(VGG16中的fc6是全连接层,这里变成卷积层,fc7层同理)fc7经过1*1*1024的卷积.

然后一方面:针对conv4_3(4),fc7(6),conv6_2(6),conv7_2(6),conv8_2(4),conv9_2(4)(括号里数字是选取的default box种类)中的每一个featuremap再分别采用两个3*3大小的卷积核进行卷积,这两个卷积核是并列的.

    上图中SSD的数字8732表示所有prior box的数量,是这么来的38*38*4+19*19*6+10*10*6+5*5*6+3*3*4+1*1*4=8732,这两个3*3的卷积核一个是用来做localization的(回归用,如果prior box是6个,那么就有6*4=24个这样的卷积核,卷积后map的大小和卷积前一样,因为pad=1),另一个是用来做confidence的(分类用,如果prior box是6个,VOC的object类别有20个,那么就有6*(20+1)=126个这样的卷积核)。

一开始看SSD的时候很困扰我的一点就是形状的匹配问题:SSD用卷积层做bbox的拟合,输出的不应该是feature map吗,怎么能正好输出4个坐标呢?这里的做法有点暴力,比如需要输出W×H×length_of_aspect_ratio×4个坐标,就直接用length_of_aspect_ratio×4个channel的卷积层做拟合,这样就得到length_of_aspect_ratio×4个大小为W×H的feature map,然后把feature map拉成一个长度为W×H×length_of_aspect_ratio×4的向量,用SmoothL1之类的loss去拟合,效果还意外地不错……

                                                           Fig.5 SSD 流程

    这里的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]

比如你卷积后的维度是32×24×19×19,那么经过交换层后就变成32×19×19×24,顺序变了而已。而flatten层的作用就是将32×19×19×24变成32*8664,32是batchsize的大小。

从图可以看到,在conv4_3 feature map网络pipeline分为了3条线路:

  • 对于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的caffe blob channel值为4 * 4 = 16。
  • fc7每个点有6个prior box。
  • 经过一系列caffe blob shape变化后,最后拼接成mbox_conf和mbox_loc。而mbox_conf后接reshape,再进行softmax。
  • 最后这些值输出detection_out_layer,获得检测结果。

         

                                                

     如上图,我们是将6个分支合并成一个向量:,然后对该向量进行变形成21*N的矩阵,(N=4w1h1+6w2h2+...)这个矩阵是我们的参数矩阵W,乘以特征图x,得到输出T*1的向量logits,然后求softmax函数。

T类  N表示前一层特征层flatten后的数字   fltten后的特征      无限大小的T类                    从0-1的T类向量              

     

训练:

选择用于检测的default box和尺度集合、难样本挖掘、数据增广策略。

  • 匹配策略: 训练阶段建立真实标签和默认框对应关系,真实标签从默认框中选择。开始先匹配每个真实标签框与默认框最好的jaccard重叠,确保每个真实标签框有一个匹配的默认框,然后匹配与真实框jaccard重叠高于阈值0.5的默认框。这样就允许网络对多个重叠的默认框预测获得高置信度,而不是只选择最大重叠的一个。

Matching strategy:

    上面得到的8732个目标框经过Jaccard Overlap筛选剩下几个了;其中不满足的框标记为负数,其余留下的标为正数框。紧随其后:

                        

在训练时,groundtruth boxes 与 default boxes(就是prior boxes) 按照如下方式进行配对:

  • 首先,寻找与每一个ground truth box有最大的jaccard overlap的default box,这样就能保证每一个groundtruth box与唯一的一个default box对应起来(所谓的jaccard overlap就是IoU,如下图)。
  • SSD之后将剩余还没有配对的default box与任意一个groundtruth box尝试配对,只要两者之间的jaccard overlap大于阈值,就认为match(SSD 300 阈值为0.5)。
  • 显然配对到GT的default box就是 候选正样本集,没有配对到GT的default box就是候选负样本集

                      

负样本获得(这是一个难例挖掘的过程)

     在目标检测中我们会事先标记好ground_truth,接下来在图片中随机提取一系列sample,与ground_truth重叠率IoU超过一定阈值的(比如0.5),则认为它是positive sample,否则为negative sample,考虑到实际负样本数>>正样本数,我们为了避免network的预测值少数服从多数而向负样本靠拢,取正样本数:负样本数大约为1:3,显而易见,用来训练网络的负样本为提取的负样本的子集,那么,我们当然选择负样本中容易被分错类的困难负样本来进行网络训练

   困难负样本是指容易被网络预测为正样本的proposal,即假阳性(false positive),如roi里有二分之一个目标时,虽然它仍是负样本,却容易被判断为正样本,这块roi即为hard negative,训练hard negative对提升网络的分类性能具有极大帮助,因为它相当于一个错题集。

    如何判断它为困难负样本呢?也很简单,我们先用初始样本集(即第一帧随机选择的正负样本)去训练网络,再用训练好的网络去预测负样本集中剩余的负样本,选择其中得分最高,即最容易被判断为正样本的负样本为困难样本,加入负样本集中,重新训练网络,循环往复,然后我们会发现:我们的网络的分类性能越来越强了。

 

    在生成 prior boxes 之后,会产生很多个符合 ground truth box 的 positive boxes(候选正样本集),但同时,不符合 ground truth boxes 也很多,而且这个 negative boxes(候选负样本集),远多于 positive boxes。这会造成 negative boxes、positive boxes 之间的不均衡。训练时难以收敛。因此对default boxes以confidence loss由高到低排序,取最高的一些值,把将正负样本控制在3:1的范围。

将每一个GT上对应prior boxes的分类loss进行排序:

    对于候选正样本集:选择loss最高的m个 prior box 与候选正样本集匹配 (box 索引同时存在于这两个集合里则匹配成功),匹配不成功则从候选正样本集中删除这个正样本(因为这个正样本loss太低,易被识别,已经很接近 ground truth box 了,不需要再训练);

   对于候选负样本集:选择最高的m个 prior box 与候选负样本集匹配,匹配成功的则留下来作为最后的负样本,不成功剔除出这个候选负样本,因为他们loss不够大,易被识别为背景,训练起来没难度没提升空间。

     举例:假设在这 8732 个 default box 里,经过 FindMatches 后得到候选正样本 P 个,候选负样本那就有 8732−P个。将 prior box 的 prediction loss 按照从大到小顺序排列后选择最高的 M个 prior box。如果这 P 个候选正样本里有 a 个 box 不在这 M 个 prior box 里(说明这a个box误差小,与真实框很接近),将这 a个 box 从候选正样本集中踢出去。如果这 8732−P个候选负样本集中有 b个在这 M 个 prior box(说明这b个box误差大,与真实框很远),则将这b个候选负样本作为正式负样本。即删除易识别的正样本,同时留下典型的负样本,组成1:3的prior boxes样本集合。SSD 算法中通过这种方式来保证 positives、negatives 的比例。

原文:https://blog.csdn.net/Gentleman_Qin/article/details/84403313 

数据扩容:

  • 使用原始图像
  • 采样一个patch,与目标间最小的jaccard overlap为:0.1,0.3,0.5,0.7,0.9.
  • 随机采样一个patch.每个采样的patch大小为原始图像的[0.1,1],aspect ratio在1/2和2之间.当ground truth box的中心在patch中时,保留重叠部分.每个采样的patch被resize到固定大小,并以0.5的概率随机水平翻转。

SSD的损失函数:

SSD的损失函数如图3所示,由每个默认框的定位损失与分类损失构成。

             

   N是match到GT(Ground Truth)的prior box数量;而α参数用于调整confidence loss和location loss之间的比例,默认α=1。其中代表第i个prior box匹配到了第j个class为p类别的GT box。SSD中的confidence loss是典型的softmax loss。

而location loss是典型的smooth L1 loss:

                        

d表示真实框的参数,g表示预测框的参数,\hat{g}表示预测的偏移量。

from:https://blog.csdn.net/a8039974/article/details/77592395

 from:https://blog.csdn.net/qq_36269513/article/details/81782722

from:https://blog.csdn.net/m0_37192554/article/details/81986346

  • 30
    点赞
  • 248
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值