参考文章:
论文笔记-2019-Object Detection in 20 Years: A Survey
基于深度学习的目标检测算法综述(一)
基于深度学习的目标检测算法综述(二)
基于深度学习的目标检测算法综述(三)
优秀的GitHub仓库:
deep learning object detection
Awesome Object Detection
比较全面的整理:
我这两年的目标检测
最全目标检测相关资料整理
我这两年收藏的目标检测好文分享
SSD算法在传统的基础网络(比如VGG)后添加了5个特征图尺寸依次减小的卷积层,对5个特征图的输入分别采用2个不同的3*3的卷积核进行卷积,一个输出类别的confidence;一个输出回归用的localization,每个default box生成4个坐标值,最后将5个特征图上的结果合并(Contact),送入loss层。
SSD算法的核心是Default box层,Default box层利用了Anchor的机制,如下图所示,这里假定有 8×8 和 4×4 两种不同尺度的 feature map。第一个概念是feature map cell,feature map cell 是指 feature map 中每一个小格子,如图中分别有 64 和 16 个 cell。另一个概念是default box,是指在feature map的每个小格(cell)上都有一系列固定大小的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卷积时卷积核的个数,包含两部分:数量 c * k * m * n 是 confidence 输出,表示每个 default box 的 是某一类别的 confidence;数量4 * k * m * n是 localization 输出,表示每个default box 回归后的坐标。
对于先验框的尺度,其遵守一个线性递增规则:随着特征图大小降低,先验框尺度线性增加:
这里smin是0.2,表示最底层的尺度是0.2,;smax是0.9,表示最高层的尺度是0.9。通过这种计算方法,可以得出6个特征图的default box尺度分别为:[30,60,111,162,213,264]。长宽比用??表示为下式(注意这里一共有5种长宽比):
通过下面的公式计算 default box 的宽度w和高度h:
另外当 aspect ratio 为1时,作者还增加一种 scale 的 default box:
因此,对于每个 feature map cell 而言,一共有 6 种 default box。
正样本获得:将得到的 default box 和真实框进行 IOU 匹配,大于0.5即认为是正样本
负样本获得:很显然负样本的数量远多于正样本,因此先将每一个物体位置上对应 predictions(default boxes)是 negative 的 boxes 进行排序,按照 default boxes 的 confidence 的大小。 选择最高的几个,最终使正负样例比例为1:3。
损失函数:定义为位置误差(locatization loss, loc)与置信度误差(confidence loss, conf)的加权和:
每一张训练图像,随机的进行如下几种选择:
采样的 patch 是原始图像大小比例是 [0.1,1],aspect ratio 在 12 与 2 之间。当 groundtruth box 的 中心(center)在采样的 patch 中时,我们保留重叠部分。在这些采样步骤之后,每一个采样的 patch 被 resize 到固定的大小,并且以 0.5 的概率随机的 水平翻转(horizontally flipped)
对于 SSD 的改进可以包括对主干网络的改进,例如使用 ResNet 等效果更好的网络作为主干网络,还可以对预测网络进行改进。
SSD 算法对小目标不够鲁棒的原因是浅层特征层的表征能力不够强,因此 DSSD使用ResNet-101代替VGG作为主干网络,在‘SSD layers‘后面添加了反卷积层和feed-forward连接,然后使用residual block作为预测层。。
采用rainbow concatenation形式(池化+反卷积)融合不同层的特征,增加不同特征层之间特征图的关系和个数
YOLO的核心思想就是利用整张图作为网络的输入,直接在输出层回归bounding box的位置和bounding box所属的类别。
YOLO的实现方法为:
YOLO_V1中取S=7,B=2,C=20(因为PASCAL VOC有20个类别),所以最后有7 * 7 * 30个tensor,下图为YOLO_V1结构图
关于损失函数的设计,前面两行表示localization error(即坐标误差),第一行是box中心坐标(x,y)的预测,第二行为宽和高的预测。这里注意用宽和高的开根号代替原来的宽和高,这样做主要是因为相同的宽和高误差对于小的目标精度影响比大的目标要大。
第三、四行表示bounding box的confidence损失,就像前面所说的,分成grid cell包含与不包含object两种情况。这里注意下因为每个grid cell包含两个bounding box,所以只有当ground truth 和该网格中的某个bounding box的IOU值最大的时候,才计算这项。
第五行表示预测类别的误差,注意前面的系数只有在grid cell包含object的时候才为1。
在测试的时候,每个网格预测的 class 信息和 bounding box 预测的 confidence信息相乘,就得到每个 bounding box 的 class-specific confidence score
等式左边第一项就是每个网格预测的类别信息,第二、三项就是每个 bounding box 预测的 confidence。这个乘积即 encode 了预测的 box 属于某一类的概率,也有该 box 准确度的信息。得到每个 box 的 class-specific confidence score 以后,设置阈值,滤掉得分低的 boxes,对保留的 boxes 进行 NMS 处理,就得到最终的检测结果。
YOLO_v2是YOLO的升级版,YOLO9000的主要检测网络也是YOLO v2,同时对数据集做了融合,使得模型可以检测9000多类物体。而提出YOLO9000的原因主要是目前检测的数据集数据量较小,因此利用数量较大的分类数据集来帮助训练检测模型。YOLO_V2、YOLO9000对比YOLO_v1主要有better、faster、stronger三个方面
YOLO9000主要通过结合分类和检测数据集使得训练得到的检测模型可以检测约9000类物体。一方面要构造数据集,另一方面要解决模型训练问题,前者采用WordTree解决,后者采用Joint classification and detection。
根据各个类别之间的从属关系(根据WordNet)建立一种树结构WordTree,结合COCO和ImageNet建立的WordTree如下图所示:
WordTree中的根节点为"physical object",每个节点的子节点都属于同一子类,可以对它们进行softmax处理。在给出某个类别的预测概率时,需要找到其所在的位置,遍历这个path,然后计算path上各个节点的概率之积。
Joint classification and detection:作者的目的是训练一个 Extremely Large Scale 检测器。所以训练的时候使用 WordTree 混合了 COCO 检测数据集与 ImageNet 中的 Top9000 类,混合后的数据集对应的 WordTree 有 9418 个类。另一方面,由于 ImageNet 数据集太大了,作者为了平衡一下两个数据集之间的数据量,通过过采样(oversampling) COCO 数据集中的数据,使 COCO 数据集与 ImageNet 数据集之间的数据量比例达到 1:4。YOLO9000 的训练基于 YOLO v2 的构架,但是使用 3 priors 而不是 5 来限制输出的大小。当网络遇到检测数据集中的图片时则正常地反方向传播,当遇到分类数据集图片的时候,只使用分类的 loss 功能进行反向传播。同时作者假设 IOU 最少为 0.3。最后根据这些假设进行反向传播。
使用联合训练法,YOLO9000 使用 COCO 检测数据集学习检测图片中的物体的位置,使用 ImageNet 分类数据集学习如何对大量的类别中进行分类。
参考文章:yolo系列之yolo v3【深度解析】
这里推荐的模型结构可视化工具是:Netron
整个v3结构里面,是没有池化层和全连接层的。前向传播过程中,张量的尺寸变换是通过改变卷积核的步长来实现的,比如stride=(2, 2),这就等于将图像边长缩小了一半。yolo_v3也和v2一样,backbone都会将输出特征图缩小到输入的1/32。所以,通常都要求输入图片是32的倍数。
darknet-19是不存在残差结构,和VGG是同类型的backbone,而darknet-53是从resnet上借鉴过来的backbone。
darknet-19在速度上仍然占据很大的优势。可以看出yolo_v3并没有那么追求速度,而是在保证实时性(fps>36)的基础上追求performance。不过要想更快,还有一个 tiny-darknet作为backbone可以替代darknet-53。
yolo v3借鉴了FPN采用多尺度来对不同size的目标进行检测的方法,输出了3个不同尺度的feature map,如上图所示的y1, y2, y3。
对于COCO类别而言,有80个种类,yolo v3中每个网格单元预测3个box,每个box需要有(x, y, w, h, confidence)五个基本参数,然后还要有80个类别的概率。所以3*(5 + 80) = 255。
对于yolo v3而言,对于先验框的选择:选用的b-box priors 的k=9,对于tiny-yolo的话,k=6。priors都是在数据集上聚类得来的,有确定的数值,9个anchor会被三个输出张量平分的。根据大中小三种size各自取自己的anchor。
v3对b-box进行预测的时候,采用了logistic regression。v3每次对b-box进行predict时,输出和v2一样是偏差,然后通过公式计算出绝对的(x, y, w, h, c)。logistic回归用于对anchor包围的部分进行一个目标性评分(objectness score),即这块位置是目标的可能性有多大。这一步是在predict之前进行的,可以去掉不必要anchor,可以减少计算量。
除了w, h的损失函数依然采用总方误差之外,其他部分的损失函数用的是二值交叉熵。
keras代码如下:
xy_loss = object_mask * box_loss_scale * K.binary_crossentropy(raw_true_xy, raw_pred[..., 0:2],
from_logits=True)
wh_loss = object_mask * box_loss_scale * 0.5 * K.square(raw_true_wh - raw_pred[..., 2:4])
confidence_loss = object_mask * K.binary_crossentropy(object_mask, raw_pred[..., 4:5], from_logits=True) + \
(1 - object_mask) * K.binary_crossentropy(object_mask, raw_pred[..., 4:5],
from_logits=True) * ignore_mask
class_loss = object_mask * K.binary_crossentropy(true_class_probs, raw_pred[..., 5:], from_logits=True)
xy_loss = K.sum(xy_loss) / mf
wh_loss = K.sum(wh_loss) / mf
confidence_loss = K.sum(confidence_loss) / mf
class_loss = K.sum(class_loss) / mf
loss += xy_loss + wh_loss + confidence_loss + class_loss
参考文章:深入浅出Yolo系列之Yolov3&Yolov4&Yolov5核心基础知识完整讲解
参考代码:Pytorch-YOLOv4
YOLO_V4结构图如下:
Yolov4的整体架构和Yolov3是相同的,不过使用各种新的算法思想对各个子结构都进行了改进。
Yolov4的五个基本组件:
主要从4个部分对YoloV4的创新之处进行解释:
Yolov4对训练时的输入端进行改进,使得训练在单张GPU上也能有不错的成绩。比如数据增强Mosaic、cmBN、SAT自对抗训练。
Yolov4中使用的Mosaic是参考2019年底提出的CutMix数据增强的方式,但CutMix只使用了两张图片进行拼接,而Mosaic数据增强则采用了4张图片,随机缩放、随机裁剪、随机排布的方式进行拼接。
Mosaic数据增强主要有几个优点:
CSPDarknet53是在Yolov3主干网络Darknet53的基础上,借鉴2019年CSPNet的经验,产生的Backbone结构,其中包含了5个CSP模块。
每个CSP模块前面的卷积核的大小都是3 * 3,stride=2,因此可以起到下采样的作用。因为Backbone有5个CSP模块,输入图像是608 * 608,所以特征图变化的规律是:608->304->152->76->38->19。
Yolov4在主干网络Backbone采用CSPDarknet53网络结构,主要有三个方面的优点:
和Leaky_relu激活函数的图形对比如下:
Yolov4的Backbone中都使用了Mish激活函数,而后面的网络则还是使用leaky_relu函数。
Dropblock,其实和常见网络中的Dropout功能类似,也是缓解过拟合的一种正则化方式。
中间Dropout的方式会随机的删减丢弃一些信息,但Dropblock的研究者认为,卷积层对于这种随机丢弃并不敏感,因为卷积层通常是三层连用:卷积+激活+池化层,池化层本身就是对相邻单元起作用。即使随机丢弃,卷积层仍然可以从相邻的激活单元学习到相同的信息。
因此,在全连接层上效果很好的Dropout在卷积层上效果并不好。所以右图Dropblock的研究者则干脆整个局部区域进行删减丢弃。
Dropblock的研究者与Cutout进行对比验证时,发现有几个特点:
在目标检测领域,为了更好的提取融合特征,通常在Backbone和输出层,会插入一些层,这个部分称为Neck。相当于目标检测网络的颈部,也是非常关键的。
Yolov4的Neck结构主要采用了SPP模块、FPN+PAN的方式。
在Yolov4中,SPP模块仍然是在Backbone主干网络之后
作者在SPP模块中,使用k={1x1 , 5x5 , 9x9 , 13x13}的最大池化的方式,再将不同尺度的特征图进行Concat操作。(这里最大池化采用padding操作,移动的步长为1,比如13×13的输入特征图,使用5×5大小的池化核池化,padding=2,因此池化后的特征图仍然是13×13大小)
采用SPP模块的方式,比单纯的使用k*k最大池化的方式,更有效的增加主干特征的接收范围,显著的分离了最重要的上下文特征。
Yolov3中具有FPN结构,Yolov4中Neck这部分除了使用FPN外,还在此基础上使用了PAN结构:
Yolov4在FPN层的后面还添加了一个自底向上的特征金字塔。其中包含两个PAN结构。这样结合操作,FPN层自顶向下传达强语义特征,而特征金字塔则自底向上传达强定位特征,两两联手,从不同的主干层对不同的检测层进行参数聚合。
需要注意的是,Yolov4中:
CIOU_Loss和DIOU_Loss前面的公式都是一样的,不过在此基础上还增加了一个影响因子,将预测框和目标框的长宽比都考虑了进去。
其中v是衡量长宽比一致性的参数,我们也可以定义为:
综合的看下各个Loss函数的不同点:
Nms主要用于预测框的筛选,常用的目标检测算法中,一般采用普通的nms的方式,Yolov4则采用DIOU_nms
在重叠目标的检测中,DIOU_nms的效果优于传统的nms。
参考文章:深入浅出Yolo系列之Yolov5核心基础知识完整讲解
Yolov5官方代码中,给出的目标检测网络中一共有4个版本,分别是Yolov5s、Yolov5m、Yolov5l、Yolov5x四个模型。
Yolov5s整体的网络结构图如下:
Yolov5s网络是Yolov5系列中深度最小,特征图的宽度最小的网络。后面的3种都是在此基础上不断加深,不断加宽。
输入端运用了Mosaic数据增强、自适应锚框计算、自适应图片缩放三种方法,Mosaic数据增强上文介绍过不再赘述。
在Yolo算法中,针对不同的数据集,都会有初始设定长宽的锚框。
在Yolov3、Yolov4中,训练不同的数据集时,计算初始锚框的值是通过单独的程序运行的。
但Yolov5中将此功能嵌入到代码中,每次训练时,自适应的计算不同训练集中的最佳锚框值。当然,如果觉得计算的锚框效果不是很好,也可以在代码中将自动计算锚框功能关闭。
在常用的目标检测算法中,不同的图片长宽都不相同,因此常用的方式是将原始图片统一缩放到一个标准尺寸,再送入检测网络中。
比如Yolo算法中常用416x416,608x608等尺寸,比如对下面800x600的图像进行缩放。
而在Yolov5的代码中datasets.py的letterbox函数中进行了修改,对原始图像自适应的添加最少的黑边。
计算方法如下:
Backbone中利用了Focus结构,CSP结构
以Yolov5s的结构为例,原始6086083的图像输入Focus结构,采用切片操作,先变成30430412的特征图,再经过一次32个卷积核的卷积操作,最终变成30430432的特征图。
Yolov5中设计了两种CSP结构,以Yolov5s网络为例,CSP1_X结构应用于Backbone主干网络,另一种CSP2_X结构则应用于Neck中。
CSP结构上文已介绍
Yolov5现在的Neck和Yolov4中一样,都采用FPN+PAN的结构,Yolov5和Yolov4的不同点在于,
Yolov4的Neck结构中,采用的都是普通的卷积操作。而Yolov5的Neck结构中,采用借鉴CSPnet设计的CSP2结构,加强网络特征融合的能力。
Yolov5中采用其中的GIOU_Loss做Bounding box的损失函数。
Yolov5中采用加权nms的方式。
需要注意的是,四种网络结构中每个CSP结构的深度都是不同的。
四种yolov5结构在不同阶段的卷积核的数量都是不一样的,因此也直接影响卷积后特征图的第三维度,即厚度
参考代码:pytorch-retinanet
参考文章:RetinaNet 论文和代码详解
RetinaNet针对现有单阶段法目标检测模型中前景(positive)和背景(negatives)类别的不平衡问题,提出了一种叫做Focal Loss的损失函数,用来降低大量easy negatives在标准交叉熵中所占权重(提高hard negatives所占权重)。
下图为RetinaNet的结构图,我们可以看出,RetinaNet的特征提取网络选择了残差网络ResNet,特征融合这块选择了FPN(特征金字塔网络),以特征金字塔不同的尺寸特征图作为输入,搭建三个用于分类和框回归的子网络。
RetinaNet最主要的创新点在于其使用Focal Loss解决前景和背景样本不平衡的问题,Focal Loss损失函数输入为网络的分类预测,框回归预测,anchor信息(用于对框回归预测进行转换)和真实标签annotations。
我们要解决样本不平衡的问题,我们使用一个平衡因子α ,其范围是0到1,对于类别1乘以 α ,而对于类别-1乘以 1-α,则损失函数变为
虽然 α 平衡了正负样本的数量,但实际上,目标检测中大量的候选目标都是易分样本。这些样本的损失很低,但是由于数量极不平衡,易分样本的数量相对来讲太多,最终主导了总的损失。因此,Focal Loss认为易分样本(即,置信度高的样本)对模型的提升效果非常小,模型应该主要关注与那些难分样本 。一个简单的想法就是将高置信度样本的损失降低一些, 也即是下面的公式:
将 γ 定义为2时效果最好!
参考文章:
目标检测:Anchor-Free时代
目标检测Anchor-free分支:基于关键点的目标检测