目标检测之SSD详解_一颗磐石的博客-程序员宅基地_ssd目标检测

技术标签: 目标检测  深度学习  

SSD介绍

SSD(Single Shot Multibox Detector)是一种单阶多层的目标检测模型,因为SSD只进行了一次框的预测与损失计算,因此属于One-Stage范畴里的一种主流框架,目前仍被广泛应用。SSD从多个角度对目标检测做出了创新,结合了Faster-RCNN和YOLO各自的优点,使得目标检测的速度相比Faster-RCNN有了很大的提升,同时检测精度也与Faster-RCNN不相上下。

SSD的创新点和优缺点

  1. SSD创新性地在多个不同深度的特征图上进行PriorBox生成、分类、回归,最终融合得到最终的预测结果。这样做的好处是考虑到了不同深度的特征图具有大小不同的感受野,浅层特征图感受野小,适合做小目标检测,但同时浅层特征的语义层次较低,不能帮助网络很好地识别;深层特征具备高层次的语义,但是其感受野较大,适合做大目标检测,容易忽略小目标。SSD在深浅不同的特征图上进行回归,在保证大目标的检测准确率同时也兼顾了小目标的检测;
  2. 提出PriorBox作为强先验知识。PriorBox是在特征图上生成的一系列长宽比不一的长方形方框,用来进行物体位置的预测。作用相当于Anchor,在预测的过程中无需从零开始选择性搜索生成很多个Proposals,而是直接在设定好的PriorBox上进行调整,极大地加快了网络训练和推理的速度。
  3. SSD做了充分的数据增强,包括光学变换和几何变换,为网络提供了充分的训练数据,在保证训练数据分布的前提下扩充了其丰富性,从而有效提升了检测精度。
    数据增强步骤

算法流程框架

在这里插入图片描述
输入图像经过VGGNet之后,又经过改进的深层卷积网络提取更高语义的特征。得到特征图之后,在特征图的每个像素上生成若干个PriorBox,并与GroundTruth经过IOU计算比较分出正、负样本,分别对正负样本进行分类,并对正样本进行偏移预测,根据预测结果计算Loss并参与反向传播运算。下面章节主要就SSD的深层网络结构,PriorBox的生成,分类以及Bounding_box回归结果预测,正、负样本的筛选,损失函数以及SSD的数据流开始分析。

SSD深层网络结构

SSD模型框架图如下所示:
在这里插入图片描述
从图中可以看到SSD的输入图像大小为300×300,BackBone采用VGG16,但是在VGG16的基础上做了进一步地改进。VGG16最后的FC6和FC7两个全连接层被换成了卷积层,同时为了提取更高语义的特征,在VGG16后又增加了多个卷积层,最后利用特定几层得到的特征图进行卷积运算得到分类和回归的预测结果。SSD分别在六张尺寸不同的特征图上(layer[‘Conv4_3’], layer[‘Conv7’], layer[‘Conv8_2’], layer[‘Conv9_2’], layer[‘Conv10_2’], layer[‘Conv11_2’])进行卷积预测,各特征图的结果最终汇聚在一起,满足了不同尺寸目标的检测要求。
注意:
1.原始VGG16的池化层统一大小为2×2,步长为2,而在SSD中。Conv5之后接的MaxPooling大小为3×3,步长为1,这样做的目的是在增大感受野的同时没有降低特征图的分辨率。
2.Conv6使用了空洞数为6,padding为6的空洞卷积,这样做的目的也是为了增大感受野的同时不改变特征图的尺寸。

PriorBox(Default Box)的生成及其类别与位置预测

SSD中提出了PriorBox,PriorBox是原图上一系列的矩形框,其作用类似于Faster-RCNN的Anchors,即提供物体检测框的先验知识,让模型在先验知识的基础上进行学习修正。不同的是Faster-CNN只在最终的特征图上使用Anchor,而SSD在多个不同尺寸(38×38,19×19,10×10,5×5,3×3,1×1)的六张特征图上生成PriorBox,满足多尺度目标的检测;而且Faster-RCNN是在第一阶段对Anchor进行位置修正和筛选得到proposal,再送入第二阶段的RCNN中进行分类和回归,SSD直接将priorbox作为先验的感兴趣区域,在同一阶段内完成分类和回归,这也是One-Stage和Two-Stage的区别。
SSD在选定的每张特征图上,以每个像素点的中心生成4个或者6个长宽比不一的同心长方形,他们以下采样率为比例对应着原图上的一个方框。如下图所示:
在这里插入图片描述
这些长方形的长宽比是事先设定好的,而并非学习来的。论文中作者使用了一个线性递增的公式:
在这里插入图片描述
K的取值为1,2,3,4,5,6,分别对应第4,7,8,9,10,11个卷积层。Sk为第k层对应的尺度, S m i n S_{min} Smin S m a x S_{max} Smax分别设为0.2,0.9,分别表示最浅层和最深层对应原图的比例。基于每一层对应原图的尺度S_k,对于第1、5、6个特征图,每个点对应 了4个PriorBox,因此其宽高分别为{ S k S_k Sk, S k S_k Sk},{ 2 ∗ S k \sqrt{2}*S_k 2 Sk, 1 / 2 ∗ S k 1/\sqrt{2}*S_k 1/2 Sk},{ 1 / 2 ∗ S k 1/\sqrt{2}*S_k 1/2 Sk, 2 ∗ S k \sqrt{2}*S_k 2 Sk}, { S k ∗ S k + 1 \sqrt{S_k*S_{k+1}} SkSk+1 , S k ∗ S k + 1 \sqrt{S_k*S_{k+1}} SkSk+1 },而对于第2、3、4个特征图,每个点对应了6个PriorBox,则 在上述4个宽高值上再增加{ 3 ∗ S k \sqrt{3}*S_k 3 Sk, 1 / 3 ∗ S k 1/\sqrt{3}*S_k 1/3 Sk},{ 1 / 3 ∗ S k 1/\sqrt{3}*S_k 1/3 Sk, 3 ∗ S k \sqrt{3}*S_k 3 Sk}这两种比例的框。
生成PriorBox之后,分别利用3×3的卷积,即可得到每个PriorBox的对应的类别和位置预测量。例如第8个卷积层得到的特征图为10×10×512,每个点对应6个PriorBox,则一共有10×10×6=600个PriorBox,每个PriorBox有21个物体类别的可能性(以PASCAL VOC数据集为例)和4个位置参数,因此经过3×3卷积后,类别特征维度为21×6=126,位置特征维度为4×6=24,即卷积后类别特征图为10×10×126,位置特征图为10×10×24.下图展示了不同特征图的分类和回归的维度情况:
在这里插入图片描述

正、负样本的筛选

经过以上步骤,我们得到了所有PriorBox的预测结果,但是想一下,每张图片上的真实目标数量是很少的,但是我们生成了很多的box,所以其中肯定有很多与真实目标无关的。那么我们怎么判断它与真实目标是否有关系呢?对了,目标检测的标配:NMS,通过计算priorBox与GT_Box的匹配情况:IOU区分正负样本。
1.在判断正、负样本时,IoU阈值设置为0.5,即一个PriorBox与所有 真实框的最大IoU小于0.5时,判断该框为负样本。
2.与真实框有最大IoU的PriorBox,即使该IoU不是此PriorBox与所有 真实框IoU中最大的IoU,也要将该Box对应到真实框上,这是为了保证 真实框的Recall。
3.在预测边框位置时,SSD与Faster RCNN相同,都是预测相对于预 选框的偏移量,因此在求得匹配关系后还需要进行偏移量计算。
确定好正负样本之后,我们会发现正负样本严重不均衡,在此SSD使用难样本挖掘,难样本挖掘是针对负样本而言的。具体方法是计算出所以负样本的损失进行排序,选取损失较大的TOP-K个负样本,这里的K设为正样本数量的3倍。在Faster-RCNN中是通过限制正负样本的数量来保证样本均衡,SDD则采用了限制正负样本的比例。

损失计算

筛选到正、负样本之后,便可以计算样本带来的分类置信损失和定位损失,如下图所示,SSD的最终损失是这两种损失的加权和。
在这里插入图片描述
计算分类置信损失的时候,SSD采用交叉熵损失;计算定位损失时采用Smoth-L1损失。Smoth-L1损失函数的表达式如下所示:
在这里插入图片描述
采用Smoth-L1损失的原因是为了在加快模型收敛的同时避免梯度爆炸,因为误差较小时,采用平方求导,梯度增大为原来的两倍,加快优化速度;当误差较大时,求导为1,避免了梯度过大,造成梯度爆炸,以及模型优化过程中的震荡。

总结

SSD以VGGNet为基本骨架,并在此基础上添加额外的卷积层用以提取更高语义的特征,而且还采用了空洞卷积和步长为1的MaxPooling,增大感受野的同时保持特征图的尺寸不变。SSD创新性地提出在多张不同尺寸的特征图上进行PriorBox的生成及通过卷积运算得到预测结果,兼顾了在不同感受野上进行目标检测,从而对大目标和小目标检测的效果都相对较好。SSD将生成的PriorBox作为具有先验知识的方框,直接参与预测与Loss计算,将Proposal的生成和分类回归划分到同一阶段,形成可以端到端训练的一阶模型。在正、负样本的筛选上采取控制正负样本比例完成,而非控制正负样本的数量,可以有效保证所有的正样本参与Loss计算。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Just_do_myself/article/details/115466153

智能推荐

Linux TCP反向连接shellcode_weixin_34395205的博客-程序员宅基地

x64LinuxreverseTCPconnectshellcode(77to85bytes,90to98withpassword)/**Author:SeanDillon*Copyright:(c)2014CAaNES,LLC.(http://caanes.com)*Release...

坑!_adx33526的博客-程序员宅基地

2018.2.28excrt合并模线性方程的时候,解不定方程得到的$x$,一定要弄小,否则容易在乘的过程中炸掉long long2018.3.2线性基取最大异或和的时候不一定包含所有基向量,而是回代后,所有数的异或和。2018.3.4数组一定不能开小。读写未被分配的内存会发生奇怪的事情。比如在I/O中莫名奇妙Runtime Er...

FastDFS+Nginx-文件服务部署_yylの博客的博客-程序员宅基地

FastDFS+Nginx-文件服务部署文章目录FastDFS+Nginx-文件服务部署1-首先是各种安装包下载2-安装依赖3-编译安装libfatscommon4-安装FastDFS4.1-配置启动tracker4.2-配置启动storage5-查看连接信息6-测试上传文件6.1-修改client配置6.2-测试上传文件6.3-下载文件7-想要通过浏览器直接下载文件(通过nginx+fdfs的模块)7.1编译nginx+fastdfs-nginx-module1-首先是各种安装包下载nginx-1.

AFNetworking 2.X 迁移 [email protected]酷的博客-程序员宅基地

AFNetworking是一款在OS X和iOS下都令人喜爱的网络库。为了迎合iOS新版本的升级, AFNetworking在3.0版本中删除了基于NSURLConnection API的所有支持。如果你的项目以前使用过这些API,建议您立即升级到基于NSURLSession 的API的AFNetworking的版本。本指南将引导您完成这个过程。本指南是为了引导使用AFNetworki

C语言实现的linux下ls命令_OldJohn86的博客-程序员宅基地

用C语言实现linux下的ls -l命令。与文件相关的结构体、函数等等知识请看"stat结构体以及文件相关函数"[cpp] view plaincopy#include     #include     #include     #include     #include     #include   

最新的ndkr20编译c_NDK编译c程序_weixin_39610964的博客-程序员宅基地

大家都知道NDK可以用C/C++为Android编写动态库,这个网络上和NDK里面文档和例子都讲的很清楚。可能有时候需要用C/C++为Android实现一个可执行程序。今天学习了下,其实很简单,基本和编写.so差不多,就是配置有点改变。至于如何搭建NDK开发环境,就不再说了,之前有写过相关的文章(Android学习笔记之NDK开发环境配置(WIN32))。在写详细步骤之前,强烈建议大家仔细阅读ND...

随便推点

java获取set方法_Java使用entrySet方法获取Map集合中的元素_简甜XIU09161027的博客-程序员宅基地

本文为大家分享了使用entrySet方法获取Map集合中元素的具体代码,供大家参考,具体内容如下/*---------------------------------使用entrySet方法取出Map集合中的元素:....该方法是将Map集合中key与value的关系存入到了Set集合中,这个关系的数据类型是Map.Entry....entrySet方法返回值类型的具体写法为:Set< Ma...

四氨基苯基卟啉铜cas67595-97-5 TAPP-Cu(2+)的保存条件_遇见齐岳的博客-程序员宅基地

卟啉是由四个吡咯环在α位以不饱和次甲基桥连接而成的高度共轭的大环化合物,卟啉,金属卟啉及其衍生物在生物体中发挥关键作用,例如,存在于血液中的铁卟啉和铜卟啉,叶绿素中的镁卟啉,维生素B12中的钴卟啉化合物,它们都是金属卟啉的衍生物。卟啉杰出的电磁性质,独特的电子性质以及极好的稳定性使得它们可以应用在许多领域,如酶催化、分子识别、发光装置、传感器、太阳能转换电池、光动力学治疗和非线性光学。此外,卟啉还可以作为抗癌药物,生物显色试剂等,卟啉在材料方面也有广泛的应用。密度泛函理论((Density Function

rabbitmq二进制安装_weixin_30613343的博客-程序员宅基地

一、erland的安装1、首先测试一下是否已经安装了erlang,命令rpm -qa | grep erlang2、没有安装则用yum安装yum install erlang -y二、下载rabbitmq二进制包wget https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.15/rabbitm...

android item弹出popupwindow recycleview_点击RecycleView或者ListView每个item显示一个对话框(Popupwindow实现)..._爱reo樱桃的纱雾酱的博客-程序员宅基地

public void showPopupWindow(View clickedItem, Profile profile) {// clickedItem 是点击的那个item的view对象, profile是数据可以自己定义View avatarInRecyclerMemberItem = clickedItem.findViewById(R.id.item_settings_group_av...

[记录]springboot+mysql存储emoji问题_二次元怪兽的博客-程序员宅基地

项目场景:小程序里面评论 存储emoji报错问题描述:插入emoji时 抛异常Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x9D\xE6\xB1...' for column 'nick' at row 1 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1084) ~[mysql-connector-java-5.1.30.

c语言调用编译程序,用C++语言,调用标准C语言编译器编程的库_刘为龙的博客-程序员宅基地

当我们调用的函数实现是*.c,而不是*.cpp时,如果不注意,在Visual C++编译器中编译,会报错。error LNK2019,无法解析的外部符号“**************”(?*******)该符号在函数***中被引用。这是在C++中调用C的代码,我们必须对C的代码进行处理,才能给顺利通过。有三种方法:1、修改C代码的头文件,假设其头文件为Max.h,其调用的函数为int Max(in...

推荐文章

热门文章

相关标签