目标检测之解读YOLOv3论文、源码及背后逻辑

关于YOLOv1、YOLOv2的内容,请参考目标检测之解读YOLOv1论文、源码及背后逻辑目标检测之解读YOLOv2论文、源码及背后逻辑。下面具体看下YOLOv3做了哪些改进。

YOLOv3结构图

在这里插入图片描述

为了让yolo_v3结构图更好理解,我对上图做一些补充解释:
DBL: 如图左下角所示,Darknetconv2d_BN_Leaky,是yolo_v3的基本组件。就是卷积+BN+Leaky relu。对于v3来说,BN和leaky relu已经是和卷积层不可分离的部分了(最后一层卷积除外),共同构成了最小组件。

resn:n代表数字,有res1,res2, … ,res8等等,表示这个res_block里含有多少个残差组件(res_unit)。这是yolo_v3的大组件,yolo_v3开始借鉴了ResNet的残差结构,使用这种结构可以让网络结构更深(从v2的darknet-19上升到v3的darknet-53,前者没有残差结构)。对于res_block的解释,可以在图的右下角直观看到,其基本组件也是DBL。

concat:张量拼接。将darknet中间层和后面的某一层的上采样进行拼接。拼接的操作和残差层add的操作是不一样的,拼接会扩充张量的维度,而add只是直接相加不会导致张量维度的改变。

新的特征提取网络结构Darknet-53

在这里插入图片描述

上图的Darknet-53网络采用256*256*3作为输入,最左侧那一列的1、2、8等数字表示多少个重复的残差组件。

YOLOv3使用了darknet-53的全局平均池化层和全连接层前的网络,yolo_v3这个网络是一个全卷积网络,大量使用残差的跳层连接,并且为了降低池化带来的梯度负面效果,YOLOv3,用conv的步长stride=(2, 2)来实现降采样。

YOLOv和3v2一样,特征提取网络的输入都是416*416,都会将输出特征图缩小到输入的1/32(13*13)。所以,通常都要求输入图片是32的倍数。

利用多尺度特征进行对象检测

YOLOv2用passthrough layer来提取细粒度特征用于检测小物体,YOLOv3进一步改进,输出了3个不同尺度的feature map,如下所示:

在这里插入图片描述

另一种更清晰的结构如下所示:

在这里插入图片描述

在上图中,卷积网络在79层后,经过下方几个黄色的卷积层得到一种尺度的检测结果。相比输入图像,这里用于检测的特征图有32倍的下采样。比如输入是416416的话,这里的特征图就是1313了。由于下采样倍数高,这里特征图的感受野比较大,因此适合检测图像中尺寸比较大的对象。

为了实现细粒度的检测,第79层的特征图又开始作上采样(从79层往右开始上采样卷积),然后与第61层特征图融合(Concatenation),这样得到第91层较细粒度的特征图,同样经过几个卷积层后得到相对输入图像16倍下采样的特征图。它具有中等尺度的感受野,适合检测中等尺度的对象。

最后,第91层特征图再次上采样,并与第36层特征图融合(Concatenation),最后得到相对输入图像8倍下采样的特征图。它的感受野最小,适合检测小尺寸的对象。

9种尺寸的anchor boxes

YOLOv2有5种尺寸anchor boxes,YOLOv3有3种尺寸anchor boxes,但是YOLO v3有3个输出层,所以YOLO v3的anchor boxes比YOLO v2还是要多,因为(13*13+26*26+52*52)*3 > 13*13*5。

YOLOv3延续v2已经开始采用K-means聚类得到先验框的尺寸这种方法聚类出9种尺寸的anchor boxes。

三个输出层对应三次检测,每次对应的感受野不同,32倍的降采样(对应13*13的输出)的感受野最大,适合检测大的目标,每个单元格的三个anchor boxes为(116 ,90); (156 ,198); (373 ,326)。16倍的降采样(对应26*26的输出)适合一般大小的物体,anchor boxes为(30,61); (62,45); (59,119)。8倍的降采样(对应52*52的输出)感受野最小,适合检测小目标,因此anchor boxes为(10,13); (16,30); (33,23)。所以当输入图像为416×416时,实际总共有(52×52+26×26+13×13)×3=10647个anchor boxes。

bounding box预测

feature map中的每一个点就代表一个单元格,都会预测3个边界框(bounding box) ,每个bounding box都会预测三个东西:(1)每个框的位置(4个值,中心坐标 b x b_x bx b y b_y by,,框的高度 b h b_h bh和宽度 b w b_w bw),(2)置信度 ,(3)N个类别,coco数据集80类,voc20类。

bounding box 与anchor box的区别:

anchor box只是一个尺度即只有宽高。

Bounding box会根据预测得到偏移量( t x , t y , t w , t h t_x,t_y,t_w,t_h tx,ty,tw,th)和对应anchor box的宽高( w a n c h o r , h a n c h o r w_{anchor},h_{anchor} wanchor,hanchor),通过公式计算得到中心坐标 b x b_x bx b y b_y by,,框的高度 b h b_h bh和宽度 b w b_w bw。计算公式如下:
p w = w a n c h o r w i m a g e p_w=\frac{w_{anchor}}{w_{image}} pw=wimagewanchor

p h = h a n c h o r h i m a g e p_h=\frac{h_{anchor}}{h_{image}} ph=himagehanchor

t w = l n w p r e d w a n c h o r t_w=ln\frac{w_{pred}}{w_{anchor}} tw=lnwanchorwpred

t h = l n h p r e d h a n c h o r t_h=ln\frac{h_{pred}}{h_{anchor}} th=lnhanchorhpred

b x = σ ( t x ) + c x b_x=\sigma(t_x)+c_x bx=σ(tx)+cx

b y = σ ( t y ) + c y b_y=\sigma(t_y)+c_y by=σ(ty)+cy

b w = p w e t w b_w=p_we^{t_w} bw=pwetw

b h = p h e t h b_h=p_he^{t_h} bh=pheth

其中: w i m a g e , h i m a g e w_{image},h_{image} wimage,himage是指输入图像的宽和高。

在这里插入图片描述

代码如下:

box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[::-1], K.dtype(feats))
box_wh = K.exp(feats[..., 2:4]) * anchors_tensor / K.cast(input_shape[::-1], K.dtype(feats))
box_confidence = K.sigmoid(feats[..., 4:5])
box_class_probs = K.sigmoid(feats[..., 5:])

分类预测变化

softmax来分类依赖于这样一个前提,即分类是相互独立的,换句话说,如果一个目标属于一种类别,那么它就不能属于另一种。

但是,当我们的数据集中存在狗或柯基犬的标签时,上面所提到的前提就是去了意义。这就是作者为什么不用softmax,而用logistic regression来预测每个类别得分并使用一个阈值来对目标进行多标签预测。比阈值高的类别就是这个边界框真正的类别。

输入映射到输出

在这里插入图片描述

总的来说,对于一个输入图像,YOLO3将其映射到3个尺度的输出张量,代表图像各个位置存在各种对象的概率。

我们看一下YOLO3共进行了多少个预测。对于一个416*416的输入图像,在每个尺度的特征图的每个网格设置3个先验框,总共有 13*13*3 + 26*26*3 + 52*52*3 = 10647 个预测。每一个预测是一个(4+1+80)=85维向量,这个85维向量包含边框坐标(4个数值),边框置信度(1个数值),对象类别的概率(对于COCO数据集,有80种对象)。

对比一下,YOLO2采用13*13*5 = 845个预测,YOLO3的尝试预测边框数量增加了10多倍,而且是在不同分辨率上进行,所以mAP以及对小物体的检测效果有一定的提升。

损失函数

YOLO损失函数由四部分组成:中心坐标损失(xy_loss)、宽高损失(wh_loss)、置信度损失(confidence_loss)、分类损失(class_loss)。

在v1中使用了一种叫sum-square error(SSE)的损失计算方法,就是差方相加。

YOLOv3不再是全部使用均方和损失,xy_loss、confidence_loss、class_loss使用了二值交叉熵计算损失,wh_loss而然采用SSE计算损失。

对于confidence_loss,分为obj和no_obj两种情况计算。对于obj(该检测框有对应的真实框)需要参与计算损失;对于no_obj(该检测框无对应的真实框),当检测框和真实框的iou低于0.5,也需要参与计算。

代码如下:

# 这里是一个系数,面积越小权重越高
box_loss_scale = 2 - y_true[l][...,2:3]*y_true[l][...,3:4]
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)
#mf是参与损失计算的样本数
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

参考

https://blog.csdn.net/guleileo/article/details/80581858
https://github.com/qqwweee/keras-yolo3

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值