参考文章:第八章_目标检测.md
不用RP,直接在网络中提取特征来预测物体分类和位置
任务:特征提取—>分类/定位回归。
常见的one stage目标检测算法有:OverFeat、YOLOv1、YOLOv2、YOLOv3、SSD和RetinaNet等
SSD的优点就是它生成的 default box 是多尺度的,这是因为SSD生成default box 的 feature map 不仅仅是CNN输出的最后一层,还有利用比较浅层的feature map 生成的default box
a.先验框的设置
SSD中default box的概念有点类似于Faster R-CNN中的anchor。不同于Faster R-CNN只在最后一个特征层取anchor, SSD在多个特征层上取default box,可以得到不同尺度的default box。在特征图的每个单元上取不同宽高比的default box,一般宽高比在{1,2,3,1/2,1/3}中选取,有时还会额外增加一个宽高比为1但具有特殊尺度的box。原文对于300x300的输入,分别在conv4_3, conv7,conv8_2,conv9_2,conv10_2,conv11_2的特征图上的每个单元取4,6,6,6,4,4个default box. 由于以上特征图的大小分别是38x38,19x19,10x10,5x5,3x3,1x1,所以一共得到38x38x4+19x19x6+10x10x6+5x5x6+
3x3x4+1x1x4=8732个default box.对一张300x300的图片输入网络将会针对这8732个default box预测8732个边界框
b.对先验框进行匹配
SSD在训练的时候只需要输入图像和图像中每个目标对应的ground truth(标注框)。先验框与ground truth的匹配遵循两个原则:
(1)对图片中的每个ground truth, 在先验框中找到与其IOU最大的先验框,则该先验框对应的预测边界框与ground truth 匹配
(2)对于(1)中每个剩下的没有与任何ground truth匹配到的先验框,找到与其IOU最大的ground truth,若其与该ground truth的IOU值大于某个阈值(一般设为0.5),则该先验框对应的预测边界框与该ground truth匹配
按照这两个原则进行匹配,匹配到ground truth的先验框对应的预测边界框作为正样本,没有匹配到ground truth的先验框对应的预测边界框作为负样本。尽管一个ground truth可以与多个先验框匹配,但是ground truth的数量相对先验框还是很少,按照上面的原则进行匹配还是会造成负样本远多于正样本的情况。为了使正负样本尽量均衡(一般保证正负样本比例约为1:3),SSD采用hard negative mining(难负例挖掘), 即对负样本按照其预测背景类的置信度进行降序排列,选取置信度较小的top-k作为训练的负样本
c.得到预测的检测结果
最后分别在所选的特征层上使用3x3卷积核预测不同default boxes所属的类别分数及其预测的边界框location。由于对于每个box需要预测该box属于每个类别的置信度(假设有c类,包括背景,例如20class的数据集合,c=21)和该box对应的预测边界框的location(包含4个值,即该box的中心坐标和宽高),则每个box需要预测c+4个值。所以对于某个所选的特征层,该层的卷积核个数为(c+4)x 该层的default box个数.最后将每个层得到的卷积结果进行拼接。对于得到的每个预测框,取其类别置信度的最大值,若该最大值大于置信度阈值,则最大值所对应的类别即为该预测框的类别,否则过滤掉此框。对于保留的预测框根据它对应的先验框进行解码得到其真实的位置参数(这里还需注意要防止预测框位置超出图片),然后根据所属类别置信度进行降序排列,取top-k个预测框,最后进行NMS,过滤掉重叠度较大的预测框,最后得到检测结果
SSD优势是速度比较快,整个过程只需要一步,首先在图片不同位置按照不同尺度和宽高比进行密集抽样,然后利用CNN提取特征后直接进行分类与回归,所以速度比较快,但均匀密集采样会造成正负样本不均衡的情况使得训练比较困难,导致模型准确度有所降低。另外,SSD对小目标的检测没有大目标好,因为随着网络的加深,在高层特征图中小目标的信息丢失掉了,适当增大输入图片的尺寸可以提升小目标的检测效果
算法结构图如所示:结构上主要的特点就是 unified detection(统一检测),不再是原来许多步骤组成的物体检测,这使得模型的运行速度快,可以直接学习图像的全局信息,且可以end-to-end训练
其流程也是非常简单明了的:
1、将图像resize到448×448作为神经网络的输入
2、运行神经网络,得到一些bounding box坐标、box中包含物体的置信度和类别概率
3、进行非极大值抑制,筛选Boxes
YOLO网络借鉴了GoogLeNet分类网络结构,不同的是YOLO使用1×1卷积层和3×3卷积层替代inception module
整个检测网络包括24个卷积层和2个全连接层。其中,卷积层用来提取图像特征,全连接层用来预测图像位置和类别概率值
网络输入图像尺寸大小为448×448,分成7×7的网格,每个网格预测2个边界框;最后的输出是7×7×k的张量
损失函数如下图所示
损失函数分为坐标预测(蓝色框)、含有物体的边界框的confidence预测(红色框)、不含有物体的边界框的confidence预测(黄色框)、分类预测(紫色框)四个部分
参考文章:Yolo系列其二:Yolo_v2
相对于YOLOv1的改进
1.BN层的引入
YOLOv2中在每个卷积层后加Batch Normalization(BN)层,去掉dropout. BN层可以起到一定的正则化效果,能提升模型收敛速度,防止模型过拟合。YOLOv2通过使用BN层使得mAP提高了2%
2.fine tune(微调)时高精度分类器的使用
大部分检测模型都会使用主流分类网络(如vgg、resnet)在ImageNet上的预训练模型作为特征提取器,而这些分类网络大部分都是以小于256×256的图片作为输入进行训练的,低分辨率会影响模型检测能力
当初YOLO模型在训练时先使用224×224的图片输入来预训练自己的特征提取网络;然后再将输入的图片尺度增大到448×448,进而继续使用检测数据集对其进行fine tune。这意味着上述fine tune中网络需要重新学习识别大尺度(448)的图片以及学习进行其上的目标检测工作
在YOLOv2中,在拿到224×224的分类数据集train过的模型后先使用448×448的分类数据集fine tune上10个epochs,然后再使用448×448的目标检测数据集进行接下来的目标检测工作的fine tune
实现表明fine tune时高精度分类器的预先fine tune操作可带来最终目标检测模型近4%的map提升
3.使用卷积操作的Anchor boxes
YOLOv1模型当初直接在特征提取主干网络最后端生成的feature maps上后接FC,然后生成得到预测的目标框的类别、位置等信息
而在YOLOv2中,像Faster-RCNN的RPN网络或者SSD等一样,开始直接使用conv filters来提取生成prior boxes(又叫Anchor boxes)的位置偏移及类别等信息。与其它网络略不同的是YOLOv2特意选了416×416的image size作为输入,这样经过前端的数个特征提取卷积层与pool层后(下采样总步长为32),最终的feature map大小为13×13,恰是个奇数(每个cell预测5个anchor boxes)。这样它就可以有效地预测最中心grid位置的目标(这一trick来自于一个数据集常识即一般我们training用的数据集上,目标往往是在图片的中央区域)
相对于YOLOv1中直接使用FC来预测目标框的类别与位置,使用卷积生成anchor boxes位置与类别的方法会带来mAP约0.3%的下降,但会导致较大的召回率(Recall ratio)提升,约7%。这使得这一模型可进一步改良、提升的空间加大
4.使用K-means cluster来选取Anchor boxes
作者直接在目标检测训练数据集上对所有的目标框进行k-means聚类最终得到了Avg IOU与模型复杂度均不错的anchor boxes组合。如下为所使用的k-means中的距离衡量公式:
d ( b o x , c e n t r o i d ) = 1 − I O U ( b o x , c e n t r o i d ) d(box, centroid) = 1 − IOU(box, centroid) d(box,centroid)=1−IOU(box,centroid)
如下是它在VOC与COCO数据集上的聚类结果。最终在模型训练时选取了k = 5个anchor box
5.直接的目标框位置预测
YOLOv2同RPN等网络一样使用了卷积来生成anchor boxes的位置信息。但它在使用像Faster-RCNN或SSD中那样来进行位置偏离计算的方法来预测predicted box的位置时发现训练时非常容易出现震荡。如下为RPN网络所用的位置计算公式:
x = ( t x ∗ w a ) − x a y = ( t y ∗ h a ) − y a \begin{array}{lcl} x=(t_x ∗ w_a) − x_a \\ \\ y=(t_y ∗ h_a) − y_a \end{array} x=(tx∗wa)−xay=(ty∗ha)−ya
为了消除此一问题,作者使用如下公式直接对目标框位置进行预测。其中 t x , t y , t w , t h , t o t_x, t_y, t_w, t_h, t_o tx,ty,tw,th,to为网络预测得到的值,而 c x 、 c y c_x、c_y cx、cy表示anchor box对图片的相对位置, p w 、 p h p_w、p_h pw、ph是anchor box的长与宽。
b x = σ ( t x ) + c x b y = σ ( t y ) + c y b w = p w e t w b h = p h e t h P r ( o b j e c t ) ∗ I O U ( b , o b j e c t ) = σ ( t o ) \begin{array}{lcl} b_x = σ(t_x) + c_x \\ \\ b_y = σ(t_y) + c_y \\ \\ b_w = p_we^{t_w} \\ \\ b_h = p_he^{t_h} \\ \\ Pr(object) ∗ IOU(b, object) = σ(t_o) \end{array} bx=σ(tx)+cxby=σ(ty)+cybw=pwetwbh=phethPr(object)∗IOU(b,object)=σ(to)
6.细粒度特征的使用
SSD在目标检测时通过使用多尺度的feature maps特征,最终能够cover尺度广泛的目标,从而获得了较高的检测mAP。YOLOv2也吸取了此一优点。但它并不像SSD那样分别在不同的feature maps之上对不同尺度大小的anchor box进行预测,而是将拥有较细粒度特征的层变形后(使得与后面粗粒度的特征层有着一样的size,有些类似于用于super resolution的subpixel层;比如若其细粒度特征层为26×26×512,而最后一层粗粒度特征层的size则为13×13,于是这里会将它变形为13×13×1024从而与最后一个特征层有着一样的size,进行能在channel level上进行合并)与后面粗粒度的特征层结合在一起用于后续的anchor box预测
7.多尺度训练
之前YOLOv1的固定图片输入大小为448×448,而YOLOv2因为Anchor box的引入从而将输入变为了416×416。进一步为了使得模型能够对各种尺度的图片进行有效检测,作者在训练Yolo v2时不再固定image size,而是每训练10个epochs随机地从一个组合{320, 352, …, 608}中选取(注意它们都是32的倍数,因为darknet网络的步长为32)一个数作为输入的image size。此种训练方法被证明可有效地使得网络学会去自动识别各种尺度大小的图片
YOLOv2还采用了有着19个Conv层与5个maxpooling层的darknet-19作为模型的特征提取前端网络。在此网络中引入了BN用于稳定训练,加快收敛,同时防止模型过拟合
参考文章:YOLOv3 深入理解
YOLOv3主要的改进:
YOLOv3核心思想:分而治之
首先通过特征提取网络对特征进行提取,得到特定大小的特征图输出;输入图像分成S×S个网格,当真实框中某个目标的中心点坐标落在某个网格里时,那么就由该网格来预测该目标(计算置信度和分类损失以及回归),没有目标中心点的框就只做置信度损失。每个目标有固定数量的bounding box,YOLOv3中将预测特征图分成了三种不同感受野去预测不同大小的目标(13×13,26×26,52×52)特征图越小感受野越大能预测较大的目标反之感受野越小能预测较小的目标
借鉴了残差网络Residual Network的做法,在一些层之间设置了快捷链路(Shortcut Connection)
上图的Darknet-53网络采用256×256×3作为输入,最左侧那一列的1、2、8等数字表示多少个重复的残差组件。每个残差组件有两个卷积层和一个快捷链路,示意图如下:
YOLOv2曾采用pass through结构来检测细粒度特征,在YOLOv3更进一步采用了3个不同尺度的特征图来进行对象检测
结合上图看,卷积网络在79层后,经过下方几个黄色的卷积层得到一种尺度的检测结果。相比输入图像,这里用于检测的特征图有32倍的下采样。比如输入是416×416的话,这里的特征图就是13×13了。由于下采样倍数高,这里特征图的感受野比较大,因此适合检测图像中尺寸比较大的对象
为了实现细粒度的检测,第79层的特征图又开始作上采样(从79层往右开始上采样卷积),然后与第61层特征图融合(Concatenation),这样得到第91层较细粒度的特征图,同样经过几个卷积层后得到相对输入图像16倍下采样的特征图。它具有中等尺度的感受野,适合检测中等尺度的对象
最后,第91层特征图再次上采样,并与第36层特征图融合(Concatenation),最后得到相对输入图像8倍下采样的特征图。它的感受野最小,适合检测小尺寸的对象
上图中①位置的是1×1的卷积,没有加BN层和激活函数,②位置是3×3的卷积,通过信息融合进行自监督,③位置的卷积集对信息进行融合,④位置是上采样操作,将13×13变为26×26,⑤位置的concatenate可获得上一个尺寸特征更加全局的信息,但更加当前尺寸特征的局部信息(全局信息是通过1×1的卷积,将通道变小的得到的,局部信息的通道更大,所以更加关注局部信息)
随着输出的特征图的数量和尺度的变化,先验框的尺寸也需要相应的调整。YOLOv2已经开始采用K-means聚类得到先验框的尺寸,YOLOv3延续了这种方法,为每种下采样尺度设定3种先验框,总共聚类出9种尺寸的先验框。在COCO数据集这9个先验框是:(10×13),(16×30),(33×23),(30×61),(62×45),(59×119),(116×90),(156×198),(373×326)
分配上,在最小的13×13特征图上(有最大的感受野)应用较大的先验框(116×90),(156×198),(373×326),适合检测较大的对象。中等的26×26特征图上(中等感受野)应用中等的先验框(30×61),(62×45),(59×119),适合检测中等大小的对象。较大的52×52特征图上(较小的感受野)应用较小的先验框(10×13),(16×30),(33×23),适合检测较小的对象
9种先验框的尺寸,下图中蓝色框为聚类得到的先验框。黄色框式ground truth,红框是对象中心点所在的网格
预测对象类别时不使用softmax,改成使用logistic的输出进行预测。这样能够支持多标签对象(比如一个人有Woman和Person两个标签)
对于一个输入图像,YOLOv3将其映射到3个尺度的输出张量,代表图像各个位置存在各种对象的概率
对于一个416×416的输入图像,在每个尺度的特征图的每个网格设置3个先验框,总共有13×13×3 + 26×26×3 + 52×523=10647个预测。每一个预测是一个(4+1+80)=85维向量,这个85维向量包含边框坐标(4个数值),边框置信度(1个数值),对象类别的概率(对于COCO数据集,有80种对象)
参考文章:深入浅出Yolo系列之Yolov3&Yolov4&Yolov5核心基础知识完整讲解
YOLOv4整体结构图:
YOLOv4和YOLOv3算法对比图:
YOLOv4本质上和YOLOv3相差不大,但在算法上有一些创新
使用Mosaic数据增强
使用Mosaic增强主要是因为小目标的AP一般比中目标和大目标低很多,Coco数据集中包括大量小目标且分布不均匀
小目标的定义是目标框的长宽0×0~32×32之间的物体
Coco数据集中小目标占比达到41.4%,数量比中目标和大目标都要多
优点:
①丰富了数据集
随机使用4张图片,随机缩放,再随机分布进行拼接,丰富了检测数据集,特别是缩放增加了很多小目标,让网络的鲁棒性更好
②减少GPU运算量
和常见网络中的Dropout功能相似,也是缓解过拟合的一种正则化方式
①传统的Dropout很简单,一句话就可以说的清:随机删除减少神经元的数量,使网络变得更简单
②中间Dropout的方式会随机的删减丢弃一些信息,但Dropblock的研究者认为,卷积层对于这种随机丢弃并不敏感,因为卷积层通常是三层连用:卷积+激活+池化层,池化层本身就是对相邻单元起作用。而且即使随机丢弃,卷积层仍然可以从相邻的激活单元学习到相同的信息。
因此,在全连接层上效果很好的Dropout在卷积层上效果并不好。
所以右图Dropblock的研究者则干脆整个局部区域进行删减丢弃。
借鉴于2017年的cutout数据增强的方式,cutout是将输入图像的部分区域清零,而Dropblock则是将Cutout应用到每一个特征图。而且并不是用固定的归零比率,而是在训练时以一个小的比率开始,随着训练过程线性的增加这个比率。
DropBlock的研究者与Cutout进行对比验证时。发现有几个特点
①Dropout的效果优于Cutout
②Cutout只能做用于输入层,而Dropout则是将Cutout应用到网络中的每一个特征图上
③Dropout可以定制各种组合,在训练的不同阶段可以修改删减的概率,从空间层面和时间层面,和Cutout相比都有更加精细的改进
SPP模块
在SPP模块中,使用k={1×1,5×5,9×9,13×13}的最大池化的方式,再将不同尺度的特征图进行Concat操作
注意:这里最大池化采用padding操作,移动的步长为1,比如13×13的输入特征图,使用5×5大小的池化核池化,padding=2,因此池化后的特征图仍然是13×13大小
FPN+PAN
YOLOv3中Neck的FPN结构
可以看到经过几次下采样,三个紫色箭头指向的地方,输出分别是76×76、38×38、19×19
最后的Prediction中用于预测的三个特征图①19×19×255、②38×38×255、③76×76×255
YOLOv4中Neck结构
每个CSP模块前面的卷积核都是3×3大小,步长为2,相当于下采样操作。因此可以看到三个紫色箭头处的特征图是76×76、38×38、19×19
最后Prediction中用于预测的三个特征图:①76×76×255,②38×38×255,③19×19×255
和YOLOv3的FPN层不同,YOLOv4在FPN层的后面还添加了一个自底向上的特征金字塔。其中包含两个PAN结构。
这样结合操作,FPN层自顶向下传达强语义特征,而特征金字塔则自底向上传达强定位特征,两两联手,从不同的主干层对不同的检测层进行参数聚合
CIoU_Loss
目标检测任务的损失函数一般由Classificition Loss(分类损失函数)和Bounding Box Regeression Loss(回归损失函数)两部分构成。
Bounding Box Regeression的Loss近些年的发展过程是:Smooth L1 Loss → IoU Loss(2016)→ GIoU Loss(2019)→ DIoU Loss(2020)→ CIoU Loss(2020)
问题2:即状态2和状态3的情况,当两个预测框大小相同,两个IoU也相同,IoU_Loss无法区分两者相交情况的不同
GIoU_Loss
右图GIoU_Loss中,增加了相交尺度的衡量方式,缓解了单纯IoU_Loss时的尴尬
DIoU_Loss
好的目标框回归函数应该考虑三个重要几何因素:
重叠面积、中心点距离,长宽比
一:如何最小化预测框和目标框之间的归一化距离?
二:如何在预测框和目标框重叠时,回归的更准确?
针对第一个问题,提出了DIoU_Loss(Distance_IoU_Loss)
上面三种情况,目标框包裹预测框,本来DIoU_Loss可以起作用,但预测框的中心点的位置都是一样的,因此按照DIoU_Loss的计算公式,三者的值都是相同的
CIou_Loss
CIoU_Loss和DIoU_Loss前面的公式都是一样的,不过在此基础上还增加了一个影响因子,将预测框和目标框的长宽比都考虑了进去
其中v是衡量长宽比一致性的参数,可定义为
各个loss函数不同点
IoU_Loss:主要考虑检测框和目标框重叠面积
GIoU_Loss:在IoU的基础上,解决边界框不重合时的问题
DIoU_Loss:在IoU和GIoU的基础上,考虑边界框中心点距离的信息
CIoU_Loss:在DIoU的基础上,考虑边界框宽高比的尺度信息
DIoU_NMS
在上图重叠的摩托车检测中,中间的摩托车因为考虑边界框中心点的位置信息,也可以回归出来
注意:这里为什么不用CIoU_nms,而用DIoU_nms?
答:因为前面讲到的CIoU_loss,是在DIoU_loss的基础上,添加的影响因子,包含groundtruth标注框的信息,在训练时用于回归
但在测试过程中,并没有ground truth的信息,不用考虑影响因子,因此直接用DIoU_nms即可
参考文章:深入浅出Yolo系列之Yolov5核心基础知识完整讲解
Mosaic数据增强
自适应锚框计算
在YOLO算法中,针对不同的数据集,都会有初始设定长宽的锚框
在网络训练中,网络在初始锚框的基础上输出预测框,进而和真实框ground truth进行比对,计算两者差距,再反向更新,迭代网络参数
因此初始锚框也是比较重要的一部分,比如YOLOv5在Coco数据集上初始设定的锚框。
在YOLOv3、YOLOv4中,训练不同的数据集时,计算初始锚框的值是通过单独的程序运行的
但Yolov5中将此功能嵌入到代码中,每次训练时,自适应的计算不同训练集中的最佳锚框值
当然,如果觉得计算的锚框效果不是很好,也可以在代码中将自动计算锚框功能关闭。控制的代码即train.py中上面一行代码,设置成False,每次训练时,不会自动计算
自适应图片缩放
在常用的目标检测算法中,不同的图片长宽都不相同,因此常用的方式是将原始图片统一缩放到一个标准尺寸,再送入检测网络中
比如YOLO算法中常用416×416,608×608等尺寸,比如对上面800×600的图像进行缩放
作者认为,在项目实际使用时,很多图片的长宽比不同,因此缩放填充后,两端的黑边大小都不同,而如果填充的比较多,则存在信息冗余,影响推理速度。
因此在YOLOv5的代码中datasets.py的letterbox函数中进行了修改,对原始图像自适应的添加最少的黑边。
图像高度上两端的黑边变少了,在推理时,计算量也会减少,即目标检测速度会得到提升。
计算方式
第一步:计算缩放比例
原始缩放尺寸是416×416,都除以原始图像的尺寸后,可以得到0.52,和0.69两个缩放系数,选择小的缩放系数
第二步:计算缩放后的尺寸
原始图片的长宽都乘以最小的缩放系数0.52,宽变成了416,而高变成了312
第三步:计算黑边填充数值
将416-312=104,得到原本需要填充的高度。再采用numpy中np.mod取余数的方式,得到8个像素,再除以2,即得到图片高度两端需要填充的数值
此外,需要注意的是:
a.这里大白填充的是黑色,即(0,0,0),而YOLOv5中填充的是灰色,即(114,114,114),都是一样的效果
b.训练时没有采用缩减黑边的方式,还是采用传统填充的方式,即缩放到416×416大小。只是在测试,使用模型推理时,才采用缩减黑边的方式,提高目标检测,推理的速度
c.为什么np.mod函数的后面用32?因为YOLOv5的网络经过5次下采样,而2的5次方,等于32。所以至少要去掉32的倍数,再进行取余
Focus结构
Focus结构,在YOLOv3、YOLOv4中并没有这个结构,其中比较关键是切片操作
比如右图的切片示意图,4×4×3的图像切片后变成2×2×12的特征图
以YOLOv5s的结构为例,原始608×608×3的图像输入Focus结构,采用切片操作,先变成304×304×12的特征图,再经过一次32个卷积核的卷积操作,最终变成304×304×32的特征图
需要注意的是:YOLOv5s的Focus结构最后使用了32个卷积核,而其他三种结构,使用的数量有所增加,先注意下,后面会讲解到四种结构的不同点
CSP结构
YOLOv4网络结构中,借鉴了CSPNet的设计思路,在主干网络中设计了CSP结构
YOLOv5与YOLOv4不同点在于,YOLOv4中只有主干网络使用了CSP结构
而YOLOv5中设计了两种CSP结构,以YOLOv5s网络为例,CSP1_X结构应用于Backbone主干网络,另一种CSP2_X结构则应用于Neck中
YOLOv5现在的Neck和Yolov4中一样,都采用FPN+PAN的结构,但在YOLOv5刚出来时,只使用了FPN结构,后面才增加了PAN结构,此外网络中其他部分也进行了调整
YOLOv4的Neck结构中,采用的都是普通的卷积操作。而YOLOv5的Neck结构中,采用借鉴CSPnet设计的CSP2结构,加强网络特征融合的能力