YOLOv5改进 | 融合改进 | C3融合新颖的可扩张残差注意力模块助力小目标检测【完整代码】

秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转


💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡


本文介绍了一种高效的多尺度特征提取方法,通过将单步过程分解为两步:区域残差化和语义残差化,简化了多速率深度可分离空洞卷积的作用提高了特征提取效率。为此,设计了Dilation-wise Residual(DWR)模块和Simple Inverted Residual(SIR)模块,构建了DWRSeg网络。在Cityscapes和CamVid数据集上的实验显示,该方法在精度和速度之间取得了优异的平衡,且模型更轻。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。 

专栏地址 YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转   

目录

1. 原理

2. 将C3_DWR代码添加到YOLOv5中

2.1 C3_DWR的代码实现

2.2 新增yaml文件

2.3 注册模块

2.4 执行程序

3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1. 原理

论文地址:DWRSeg: Rethinking Efficient Acquisition of Multi-scale Contextual Information for Real-time Semantic Segmentation——点击即可跳转

DWR (Dilation-wise Residual) 主要原理是为了在实时语义分割任务中高效地提取多尺度上下文信息。为了克服传统方法中多尺度上下文信息提取的复杂性和效率问题,DWR 提出了一个两步特征提取方法,即“区域残差化(Region Residualization)”和“语义残差化(Semantic Residualization)”。

主要步骤与原理:

  1. 区域残差化(Region Residualization)

    该步骤的目的是从输入特征中生成不同尺寸的简洁区域特征图。通过3x3卷积结合BN(Batch Normalization)层和ReLU激活层,生成这些区域特征图。ReLU激活函数在这里用于激活区域特征,使其更加简洁。
  2. 语义残差化(Semantic Residualization)

    在该步骤中,使用多速率的膨胀深度卷积对不同尺寸的区域特征进行形态学过滤。这意味着对每一个通道的特征仅应用一个所需的感受野,以避免冗余的感受野。在此过程中,区域特征图被分组,并在每个组上应用不同速率的膨胀卷积。

优点:

  • 通过将复杂的上下文信息提取任务分解为两个简单步骤,DWR 提高了特征提取的效率。尤其是,它使得膨胀卷积的角色从获取复杂语义信息变得更加简单,仅需在简洁的区域特征图上执行形态学过滤。

  • 该方法使得多尺度上下文信息的获取更加有序和高效,从而显著提升了实时语义分割的性能。

实际应用:

DWR 模块主要用于网络的高层部分,而对于低层部分则使用了改进后的SIR(Simple Inverted Residual)模块。这种结构在实际应用中,如Cityscapes数据集上,取得了较好的效果,表现为在保持高推理速度的同时还能获得较高的分割精度。

2. 将C3_DWR代码添加到YOLOv5中

2.1 C3_DWR的代码实现

关键步骤一:将下面的代码粘贴到\yolov5\models\common.py中

class DWR(nn.Module):
    def __init__(self, dim) -> None:
        super().__init__()

        self.conv_3x3 = Conv(dim, dim // 2, 3)
        
        self.conv_3x3_d1 = Conv(dim // 2, dim, 3, d=1)
        self.conv_3x3_d3 = Conv(dim // 2, dim // 2, 3, d=3)
        self.conv_3x3_d5 = Conv(dim // 2, dim // 2, 3, d=5)
        
        self.conv_1x1 = Conv(dim * 2, dim, k=1)
        
    def forward(self, x):
        conv_3x3 = self.conv_3x3(x)
        x1, x2, x3 = self.conv_3x3_d1(conv_3x3), self.conv_3x3_d3(conv_3x3), self.conv_3x3_d5(conv_3x3)
        x_out = torch.cat([x1, x2, x3], dim=1)
        x_out = self.conv_1x1(x_out) + x
        return x_out

class C3_DWR(C3):
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        super().__init__(c1, c2, n, shortcut, g, e)
        c_ = int(c2 * e)  # hidden channels
        self.m = nn.Sequential(*(DWR(c_) for _ in range(n)))

DWR(Dilation-wise Residual)处理图像的主要步骤可以分为以下几个阶段,每个阶段都有特定的任务,以高效地提取多尺度上下文信息来辅助实时语义分割:

1. 区域残差化(Region Residualization)

  • 目标:生成简洁的区域特征图,作为后续处理的基础。

  • 步骤

    • 输入的图像特征首先通过一个普通的3x3卷积层,以初步提取图像的特征。

    • 然后,这些初步提取的特征经过批量归一化(BN)和ReLU激活,使得生成的区域特征图更加简洁和明确。

    • 最终,得到一系列不同大小的区域特征图,这些图能够清晰地表示图像中的局部信息。

2. 语义残差化(Semantic Residualization)

  • 目标:从区域特征图中提取有用的多尺度上下文信息。

  • 步骤

    • 将生成的区域特征图分成若干组,每组特征图代表不同的尺度或区域。

    • 对这些特征图组分别应用不同速率的膨胀深度卷积(也叫空洞卷积),这种卷积允许在不同的感受野上进行处理,以获取不同尺度的上下文信息。

    • 每个卷积操作的作用类似于形态学过滤,只在需要的感受野上提取信息,避免了信息的冗余处理。

3. 特征融合

  • 目标:将提取的多尺度特征进行融合,形成更强的特征表示。

  • 步骤

    • 将所有通过语义残差化处理后的特征图进行拼接(concatenate)。

    • 对拼接后的特征图进行批量归一化(BN),然后通过1x1卷积层进一步融合特征。

    • 最终,将这些融合后的特征与原始输入特征图进行加法操作,构建一个更为全面且强大的特征表示。

4. 输出预测

  • 目标:使用融合后的特征图进行最终的语义分割预测。

  • 步骤

    • 将生成的最终特征图输入到解码器中,解码器通常包括上采样和卷积操作,以恢复到原始图像的分辨率。

    • 解码器生成的特征图经过分类头(SegHead)处理,输出图像的语义分割结果。

通过这些步骤,DWR能够在保持高效计算的同时,提取到丰富的多尺度上下文信息,从而提升语义分割的精度和速度。

2.2 新增yaml文件

关键步骤二在下/yolov5/models下新建文件 yolov5_C3_DWR.yaml并将下面代码复制进去

  • 目标检测yaml文件 
# Ultralytics YOLOv5 🚀, AGPL-3.0 license

# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
anchors:
  - [10, 13, 16, 30, 33, 23] # P3/8
  - [30, 61, 62, 45, 59, 119] # P4/16
  - [116, 90, 156, 198, 373, 326] # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [
    [-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
    [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
    [-1, 3, C3_DWR, [128]],
    [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
    [-1, 6, C3_DWR, [256]],
    [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
    [-1, 9, C3_DWR, [512]],
    [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
    [-1, 3, C3_DWR, [1024]],
    [-1, 1, SPPF, [1024, 5]], # 9
  ]

# YOLOv5 v6.0 head
head: [
    [-1, 1, Conv, [512, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 6], 1, Concat, [1]], # cat backbone P4
    [-1, 3, C3, [512, False]], # 13

    [-1, 1, Conv, [256, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 4], 1, Concat, [1]], # cat backbone P3
    [-1, 3, C3, [256, False]], # 17 (P3/8-small)

    [-1, 1, Conv, [256, 3, 2]],
    [[-1, 14], 1, Concat, [1]], # cat head P4
    [-1, 3, C3, [512, False]], # 20 (P4/16-medium)

    [-1, 1, Conv, [512, 3, 2]],
    [[-1, 10], 1, Concat, [1]], # cat head P5
    [-1, 3, C3, [1024, False]], # 23 (P5/32-large)

    [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
  ]
  • 语义分割yaml文件
# Ultralytics YOLOv5 🚀, AGPL-3.0 license

# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
anchors:
  - [10, 13, 16, 30, 33, 23] # P3/8
  - [30, 61, 62, 45, 59, 119] # P4/16
  - [116, 90, 156, 198, 373, 326] # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [
    [-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
    [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
    [-1, 3, C3_DWR, [128]],
    [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
    [-1, 6, C3_DWR, [256]],
    [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
    [-1, 9, C3_DWR, [512]],
    [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
    [-1, 3, C3_DWR, [1024]],
    [-1, 1, SPPF, [1024, 5]], # 9
  ]

# YOLOv5 v6.0 head
head: [
    [-1, 1, Conv, [512, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 6], 1, Concat, [1]], # cat backbone P4
    [-1, 3, C3, [512, False]], # 13

    [-1, 1, Conv, [256, 1, 1]],
    [-1, 1, nn.Upsample, [None, 2, "nearest"]],
    [[-1, 4], 1, Concat, [1]], # cat backbone P3
    [-1, 3, C3, [256, False]], # 17 (P3/8-small)

    [-1, 1, Conv, [256, 3, 2]],
    [[-1, 14], 1, Concat, [1]], # cat head P4
    [-1, 3, C3, [512, False]], # 20 (P4/16-medium)

    [-1, 1, Conv, [512, 3, 2]],
    [[-1, 10], 1, Concat, [1]], # cat head P5
    [-1, 3, C3, [1024, False]], # 23 (P5/32-large)

    [[17, 20, 23], 1, Segment, [nc, anchors, 32, 256]], # Detect(P3, P4, P5)
  ]

温馨提示:本文只是对yolov5基础上添加模块,如果要对yolov5n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。


# YOLOv5n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
 
# YOLOv5s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
 
# YOLOv5l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
 
# YOLOv5m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple
 
# YOLOv5x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple

2.3 注册模块

关键步骤三在yolo.py的parse_model函数替换添加C3_DWR

2.4 执行程序

在train.py中,将cfg的参数路径设置为yolov5_C3_DWR.yaml的路径

建议大家写绝对路径,确保一定能找到 

🚀运行程序,如果出现下面的内容则说明添加成功🚀 

                 from  n    params  module                                  arguments
  0                -1  1      7040  models.common.Conv                      [3, 64, 6, 2, 2]
  1                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]
  2                -1  3    225088  models.common.C3_DWR                    [128, 128, 3]
  3                -1  1    295424  models.common.Conv                      [128, 256, 3, 2]
  4                -1  6   1661184  models.common.C3_DWR                    [256, 256, 6]
  5                -1  1   1180672  models.common.Conv                      [256, 512, 3, 2]
  6                -1  9   9684736  models.common.C3_DWR                    [512, 512, 9]
  7                -1  1   4720640  models.common.Conv                      [512, 1024, 3, 2]
  8                -1  3  14301696  models.common.C3_DWR                    [1024, 1024, 3]
  9                -1  1   2624512  models.common.SPPF                      [1024, 1024, 5]
 10                -1  1    525312  models.common.Conv                      [1024, 512, 1, 1]
 11                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']
 12           [-1, 6]  1         0  models.common.Concat                    [1]
 13                -1  3   2757632  models.common.C3                        [1024, 512, 3, False]
 14                -1  1    131584  models.common.Conv                      [512, 256, 1, 1]
 15                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']
 16           [-1, 4]  1         0  models.common.Concat                    [1]
 17                -1  3    690688  models.common.C3                        [512, 256, 3, False]
 18                -1  1    590336  models.common.Conv                      [256, 256, 3, 2]
 19          [-1, 14]  1         0  models.common.Concat                    [1]
 20                -1  3   2495488  models.common.C3                        [512, 512, 3, False]
 21                -1  1   2360320  models.common.Conv                      [512, 512, 3, 2]
 22          [-1, 10]  1         0  models.common.Concat                    [1]
 23                -1  3   9971712  models.common.C3                        [1024, 1024, 3, False]        
 24      [17, 20, 23]  1    457725  Detect                                  [80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [256, 512, 1024]]
YOLOv5_C3_DWR summary: 557 layers, 54755773 parameters, 54755773 gradients, 134.0 GFLOPs

3. 完整代码分享

https://pan.baidu.com/s/1Eaoc2hx2jYSFBfiyIWL5Tw?pwd=zbgf

 提取码: zbgf 

4. GFLOPs

关于GFLOPs的计算方式可以查看百面算法工程师 | 卷积基础知识——Convolution

未改进的GFLOPs

img

改进后的GFLOPs

5. 进阶

可以结合损失函数或者卷积模块进行多重改进

YOLOv5改进 | 损失函数 | EIoU、SIoU、WIoU、DIoU、FocuSIoU等多种损失函数——点击即可跳转

6. 总结

DWR(Dilation-wise Residual)的主要原理是通过引入两步特征提取方法来高效获取多尺度上下文信息,以优化实时语义分割的性能。首先,DWR将传统的单步复杂上下文信息提取过程分解为区域残差化(Region Residualization)和语义残差化(Semantic Residualization)两个步骤。在区域残差化中,输入特征图经过卷积和激活处理生成不同尺寸的简洁区域特征图,作为后续形态学过滤的基础。接着,在语义残差化步骤中,对这些区域特征图应用多速率膨胀卷积,从而在每个特征图上实现特定感受野的形态学过滤,避免了感受野的冗余和信息获取的复杂性。通过这种方式,DWR极大简化了多尺度信息的提取过程,使得网络能够以更高的效率和准确性进行实时语义分割。

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
YOLOv8是目标检测领域中的一种经典算法,其以速度快和准确性高而受到广泛关注。在YOLOv8的主干网络上,我们可以进行一些改进来提升其在低照度环境下的性能。 低照度条件下,图像通常会受到噪声的影响,目标的细节和边缘信息可能会被模糊或者丢失,导致目标检测精度受到影响。为了克服这个问题,我们可以引入低照度增强网络来对输入图像进行预处理。低照度增强网络可以根据图像的特点对其进行自适应地增强,提升图像的亮度和对比度,减少噪声的干扰。这样可以使得图像中的目标更加清晰可见,有助于提高YOLOv8的检测精度。 在主干网络的选择方面,我们可以考虑使用Pe-YOLO来替代YOLOv8原有的主干网络。Pe-YOLO是一种经过优化的主干网络,其在保持YOLOv8原有速度优势的同时,能够提升在低照度环境下目标检测的性能。Pe-YOLO采用了一些先进的网络结构和设计技巧,例如注意力机制和残差连接,使得主干网络具有更好的图像特征提取能力和抗干扰能力。 通过将Pe-YOLO用于YOLOv8的主干网络,可以加强对低照度环境下目标的探测能力,提升检测的准确率和鲁棒性。此外,我们还可以对Pe-YOLO进行训练,使其能够更好地适应低照度条件下目标的特征,进一步加强目标检测的效果。 总结而言,yolov8改进中的主干篇,我们可以通过引入低照度增强网络和选择Pe-YOLO作为主干网络来提升在低照度环境下的目标检测性能。这些改进可以有效地减少噪声干扰,提高目标的可见性,在大幅度提升速度的同时,保证准确率和鲁棒性,使得yolov8在低照度条件下仍能取得出色的检测效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay_545

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值