yolo-yolov5介绍

yolo系列

1.You Only Look Once: Unified, Real-Time Object Detection cvpr2016

https://bbs.huaweicloud.com/blogs/392995

预处理数据集得到 yolov1需要的label
训练
后处理数据得到方便显示的方式。

后处理:98个bbox , 20个种类, 然后NMS处理
https://zhuanlan.zhihu.com/p/416909015

2.yolov2

YOLO系列算法精讲:从yolov1至yolov8的进阶之路(2万字超全整理)

2.1 BN

在卷积或池化之后,激活函数之前,对每个数据输出进行标准化
在这里插入图片描述

2.2 anchor box

anchor box就是
首先一个数据集中的所有 gt box分析,
得到若干个固定 height, width的 box, 成为anchor box
这些anchor box具有一定的代表性。

在预测的时候,不是像 yolov1直接预测 x,y,h,w而是预测 相对于预先得到的anchor box的偏移量。
在这里插入图片描述

预测的4个数是 tx, ty, th, tw

yolov2 选择了5个anchor box。 faster rcnn中凭经验选择了9个anchor box, yolov2中选择了5个anchor box, 这5个anchor box是通过对数据集中的左右标注好的gt box 聚类得到的。

聚类的目的是得到若干个anchor box 的高度和宽度 。
使 Anchor boxes 和临近的 ground truth boxes有更大的IOU值

在这里插入图片描述

2.3 网络结构

在这里插入图片描述

2.4pass through 模块

在这里插入图片描述

3.yolov3

3.1结构

https://blog.csdn.net/leviopku/article/details/82660381
把结构介绍的很详细:

在这里插入图片描述

与darknet-19对比可知,darknet-53主要做了如下改进:

没有采用最大池化层,转而采用步长为2的卷积层进行下采样。
为了防止过拟合,在每个卷积层之后加入了一个BN层和一个Leaky ReLU。
引入了残差网络的思想,目的是为了让网络可以提取到更深层的特征,同时避免出现梯度消失或爆炸。
将网络的中间层和后面某一层的上采样进行张量拼接,达到多尺度特征融合的目的。
https://blog.csdn.net/wjinjie/article/details/107509243

3.2anchor

v3 和 v2一样也是预测相对位置:
在这里插入图片描述

v3的anchor选用数量是9个:
高度,宽度
在这里插入图片描述

3.3output

output是
在这里插入图片描述

9个anchor 按size 对应 y1,y2,y3 各三个anchor.

损失函数:
在这里插入图片描述

4.yolov4

YOLO系列算法精讲:从yolov1至yolov8的进阶之路(2万字超全整理)

4.1 CSPNet全称是Cross Stage Partial Networ

在前面的YOLOv3中,我们已经了解了Darknet53的结构,它是由一系列残差结构组成。进行结合后,CSPnet的主要工作就是将原来的残差块的堆叠进行拆分,把它拆分成左右两部分:主干部分继续堆叠原来的残差块,支路部分则相当于一个残差边,经过少量处理直接连接到最后。
在这里插入图片描述

CSPNet和PRN都是一个思想,将feature map拆成两个部分,一部分进行卷积操作,另一部分和上一部分卷积操作的结果进行concate。

从实验结果来看,分类问题中,使用CSPNet可以降低计算量,但是准确率提升很小;在目标检测问题中,使用CSPNet作为Backbone带来的提升比较大,可以有效增强CNN的学习能力,同时也降低了计算.

作者认为网络推理成本过高的问题是由于网络优化中的梯度信息重复导致的。CSPNet 通过将梯度的变化从头到尾地集成到特征图中,在减少了计算量的同时可以保证准确率。CSP(Cross Stage Partial Network,简称 CSPNet) 方法可以减少模型计算量和提高运行速度的同时,还不降低模型的精度,是一种更高效的网络设计方法,同时还能和Resnet、Densenet、Darknet 等 backbone 结合在一起。

网络结构如下:
在这里插入图片描述

Transition layer 的含义和 DenseNet 类似,是一个 1x1 的卷积层(没有再使用 average pool)。上图中 transition layer 的位置决定了梯度的结构方式,并且各有优势

参考:轻量级网络论文解析/CSPNet论文详解.md

4.2 mish代替 leaky relu

在这里插入图片描述

4.3 spp结构

SPP来源于这篇论文:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
在这里插入图片描述

4.4 PANet

《Path Aggregation Network for Instance Segmentation》
这篇文章发表于CVPR2018,它提出的Path Aggregation Network (PANet)既是COCO2017实例分割比赛的冠军,也是目标检测比赛的第二名。代码和模型见:https://github.com/ShuLiu1993/PANet。
在这里插入图片描述

4.5 数据增强方法 mosaic

在这里插入图片描述

总之 yolov4 有特别多的tricks.
YOLOv4的体系结构确定为:CSPDarknet53(主干) + SPP附加模块(颈) + PANet路径聚合(颈) + YOLOv3(头部)

4.6 结构

前面介绍了相关组块的结构和论文来源,再来看下整体结构会更加清晰明了:

在这里插入图片描述

参考:YOLOv4之网络结构剖析

https://zhuanlan.zhihu.com/p/143747206

5. yolov5

也是从yolov4发展过来的

5.1 focus结构

在这里插入图片描述

和pixel_unshuffle在最后的通道排列顺序上有差异。
参考:https://blog.csdn.net/tywwwww/article/details/137342458


def autopad(k, p=None):  # kernel, padding自动填充的设计,更加灵活多变
    # Pad to 'same'
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  
    return p
 
class Conv(nn.Module):
    # 这里对应结构图部分的CBL,CBL = conv+BN+Leaky ReLU,后来改成了SiLU(CBS)
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2) 

        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

 
    def forward(self, x):#正态分布型的前向传播
        return self.act(self.bn(self.conv(x)))
 
    def forward_fuse(self, x):#普通前向传播
        return self.act(self.conv(x))
 
class Focus(nn.Module):
    # Focus wh information into c-space
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super().__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
        # self.contract = Contract(gain=2)
 
    def forward(self, x):  # x(b,c,w,h) -> y(b,4c,w/2,h/2)
        return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1)) 
       

5.2 spp结构和sppf结构:

参考:https://blog.csdn.net/weixin_55073640/article/details/122621148?spm=1001.2014.3001.5502
需要注意的是yolov5中的spp结构的 maxpool stride = 1,因此池化后尺寸是不变的。
和最开始的spp 有差异。
sppf只不过 并联变成串联。

在这里插入图片描述

import time
import torch
import torch.nn as nn


class SPP(nn.Module):
    def __init__(self):
        super().__init__()
        self.maxpool1 = nn.MaxPool2d(5, 1, padding=2)
        self.maxpool2 = nn.MaxPool2d(9, 1, padding=4)
        self.maxpool3 = nn.MaxPool2d(13, 1, padding=6)

    def forward(self, x):
        o1 = self.maxpool1(x)
        o2 = self.maxpool2(x)
        o3 = self.maxpool3(x)
        return torch.cat([x, o1, o2, o3], dim=1)


class SPPF(nn.Module):
    def __init__(self):
        super().__init__()
        self.maxpool = nn.MaxPool2d(5, 1, padding=2)

    def forward(self, x):
        o1 = self.maxpool(x)
        o2 = self.maxpool(o1)
        o3 = self.maxpool(o2)
        return torch.cat([x, o1, o2, o3], dim=1)


def main():
    input_tensor = torch.rand(8, 32, 16, 16)
    spp = SPP()
    sppf = SPPF()
    output1 = spp(input_tensor)
    output2 = sppf(input_tensor)

    print(torch.equal(output1, output2))

    t_start = time.time()
    for _ in range(100):
        spp(input_tensor)
    print(f"spp time: {time.time() - t_start}")

    t_start = time.time()
    for _ in range(100):
        sppf(input_tensor)
    print(f"sppf time: {time.time() - t_start}")


if __name__ == '__main__':
    main()

5.5 bottleneck

resnet中的bottleneck:
在这里插入图片描述

yolov5中的bottleneck代码:2各卷积层组成

class Bottleneck(nn.Module):#瓶颈层,由两个CBL组成,1个1*1,一个3*3,再横跨一个Residual
   
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_, c2, 3, 1, g=g)
        self.add = shortcut and c1 == c2
 
    def forward(self, x):
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))#这里对应判断:如果False就只有self.cv2(self.cv1(x)),True就x + self.cv2(self.cv1(x))

5.55 完整结构

https://blog.csdn.net/qq_37541097/article/details/123594351
一图胜过千言万语

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-09 21:38:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-09 21:38:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-09 21:38:02       82 阅读
  4. Python语言-面向对象

    2024-04-09 21:38:02       91 阅读

热门阅读

  1. 第 9 场 小白入门赛 字典树考试

    2024-04-09 21:38:02       33 阅读
  2. python爬虫基础知识整理(2)

    2024-04-09 21:38:02       34 阅读
  3. SQL语言

    SQL语言

    2024-04-09 21:38:02      36 阅读
  4. 如何使用Docker容器化改善你的开发流程

    2024-04-09 21:38:02       38 阅读
  5. == 和 ===什么区别呀?

    2024-04-09 21:38:02       31 阅读