YOLOv1
YOLO算法的原理与实现
死磕YOLO系列,YOLOv1 的大脑、躯干和手脚
YOLOv2
史上最通俗易懂的YOLOv2讲解
目标检测YOLOv2最详细解释!
YOLOv3
一文看懂YOLO v3
SSD
SSD原理解读-从入门到精通
优秀文章摘录
目标检测之YOLOv3算法: An Incremental Improvement
1. 前言
论文地址:https://pjreddie.com/media/files/papers/YOLOv3.pdf
相关代码:https://github.com/yjh0410/yolov2-yolov3_PyTorch
目标检测之YOLO算法:YOLOv1,YOLOv2,YOLOv3,TinyYOLO,YOLOv4,YOLOv5,YOLObile,YOLOF详解:
初识CV:目标检测之YOLO算法:YOLOv1,YOLOv2,YOLOv3,TinyYOLO,YOLOv4,YOLOv5,YOLObile,YOLOF详解1168 赞同 · 69 评论文章
2. YOLOv3算法详解
YOLO v3网络结构
YOLO v3的模型(如上图所示,图来自这里)比之前的模型复杂了不少,可以通过改变模型结构的大小来权衡速度与精度。
-
DBL
:代码中的Darknetconv2d_BN_Leaky
,是yolo_v3的基本组件。就是卷积+BN+Leaky relu。 -
resn
:n代表数字,有res1,res2, … ,res8等等,表示这个res_block
里含有多少个res_unit。 -
concat
:张量拼接。将darknet中间层和后面的某一层的上采样进行拼接。拼接的操作和残差层add的操作是不一样的,拼接会扩充张量的维度,而add只是直接相加不会导致张量维度的改变
速度和精度(mAP)对比如下:
简而言之,YOLOv3 的先验检测(Prior detection)系统将分类器或定位器重新用于执行检测任务。他们将模型应用于图像的多个位置和尺度。而那些评分较高的区域就可以视为检测结果。此外,相对于其它目标检测方法,我们使用了完全不同的方法。我们将一个单神经网络应用于整张图像,该网络将图像划分为不同的区域,因而预测每一块区域的边界框和概率,这些边界框会通过预测的概率加权。我们的模型相比于基于分类器的系统有一些优势。它在测试时会查看整个图像,所以它的预测利用了图像中的全局信息。与需要数千张单一目标图像的 R-CNN 不同,它通过单一网络评估进行预测。这令 YOLOv3 非常快,一般它比 R-CNN 快 1000 倍、比 Fast R-CNN 快 100 倍。
2.1 基础网络 Darknet-53
下图是YOLOv3的网络模型结构图,此结构主要由75个卷积层构成,卷积层对于分析物体特征最为有效。由于没有使用全连接层,该网络可以对应任意大小的输入图像。此外,池化层也没有出现在YOLOv3当中,取而代之的是将卷积层的stride设为2来达到下采样的效果,同时将尺度不变特征传送到下一层。除此之外,YOLOv3中还使用了类似ResNet和FPN网络的结构,这两个结构对于提高检测精度也是大有裨益。作者在3条预测支路采用的也是全卷积的结构,其中最后一个卷积层的卷积核个数是255,是针对COCO数据集的80类:3*(80+4+1)=255,3表示一个grid cell包含3个bounding box,4表示框的4个坐标信息,1表示objectness score。
darknet-53:
作者在ImageNet上实验发现这个darknet-53,的确很强,相对于ResNet-152和ResNet-101,darknet-53不仅在分类精度上差不多,计算速度还比ResNet-152和ResNet-101强多了,网络层数也比他们少。对比如下:
darknet-53代码解析如下(Pytorch):
class DarkNet_53(nn.Module):标签:YOLO,系列,nn,self,yolo,stride,YOLOv3,ssd,BN From: https://blog.51cto.com/u_12617333/5997042
"""
YOLOv3 model module. The module list is defined by create_yolov3_modules function. \
The network returns loss values from three YOLO layers during training \
and detection results during test.
"""
def __init__(self, num_classes=1000):
super(DarkNet_53, self).__init__()
# stride = 2
self.layer_1 = nn.Sequential(
Conv_BN_LeakyReLU(3, 32, 3, padding=1),
Conv_BN_LeakyReLU(32, 64, 3, padding=1, stride=2),
resblock(64, nblocks=1)
)
# stride = 4
self.layer_2 = nn.Sequential(
Conv_BN_LeakyReLU(64, 128, 3, padding=1, stride=2),
resblock(128, nblocks=2)
)
# stride = 8
self.layer_3 = nn.Sequential(
Conv_BN_LeakyReLU(128, 256, 3, padding=1, stride=2),
resblock(256, nblocks=8)
)
# stride = 16
self.layer_4 = nn.Sequential(
Conv_BN_LeakyReLU(256, 512, 3, padding=1, stride=2),
resblock(512, nblocks=8)
)
# stride = 32
self.layer_5 = nn.Sequential(
Conv_BN_LeakyReLU(512, 1024, 3, padding=1, stride=2),
resblock(1024, nblocks=4)
)
# self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
# self.fc = nn.Linear(1024, num_classes)
def forward(self, x, targets=None):
x = self.layer_1(x)
x = self.layer_2(