深入浅出之SPP、SPPF、SPPCSPC与ASPP模块(YOLO)

一、池化层

池化层(Pooling Layer)是卷积神经网络(Convolutional Neural Networks, CNNs)中的一个重要组成部分,主要用于减少输入数据的空间尺寸(例如,图像的宽度和高度),同时保持其最重要的信息。这一过程称为下采样(downsampling)或者降维。池化操作通过提取特征图(feature maps)的摘要信息来实现,这些摘要信息通常是原特征的统计量,如最大值、平均值或其他聚合方式的结果。主要目的和作用包括:

  • 减少计算量和参数数量:通过减小特征图的尺寸,池化层显著减少了后续层所需的计算资源和模型中的参数数量,这有助于减轻过拟合并加速训练过程。
  • 增加感受野:池化操作扩大了网络对输入数据的感受野,使得网络能够捕获更广阔的上下文信息,这对于识别较大的图像结构或模式很有帮助。
  • 提供位置不变性:由于池化是对局部区域进行操作,它降低了网络对特征位置的敏感度,使模型对输入中的平移、旋转等变换更加鲁棒。
  • 抑制噪声:通过聚合区域内的特征,池化能减少个别像素噪声的影响,提取更具代表性的特征。

常见的池化类型包括:

  • 最大池化(Max Pooling):选取每个池化窗口内的最大值作为输出。
  • 平均池化(Average Pooling):计算每个池化窗口内所有值的平均值作为输出。
  • 全局池化:对整个特征图进行池化,通常用于网络的最后一层,生成固定长度的输出向量。
  • 可变大小池化(如Spatial Pyramid Pooling, SPP):在不同层级上执行池化,以整合多尺度特征。

池化层通常被插入在卷积层之后,作为卷积神经网络架构的一个标准组件,以提高模型的性能和效率。

在YOLOv4中,SPP(Spatial Pyramid Pooling,空间金字塔池化)是一个重要的组成部分,它主要用于提升模型对不同尺度目标的识别能力。以下是关于YOLOv4中SPP的详细解释:

二、SPPNet网络介绍

SPP是一种允许神经网络处理任意尺寸输入的技术。它通过在不同尺度上对特征图进行池化操作,生成固定长度的特征表示,从而使得网络能够捕捉到多尺度的特征信息。具体来说,SPP通过在特征图上应用不同窗口大小的最大池化,生成多个不同尺度的特征图,然后将这些特征图拼接起来形成最终的特征表示。这种机制使得网络能够更好地适应不同大小的输入图像,并提取出更加丰富的特征信息。

更详细介绍,详见《深入浅出之SPPNET网络

三、SPP版本的演化及各自优缺点

 3.1.SPP空间金字塔池化层

SPP(空间金字塔池化层,Spatial Pyramid Pooling)是一种深度学习中的技术,特别是在卷积神经网络(CNN)中用于处理不同尺寸和比例的输入图像。该技术由何恺明等人在其研究中提出,旨在解决传统CNN需要固定输入图像尺寸的问题,同时提高模型的鲁棒性和泛化能力。以下是SPP的详细解析:

3.1.1.、SPP的基本概念

SPP层的主要作用是将任意尺寸的特征图转换成固定大小的特征向量,从而作为全连接层的输入。这一特性使得SPP层能够处理不同尺寸的输入图像,避免了图像缩放带来的精度损失和计算冗余。

3.1.2、SPP的工作原理

  1. 特征图分割:SPP层将输入的特征图分割成多个不同大小的网格(如1x1、2x2、4x4等)。

  2. 池化操作:对每个网格进行池化操作(通常是最大池化),得到每个网格的特征表示。

  3. 特征拼接:将所有网格的特征表示拼接起来,形成一个固定长度的特征向量。

3.1.3、SPP的优势

  1. 尺度不变性:SPP层能够处理不同尺寸和比例的输入图像,使模型具有尺度不变性。

  2. 减少计算量:通过池化操作,SPP层能够降低特征图的维度,从而减少后续全连接层的计算量。

  3. 提高性能:SPP层能够捕获输入图像的多尺度特征信息,提高模型的性能。

3.1.4、SPP的应用场景

SPP层已经成功应用于多个计算机视觉任务中,包括但不限于图像分类、目标检测、语义分割等。在目标检测任务中,SPP层通常与区域候选网络(RPN)结合使用,以提高检测精度和速度。

3.1.5、SPP的实例分析

以YOLOv3为例,YOLOv3在其网络结构中引入了SPP模块,通过不同尺度的池化操作来融合不同感受野的特征信息。具体来说,YOLOv3在其DarkNet-53主干网络之后添加了一个SPP模块,该模块包含三个不同尺度的最大池化层(池化核大小分别为1x1、5x5、9x9和13x13,但注意这里的描述与常规SPP稍有不同,常规SPP通常使用固定的网格划分而不是不同尺度的池化核),通过拼接这些池化层的输出,YOLOv3能够捕获更丰富的上下文信息,从而提高检测精度。

3.1.6、总结

SPP层作为一种有效的深度学习技术,在处理不同尺寸和比例的输入图像方面表现出色。通过其独特的特征图分割和池化操作,SPP层能够生成固定长度的特征向量,为后续的全连接层提供有效的输入。同时,SPP层还具有尺度不变性、减少计算量和提高性能等优势,已经成为计算机视觉领域中的一种重要技术。


3.2.SPPF快速-空间金字塔池化层

SPPF(Spatial Pyramid Pooling - Fast)是一种在深度学习和计算机视觉领域中使用的技术,特别是在目标检测任务中。它是空间金字塔池化(Spatial Pyramid Pooling,简称SPP)的一个变体或快速版本,旨在提高处理速度和效率,同时保持多尺度特征融合的能力。

以下是对SPPF的详细解析:

3.2.1、SPPF的基本概念

SPPF是SPP的一种改进版本,通过优化池化操作来减少计算量,同时保持模型对多尺度目标的检测性能。在SPP中,通常使用不同大小的池化核来捕获不同尺度的特征信息,而SPPF则通过一种更高效的池化策略来实现这一目标。

3.2.2、SPPF的工作原理

SPPF的工作原理可以概括为以下几点:

  1. 特征图输入:SPPF层接收来自前一层(通常是卷积层)的特征图作为输入。

  2. 快速池化操作:与传统的SPP使用多个不同大小的池化核不同,SPPF通常采用多个小型的池化层(如三层3x3的最大池化)来代替单个大核的池化操作。这种策略减少了计算量,同时保持了多尺度特征融合的能力。

  3. 特征拼接与输出:经过快速池化操作后,SPPF层将不同池化层的输出进行拼接,形成一个固定长度的特征向量。这个特征向量随后可以作为后续全连接层或其他网络层的输入。

3.2.3、SPPF的优势

  1. 高效计算:相比于传统的SPP层,SPPF通过减少池化核的数量和大小显著提升了计算速度,特别是在处理高分辨率特征图时更为明显。

  2. 多尺度特征融合:尽管简化了池化操作,但SPPF仍然保留了SPP的核心优势,即能够融合不同尺度的特征信息,有助于提高模型对物体尺度变化的鲁棒性。

  3. 内存占用减少:通过优化池化策略,SPPF在保持性能的同时降低了模型运行时的内存需求。

3.2.4、SPPF的应用场景

SPPF广泛应用于目标检测等计算机视觉任务中,特别是在需要处理不同尺寸和比例输入图像的场景中。例如,在YOLOv5等目标检测模型中,SPPF模块被嵌入到网络的不同阶段,以便在不同尺度上捕获上下文信息,提高检测的准确性和效率。

3.2.6、总结

SPPF作为SPP的一种快速版本,通过优化池化操作实现了高效计算和多尺度特征融合的目标。它在目标检测等计算机视觉任务中表现出色,为模型带来了显著的性能提升。对于希望提升模型处理速度和效率的开发者来说,了解并掌握SPPF的工作原理和应用方法至关重要。

3.3 SimSPPF(Simplified SPPF)

美团YOLOv6提出的模块,感觉和SPPF只差了一个激活函数,简单测试了一下,单个ConvBNReLU速度比ConvBNSiLU18%

SimSPPF(Simplified Spatial Pyramid Pooling - Fast)是YOLOv6中提出的一种简化的空间金字塔池化模块,主要用于计算机视觉任务中的特征提取。以下是关于SimSPPF的详细介绍:

3.3.1、设计原理及特点

  1. 简化设计
    • SimSPPF模块的设计相比传统的SPP和SPPF更为简化,它通过减少不必要的计算步骤和参数,提高了计算效率。
  2. 多尺度特征提取
    • SimSPPF仍然保留了空间金字塔池化的核心优势,即能够提取多尺度的特征。这对于目标检测等任务至关重要,因为不同大小的目标需要不同尺度的特征来进行准确识别。
  3. 高效计算
    • 通过采用更高效的池化操作和卷积操作,SimSPPF模块在计算速度上有了显著提升。这使得它适用于对实时性要求较高的计算机视觉任务。
  4. 融合特征
    • SimSPPF通过多次最大池化和拼接操作,实现了对不同尺度特征的融合。这种融合后的特征包含了更丰富的信息,有助于提升模型的识别性能。

3.3.2、应用及影响

  1. 目标检测
    • SimSPPF模块在YOLOv6等目标检测模型中得到了应用。通过引入SimSPPF模块,这些模型在保持较高识别精度的同时,显著提升了计算速度和降低了内存占用。
  2. 计算机视觉任务
    • 除了目标检测外,SimSPPF模块还可以应用于其他计算机视觉任务,如图像分类、图像分割等。这些任务同样需要处理多尺度特征,并追求高效计算。
  3. 模型优化
    • SimSPPF模块的出现为模型优化提供了新的思路。通过简化设计和高效计算,可以在不牺牲太多精度的前提下,显著提升模型的运行效率。

3.3.3、实现细节

  1. 卷积操作
    • SimSPPF模块通常包含一个初始的卷积层(如SimConv),用于对输入特征图进行初步处理。这个卷积层可以降低通道数并提取初步特征。
  2. 池化操作
    • 在卷积层之后,SimSPPF模块会进行多次最大池化操作。这些池化操作会生成不同尺度的特征图。
  3. 拼接操作
    • 将不同尺度的特征图进行拼接,得到融合后的特征图。这个特征图包含了多尺度的信息,有助于提升模型的识别性能。
  4. 后续处理
    • 融合后的特征图通常会经过一个额外的卷积层(如SimConv)进行处理,以将其转换为指定的输出通道数。

综上所述,SimSPPF是一种简化的空间金字塔池化模块,它通过简化设计和高效计算实现了多尺度特征提取和高效计算。在目标检测等计算机视觉任务中,SimSPPF模块的应用有助于提升模型的识别性能和运行效率。

3.4.SPPCSPC结合跨阶段部分卷积的空间金字塔池化

SPPCSPC是深度学习领域中,特别是在卷积神经网络(CNN)架构中的一个模块,它结合了Spatial Pyramid Pooling(SPP)和Cross Stage Partial Networks(CSPN)的概念。这一模块主要用于提升模型的多尺度特征表达能力和计算效率,尤其在目标检测等计算机视觉任务中表现出色。以下是对SPPCSPC的详细解析:

3.4.1、SPPCSPC的定义与原理

SPPCSPC通过在一串卷积中加入并行的多次MaxPool操作,并结合CSPN的结构,来实现对多尺度特征的有效提取和融合。SPP层能够将任意大小的特征图转换成固定大小的特征向量,有效避免了由于图像裁剪、缩放等操作导致的图像失真问题,并解决了卷积神经网络对图像重复特征提取的难题。而CSPN结构则通过分割和复用特征图,减少了计算量,同时保持了模型的表达能力。

3.4.2、SPPCSPC的组成

SPPCSPC模块通常由以下几个部分组成:

  1. 卷积层:用于对输入特征图进行初步的特征提取。

  2. SPP层:在卷积层之后,通过不同大小的池化核进行并行的最大池化操作,以捕获不同尺度的特征信息。

  3. CSPN结构:对SPP层输出的特征图进行进一步的处理,通过分割和复用特征图,减少计算量,同时提升模型的表达能力。

3.4.3、SPPCSPC的优势

  1. 多尺度特征提取:SPP层有效整合了不同尺度的上下文信息,提高了模型对尺度变化的适应性。

  2. 计算效率与性能平衡:CSPN结构通过分割和复用特征图,减少了计算量,同时保持了模型的表达能力,实现了计算效率与性能的平衡。

  3. 灵活性与扩展性:通过调整卷积层参数、SPP的池化核大小和数量等,可以灵活适应不同的任务需求和资源限制。

3.4.4、应用场景

SPPCSPC模块广泛应用于计算机视觉领域,特别是在目标检测任务中。例如,在YOLOv7等目标检测模型中,SPPCSPC模块被用作网络架构的一部分,以提升模型对多尺度目标的检测能力。

3.4.5、注意事项

  1. 调参复杂度:SPP的池化核大小、CSPN的划分策略等超参数的选择对模型性能有显著影响,增加了调参的复杂度。

  2. 内存占用与计算开销:对于大规模输入或深度网络,SPPCSPC模块可能会导致较高的内存占用和计算开销。

综上所述,SPPCSPC模块通过结合SPP和CSPN的优势,有效提升了模型的多尺度特征表达能力和计算效率,在目标检测等计算机视觉任务中展现出了良好的性能。然而,在实际应用中需要注意调参复杂度和计算开销等问题。

3.5 SPPFCSPC结合跨阶段部分卷积的快速空间金字塔池化

借鉴了SPPF的思想将SPPCSPC优化了一下,得到了SPPFCSPC,在保持感受野不变的情况下获得速度提升;

目前这个结构被YOLOv6 3.0版本使用了,效果很不错,大家可以看YOLOv6 3.0的论文,里面有详细的实验结果。

SPPFCSPC(Spatial Pyramid Pooling Faster Cross Stage Partial Channel)是一个旨在增强卷积神经网络能力的模块,特别是在物体检测任务中。以下是对SPPFCSPC的详细解析:

3.5.1、关键组件与原理

  1. 经典SPP结构
    • SPP(Spatial Pyramid Pooling)用于提高模型对空间布局和物体变化的鲁棒性。它通过在不同尺度上对特征图进行池化操作,生成固定长度的特征向量,使得网络能够更好地适应不同大小的输入图像,并提取出更加丰富的特征信息。
  2. SPPF结构
    • SPPF(Spatial Pyramid Pooling Faster)是SPP的一个变体或快速版本。它使用较小的核心结构进行池化,从而产生二次池化以实现更丰富的特征融合。SPPF通过减少计算负荷并提高了模型速度,同时保持了多尺度特征融合的能力。
  3. SPPCSPC结构
    • SPPCSPC结合了Spatial Pyramid Pooling(SPP)和Cross Stage Partial Networks(CSPNet)的概念。它由与最大池化层连接的多个卷积块(CBS模块)组成的串行结构,这些最大池化层的感知范围设置为特定大小(如5×5、9×9、13×13)。SPPCSPC主要用于提升模型的多尺度特征表达能力和计算效率。
  4. SPPFCSPC结构
    • SPPFCSPC是SPPCSPC的改进版本或变体。它结合了SPPF和CSPNet的优势,采用分组卷积操作对特征图进行处理。SPPFCSPC通过结合多个分组卷积块(包括1×1和3×3卷积)和具有相同感受野的串行最大池化层,进一步增强了模型的特征提取能力。

3.5.2、主要操作步骤

SPPFCSPC的主要操作步骤可以分为以下几个阶段:

  1. 数据输入:输入预处理和增强后的图像数据。
  2. 数据预处理:包括调整图像大小、归一化、数据增强(如旋转、缩放、颜色变换等)。
  3. 卷积操作:初始卷积层对输入图像进行特征提取,生成特征图。这些层通常包含卷积、批量归一化和激活函数。
  4. 池化操作:对特征图进行池化操作(如最大池化),以减少特征图的尺寸和计算量。
  5. 空间金字塔池化(SPP):使用不同大小的池化核对特征图进行多尺度池化,生成固定尺寸的特征向量。
  6. 快速空间金字塔池化(SPPF):通过多个小型的池化层代替单个大核的池化操作,进一步丰富特征信息并减少计算开销。
  7. Cross Stage Partial Network(CSPNet)模块:将特征图分成两部分,其中一部分直接通过残差连接到后续层,另一部分经过卷积操作后再合并。这样可以减少冗余梯度信息,提升梯度流动和特征复用能力。

3.5.3、应用与优势

SPPFCSPC模块在物体检测任务中表现出色,其优势主要体现在以下几个方面:

  1. 多尺度特征提取:通过结合SPP和SPPF的多尺度池化策略,SPPFCSPC能够提取不同尺度的特征信息,增强模型对不同大小和比例对象的鲁棒性。
  2. 高效计算:SPPFCSPC通过优化池化操作和减少计算负荷,提高了模型的计算效率,使得模型在保持较高识别精度的同时,能够更快地进行推理。
  3. 特征复用与梯度流动:通过引入CSPNet模块,SPPFCSPC能够减少冗余梯度信息,提升梯度流动和特征复用能力,有助于模型的收敛和性能提升。

综上所述,SPPFCSPC是一个结合了SPP、SPPF和CSPNet优势的卷积神经网络模块,在物体检测等计算机视觉任务中具有广泛的应用前景。

3.6  ASPP带孔空间金字塔池化

ASPP(Atrous Spatial Pyramid Pooling)是一种在深度学习和计算机视觉中常用的卷积神经网络(CNN)模块,特别是在语义分割和图像理解任务中。ASPP模块通过结合不同采样率的空洞卷积(atrous convolution,也称为扩张卷积或膨胀卷积)以及图像级特征来增强网络捕获多尺度上下文信息的能力。

3.6.1、ASPP的组成

ASPP模块通常由以下几个部分组成:

  1. 多个并行的空洞卷积层:这些卷积层使用不同的空洞率(dilation rates),以便在不同的感受野上捕获信息。空洞卷积通过在卷积核的元素之间插入“空洞”来增加感受野,而不需要增加卷积核的大小或额外的计算成本。这有助于模型捕获不同尺度的上下文信息。

  2. 图像级特征:ASPP模块通常还包含一个全局平均池化层,用于生成图像级特征。这些特征随后通过上采样(如双线性插值)与空洞卷积层的输出进行融合,以引入全局上下文信息。

  3. 1x1卷积层:在将不同空洞率的空洞卷积输出和图像级特征融合之前,通常会使用1x1卷积来减少通道数,以节省计算资源并防止过拟合。

  4. 融合操作:最后,所有并行的空洞卷积输出和图像级特征通过拼接(concatenation)或求和(summation)等方式进行融合,形成最终的多尺度特征表示。

3.6.2、ASPP的优势

  1. 多尺度上下文信息:通过不同空洞率的空洞卷积和图像级特征,ASPP能够捕获丰富的多尺度上下文信息,这对于语义分割等任务至关重要。

  2. 高效计算:相比于传统的多尺度处理方法(如图像金字塔),ASPP通过空洞卷积在单个输入上直接捕获多尺度信息,从而减少了计算量和内存占用。

  3. 灵活性:ASPP模块可以轻松地集成到现有的CNN架构中,以增强其性能,而无需对整体架构进行重大修改。

3.6.3、ASPP的应用场景

ASPP模块已被广泛应用于各种语义分割和图像理解任务中,如城市景观分割、医学图像分析、自动驾驶等。在DeepLab系列模型中,ASPP模块是核心组件之一,用于提升模型对复杂场景的分割能力。

3.6.4、总结

ASPP是一种有效的多尺度上下文信息捕获模块,通过结合不同空洞率的空洞卷积和图像级特征,ASPP能够显著提升CNN在语义分割等任务中的性能。随着深度学习技术的不断发展,ASPP及其变体将继续在计算机视觉领域发挥重要作用。

3.7、SPP、SPPF、SimSPPF、SPPCSPC及ASPP对比 

SPP(Spatial Pyramid Pooling)、SPPF(Spatial Pyramid Pooling - Fast)、SimSPPF(Simplified SPPF)、SPPCSPC以及ASPP(Atrous Spatial Pyramid Pooling)在输入尺寸要求、计算效率、参数量、特征提取能力和应用场景等方面存在显著的差异。以下是对这些方面的详细对比:

模块输入尺寸要求计算效率参数量特征提取能力应用场景
SPP任意尺寸中等中等多尺度特征提取图像分类、目标检测、语义分割
SPPF任意尺寸较低多尺度特征提取目标检测(如YOLOv5)
SimSPPF任意尺寸较高较低多尺度特征提取计算机视觉任务(如YOLOv6)
SPPCSPC任意尺寸依实现而定依实现而定多尺度特征提取与CSPN结合目标检测等计算机视觉任务
ASPP任意尺寸中等至高(依实现而定)中等至高(依实现而定)多尺度上下文信息捕获语义分割(如DeepLab系列)

3.7.1、输入尺寸要求

  • SPP、SPPF、SimSPPF:这些模块均能够处理任意尺寸的输入图像,无需对图像进行裁剪或缩放等预处理操作,保留了图像的原始信息。
  • SPPCSPC:同样能够处理任意尺寸的输入,但由于结合了CSPN的概念,其输入处理可能涉及更复杂的操作。
  • ASPP:也接受任意尺寸的输入,适用于各种尺寸的图像或特征图。

3.7.2、计算效率

  • SPP:计算效率中等,因为需要对不同尺度的子区域进行池化操作。
  • SPPF:通过优化池化策略,显著提高了计算速度,特别是在处理高分辨率特征图时更为明显。
  • SimSPPF:在SPPF的基础上进一步简化了设计,通常具有更高的计算效率。
  • SPPCSPC:计算效率取决于具体实现,可能涉及额外的CSPN操作。
  • ASPP:计算效率中等至高,取决于空洞卷积的采样率和并行处理的实现方式。

3.7.3、参数量

  • SPP:参数量中等,主要取决于卷积层的数量和大小。
  • SPPF:由于简化了池化操作,参数量通常较低。
  • SimSPPF:参数量与SPPF相似或更低,因为可能采用了更简单的卷积模块。
  • SPPCSPC:参数量取决于SPP和CSPN的具体实现。
  • ASPP:参数量中等至高,因为使用了多个并行空洞卷积。

3.7.4、特征提取能力

  • SPP、SPPF、SimSPPF:这些模块均能够提取多尺度的特征信息,增强了网络对不同大小目标的适应能力。
  • SPPCSPC:结合了SPP和CSPN的优点,具有更强的多尺度特征表达能力和计算效率。
  • ASPP:通过不同采样率的空洞卷积捕获多尺度的上下文信息,特别适用于语义分割任务。

3.7.5、应用场景

  • SPP:广泛应用于图像分类、目标检测和语义分割等计算机视觉任务。
  • SPPF:特别适用于目标检测任务,如YOLOv5等模型。
  • SimSPPF:在YOLOv6等计算机视觉任务中表现出色。
  • SPPCSPC:适用于需要提升多尺度特征表达能力和计算效率的目标检测等任务。
  • ASPP:是语义分割模型DeepLab系列的重要组成部分,也适用于其他需要多尺度上下文信息的任务。

综上所述,这些模块在输入尺寸要求、计算效率、参数量、特征提取能力和应用场景等方面各有优势。在选择使用哪个模块时,需要根据具体任务的需求和模型的性能要求进行权衡。

3.8、SPPCPC与SPPFCSPC

为什么使用SPPCPC代替SPPFCSPC(Yolov5的SPPF比SPP快得多 为什么不尝试用SPPFCSPC替换SPPCSPC)

在探讨为何使用SPPCPC(如果这里指的是SPP Cross Stage Partial Channel或其类似变体,注意原问题中可能存在笔误,应为SPPCSPC的类似表述,但为保持问题一致性,以下仍用SPPCPC代替讨论)代替SPPFCSPC时,我们需要从多个角度进行分析。然而,需要指出的是,直接比较SPPCPC和SPPFCSPC的文献或公开资料相对较少,因此以下分析基于一般性的理解和推理。

  1. 计算效率与模型复杂度
    • SPPFCSPC(Spatial Pyramid Pooling Faster Cross Stage Partial Channel)通常结合了多种技术,如分组卷积、最大池化等,旨在提高计算效率和特征提取能力。然而,其复杂的结构可能带来较高的计算负荷和模型复杂度。
    • 相比之下,如果SPPCPC在保持多尺度特征提取能力的同时,通过更简洁的结构或优化策略降低了计算复杂度,那么它可能成为一个更优的选择。例如,SPPCPC可能采用了更少的卷积层、更小的卷积核或更高效的池化策略。
  2. 特征提取能力
    • SPPFCSPC通过分组卷积和多个最大池化层来提取多尺度特征,这有助于模型在处理复杂场景和多变尺寸目标时表现出色。
    • SPPCPC如果也具备类似的多尺度特征提取能力,并且能够通过更少的参数和计算量实现这一点,那么它在特征提取方面可能更具优势。
  3. 模型泛化能力
    • 模型的泛化能力是指其在未见过的数据上的表现能力。SPPFCSPC通过复杂的结构可能在一定程度上提高了模型的泛化能力,但这也可能带来过拟合的风险。
    • SPPCPC如果能够通过更简洁的结构和更有效的正则化策略来平衡模型的复杂性和泛化能力,那么它可能在实际应用中表现出更好的性能。
  4. 实现难度与兼容性
    • SPPFCSPC的结构相对复杂,实现起来可能更具挑战性。此外,它可能需要与特定的模型架构或框架兼容。
    • 如果SPPCPC在保持性能的同时具有更简单的结构和更广泛的兼容性,那么它可能更容易被集成到现有的模型或框架中。
  5. 实际应用需求
    • 在实际应用中,选择哪种结构往往取决于具体的任务需求、计算资源和时间限制等因素。例如,在实时性要求较高的场景中,计算效率可能更为重要;而在需要处理复杂场景和多变尺寸目标的场景中,特征提取能力可能更为关键。

综上所述,使用SPPCPC代替SPPFCSPC的原因可能包括计算效率更高、特征提取能力更强、模型泛化能力更好、实现难度更低以及更好的实际应用兼容性等。然而,这些结论需要基于具体的实验数据和对比分析来验证。在实际应用中,我们应该根据具体的需求和资源来选择最合适的结构。

四、YOLO中的SPP结构

4.1 SPP与YOLO关系

SPP(Spatial Pyramid Pooling,空间金字塔池化)、SPPF(Spatial Pyramid Pooling - Fast,快速空间金字塔池化)、SPPCSPC(Spatial Pyramid Pooling with Cross Stage Partial Convolutions,结合跨阶段部分卷积的空间金字塔池化)以及ASPP(Atrous Spatial Pyramid Pooling,空洞空间金字塔池化)与YOLO(You Only Look Once)系列目标检测算法之间存在着紧密的联系。以下是对这些池化技术与YOLO关系的详细解析:

SPP与YOLO

  • SPP简介:SPP是一种在不同层级上执行池化的技术,旨在整合多尺度特征,提高模型对多尺度目标检测的准确性。该技术最初在YOLOv3-SPP模型中被引入,并显著提升了模型性能。

  • 与YOLO的关系:SPP是YOLOv3-SPP模型的关键组成部分,帮助模型更好地理解不同尺度下的特征,从而提高对多尺度目标的检测能力。在YOLOv4及后续版本中,SPP的思想被继续沿用并优化。

SPPF与YOLO

  • SPPF简介:SPPF是YOLOv5模型中采用的一种改进型空间金字塔池化层,由Glenn Jocher设计。它旨在加速SPP的计算过程,同时保持多尺度特征融合的能力。

  • 与YOLO的关系:SPPF作为YOLOv5中的一个组件,进一步提升了模型在保持高精度检测的同时的计算效率,尤其适用于移动端或资源受限的设备。

SPPCSPC与YOLO

  • SPPCSPC简介:SPPCSPC结合了SPP和CSP(Cross Stage Partial Networks)的概念,主要用于YOLO系列的改进版本中。它通过分割和复用特征图,减少计算量,同时保持模型的表达能力。

  • 与YOLO的关系:SPPCSPC在YOLOv7等版本中得到了应用,通过其多尺度特征提取和计算效率与性能平衡的特点,进一步增强了模型的检测性能。

ASPP与YOLO

  • ASPP简介:ASPP是一种用于提取多尺度特征的深度学习技术,常见于语义分割任务。它通过不同膨胀率的空洞卷积获取不同感受野的特征,并通过全局池化和1×1卷积获取全局信息。

  • 与YOLO的关系:虽然ASPP在YOLO系列中不是直接的组成部分,但其多尺度特征提取的思想对YOLO的发展有所启发。YOLO系列算法也在不断优化其多尺度特征提取能力,以应对复杂多变的检测场景。

综上所述,SPP、SPPF、SPPCSPC和ASPP等池化技术在一定程度上影响了YOLO系列目标检测算法的发展。它们通过不同的方式提升了模型对多尺度目标的检测能力、计算效率和鲁棒性,为YOLO在各类检测任务中的广泛应用奠定了坚实的基础。

4.2 SPP在YOLO中版本

YOLO系列中的SPP(Spatial Pyramid Pooling,空间金字塔池化)模块是一种用于提升目标检测性能的技术。随着YOLO系列的不断发展,SPP模块也经历了不同的演化版本。以下是对YOLO SPP模块演化版本的概述:

1. YOLOv3-SPP

在YOLOv3的基础上,YOLOv3-SPP通过在特征提取网络中的特定位置(如第五、六层卷积之间)集成SPP模块,来提升检测性能。SPP模块主要由不同大小的池化操作组成,这些池化操作并行进行,并将结果拼接起来,从而融合局部特征和全局特征。这种设计有助于模型更好地处理不同尺度的目标,并提高检测的精度。

2. YOLOv3的衍生版本

YOLOv3还衍生出了多个包含SPP模块的不同版本,如YOLOv3-SPP1(仅在第一个检测头前集成SPP模块)、YOLOv3-SPP3(在三个检测头前都加入了SPP模块)等。这些版本通过在不同位置集成SPP模块,进一步探索了SPP模块在YOLOv3框架中的潜力。

3. YOLOv4及后续版本

虽然YOLOv4及其后续版本(如YOLOv5、YOLOv6、YOLOv7等)在架构和性能上进行了大量优化,但直接提及SPP模块作为独立组件的演化并不明显。这些版本更多地关注于整体架构的创新、特征提取器的改进、训练策略的调整以及数据增强技术的应用等方面。然而,SPP模块的思想(即空间金字塔池化)仍然在这些版本的某些组件中得到了体现,如通过不同尺度的特征融合来提升模型的检测能力。

 在YOLOv4中,SPP被用作Neck网络的附加模块,以增强特征的多样性和鲁棒性。YOLOv4的Neck网络不仅包含了SPP模块,还结合了自顶向下的FPN(特征金字塔网络)和自底向上的PAN(路径聚合网络)特征金字塔,以进一步提升网络的特征提取能力。SPP模块通过融合不同尺度大小的特征图,使得网络能够捕捉到更加全面的特征信息,从而提高目标检测的精度。

4. SPP模块在其他YOLO版本中的应用

除了上述明确提及SPP模块的版本外,SPP的思想还可能在其他YOLO版本中以不同的形式出现。例如,在YOLOv5等版本中,虽然可能没有直接命名为SPP模块,但可能通过多尺度特征融合、金字塔结构等设计来实现类似SPP的功能。

5. SPP模块的未来发展

随着目标检测技术的不断进步和深度学习理论的深入发展,SPP模块及其变体有望在未来的YOLO版本中继续发挥重要作用。研究人员可能会探索更多创新的设计来优化SPP模块的性能和效率,以满足不同应用场景下的需求。

总之,SPP模块作为YOLO系列中的一个重要组件,在提升目标检测性能方面发挥了重要作用。随着YOLO系列的不断发展和完善,SPP模块也经历了不同的演化版本,并在不同的版本中得到了应用和优化。

4.3、应用

  • 1) : 各个代码放入common.py
  • (2): yolo.py中加入类名
  • (3): 修改配置文件

yolov5配置文件如下:

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license

# 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, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   # [-1, 1, ASPP, [512]],  # 9
   # [-1, 1, SPP, [1024]],
   # [-1, 1, SimSPPF, [1024, 5]],
   # [-1, 1, SPPCSPC, [1024]],
   # [-1, 1, SPPFCSPC, [1024, 5]], # 🍀
  ]

五、pytorch实现 

import torch
import torch.nn as nn
import torch.nn.functional as F
import warnings


# 假设Conv是一个自定义的或来自其他库的卷积层,这里我们简单地使用nn.Conv2d作为替代
class Conv(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=1, stride=1, groups=1, bias=False):
        super(Conv, self).__init__()
        padding = kernel_size // 2
        self.conv = nn.Conv2d(
            in_channels,
            out_channels,
            kernel_size=kernel_size,
            stride=stride,
            padding=padding,
            groups=groups,
            bias=bias,
        )
        self.bn = nn.BatchNorm2d(out_channels)
        self.act = nn.SiLU()

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

class SimConv(nn.Module):
    '''Normal Conv with ReLU activation'''
    def __init__(self, in_channels, out_channels, kernel_size, stride, groups=1, bias=False):
        super().__init__()
        padding = kernel_size // 2
        self.conv = nn.Conv2d(
            in_channels,
            out_channels,
            kernel_size=kernel_size,
            stride=stride,
            padding=padding,
            groups=groups,
            bias=bias,
        )
        self.bn = nn.BatchNorm2d(out_channels)
        self.act = nn.ReLU()

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):
        return self.act(self.conv(x))


# SPP层的定义(与之前相同)
class SimConv(nn.Module):
    '''Normal Conv with ReLU activation'''
    def __init__(self, in_channels, out_channels, kernel_size, stride, groups=1, bias=False):
        super().__init__()
        padding = kernel_size // 2
        self.conv = nn.Conv2d(
            in_channels,
            out_channels,
            kernel_size=kernel_size,
            stride=stride,
            padding=padding,
            groups=groups,
            bias=bias,
        )
        self.bn = nn.BatchNorm2d(out_channels)
        self.act = nn.ReLU()

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):
        return self.act(self.conv(x))

class SPP(nn.Module):
    # Spatial Pyramid Pooling (SPP) layer
    def __init__(self, c1, c2, k=(5, 9, 13)):
        super(SPP, self).__init__()
        c_ = c1 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
        self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])

    def forward(self, x):
        x = self.cv1(x)
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')  # 抑制torch 1.9.0 max_pool2d()警告
            return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))

        # 测试程序

class SPPF(nn.Module):
    # Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
    def __init__(self, c1, c2, k=5):  # equivalent to SPP(k=(5, 9, 13))
        super().__init__()
        c_ = c1 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * 4, c2, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)

    def forward(self, x):
        x = self.cv1(x)
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')  # suppress torch 1.9.0 max_pool2d() warning
            y1 = self.m(x)
            y2 = self.m(y1)
            return self.cv2(torch.cat((x, y1, y2, self.m(y2)), 1))


class SimSPPF(nn.Module):
    '''Simplified SPPF with ReLU activation'''
    def __init__(self, in_channels, out_channels, kernel_size=5):
        super().__init__()
        c_ = in_channels // 2  # hidden channels
        self.cv1 = SimConv(in_channels, c_, 1, 1)
        self.cv2 = SimConv(c_ * 4, out_channels, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=kernel_size, stride=1, padding=kernel_size // 2)

    def forward(self, x):
        x = self.cv1(x)
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')
            y1 = self.m(x)
            y2 = self.m(y1)
            return self.cv2(torch.cat([x, y1, y2, self.m(y2)], 1))

# without BN version
class ASPP(nn.Module):
    def __init__(self, in_channel=512, out_channel=256):
        super(ASPP, self).__init__()
        self.mean = nn.AdaptiveAvgPool2d((1, 1))  # (1,1)means ouput_dim
        self.conv = nn.Conv2d(in_channel,out_channel, 1, 1)
        self.atrous_block1 = nn.Conv2d(in_channel, out_channel, 1, 1)
        self.atrous_block6 = nn.Conv2d(in_channel, out_channel, 3, 1, padding=6, dilation=6)
        self.atrous_block12 = nn.Conv2d(in_channel, out_channel, 3, 1, padding=12, dilation=12)
        self.atrous_block18 = nn.Conv2d(in_channel, out_channel, 3, 1, padding=18, dilation=18)
        self.conv_1x1_output = nn.Conv2d(out_channel * 5, out_channel, 1, 1)

    def forward(self, x):
        size = x.shape[2:]

        image_features = self.mean(x)
        image_features = self.conv(image_features)
        image_features = F.upsample(image_features, size=size, mode='bilinear')

        atrous_block1 = self.atrous_block1(x)
        atrous_block6 = self.atrous_block6(x)
        atrous_block12 = self.atrous_block12(x)
        atrous_block18 = self.atrous_block18(x)

        net = self.conv_1x1_output(torch.cat([image_features, atrous_block1, atrous_block6,
                                              atrous_block12, atrous_block18], dim=1))
        return net

class SPPCSPC(nn.Module):
    # CSP https://github.com/WongKinYiu/CrossStagePartialNetworks
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5, k=(5, 9, 13)):
        super(SPPCSPC, self).__init__()
        c_ = int(2 * c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(c_, c_, 3, 1)
        self.cv4 = Conv(c_, c_, 1, 1)
        self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
        self.cv5 = Conv(4 * c_, c_, 1, 1)
        self.cv6 = Conv(c_, c_, 3, 1)
        self.cv7 = Conv(2 * c_, c2, 1, 1)

    def forward(self, x):
        x1 = self.cv4(self.cv3(self.cv1(x)))
        y1 = self.cv6(self.cv5(torch.cat([x1] + [m(x1) for m in self.m], 1)))
        y2 = self.cv2(x)
        return self.cv7(torch.cat((y1, y2), dim=1))


class SPPFCSPC(nn.Module):

    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5, k=5):
        super(SPPFCSPC, self).__init__()
        c_ = int(2 * c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(c_, c_, 3, 1)
        self.cv4 = Conv(c_, c_, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
        self.cv5 = Conv(4 * c_, c_, 1, 1)
        self.cv6 = Conv(c_, c_, 3, 1)
        self.cv7 = Conv(2 * c_, c2, 1, 1)

    def forward(self, x):
        x1 = self.cv4(self.cv3(self.cv1(x)))
        x2 = self.m(x1)
        x3 = self.m(x2)
        y1 = self.cv6(self.cv5(torch.cat((x1, x2, x3, self.m(x3)), 1)))
        y2 = self.cv2(x)
        return self.cv7(torch.cat((y1, y2), dim=1))

class BasicConv(nn.Module):

    def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, dilation=1, groups=1, relu=True, bn=False):
        super(BasicConv, self).__init__()
        self.out_channels = out_planes
        if bn:
            self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=False)
            self.bn = nn.BatchNorm2d(out_planes, eps=1e-5, momentum=0.01, affine=True)
            self.relu = nn.ReLU(inplace=True) if relu else None
        else:
            self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=True)
            self.bn = None
            self.relu = nn.ReLU(inplace=True) if relu else None

    def forward(self, x):
        x = self.conv(x)
        if self.bn is not None:
            x = self.bn(x)
        if self.relu is not None:
            x = self.relu(x)
        return x


class BasicRFB(nn.Module):

    def __init__(self, in_planes, out_planes, stride=1, scale=0.1, map_reduce=8, vision=1, groups=1):
        super(BasicRFB, self).__init__()
        self.scale = scale
        self.out_channels = out_planes
        inter_planes = in_planes // map_reduce

        self.branch0 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1, groups=groups, relu=False),
            BasicConv(inter_planes, 2 * inter_planes, kernel_size=(3, 3), stride=stride, padding=(1, 1), groups=groups),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=vision + 1, dilation=vision, relu=False, groups=groups)
        )
        self.branch1 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1, groups=groups, relu=False),
            BasicConv(inter_planes, 2 * inter_planes, kernel_size=(3, 3), stride=stride, padding=(1, 1), groups=groups),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=vision + 2, dilation=vision + 2, relu=False, groups=groups)
        )
        self.branch2 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1, groups=groups, relu=False),
            BasicConv(inter_planes, (inter_planes // 2) * 3, kernel_size=3, stride=1, padding=1, groups=groups),
            BasicConv((inter_planes // 2) * 3, 2 * inter_planes, kernel_size=3, stride=stride, padding=1, groups=groups),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=vision + 4, dilation=vision + 4, relu=False, groups=groups)
        )

        self.ConvLinear = BasicConv(6 * inter_planes, out_planes, kernel_size=1, stride=1, relu=False)
        self.shortcut = BasicConv(in_planes, out_planes, kernel_size=1, stride=stride, relu=False)
        self.relu = nn.ReLU(inplace=False)

    def forward(self, x):
        x0 = self.branch0(x)
        x1 = self.branch1(x)
        x2 = self.branch2(x)

        out = torch.cat((x0, x1, x2), 1)
        out = self.ConvLinear(out)
        short = self.shortcut(x)
        out = out * self.scale + short
        out = self.relu(out)

        return out


def test_spp_layer():
    # 定义一个简单的输入张量,形状为(batch_size, in_channels, height, width)
    batch_size = 1
    in_channels = 64  # 假设输入通道数为64
    height, width = 36, 36  # 假设输入图像大小为32x32
    x = torch.randn(batch_size, in_channels, height, width)  # 随机生成输入数据

    # 实例化SPP层
    c1 = in_channels  # 输入通道数
    c2 = 64  # 输出通道数,可以根据需要调整
    spp_layer = SPPFCSPC(c1, c2)

    # 通过SPP层传递输入张量
    output = spp_layer(x)

    # 打印输出张量的形状
    print("Output shape:", output.shape)


# 运行测试
test_spp_layer()

注意

  1. 在上面的示例中,我省略了批量归一化(Batch Normalization)和ReLU激活函数,但在实际应用中,你很可能需要在每个卷积层后面添加这些层。

  2. 全局平均池化分支中的nn.Upsample层的size参数需要根据你的实际输入尺寸动态设置,或者你可以使用scale_factor来指定上采样的比例(但这需要你知道输入和输出尺寸之间的比例关系)。在上面的示例中,我使用了size=Nonemode='bilinear'来示意性地展示上采样过程,但在实际代码中你需要根据具体情况进行调整。

  3. 空洞卷积(dilation)允许你增加感受野而不增加参数数量或计算量,这在处理多尺度信息时非常有用。

  4. ASPP模块通常与其他组件(如编码器-解码器结构)一起使用,以构建完整的图像分割网络。

六、总结

SPP(Spatial Pyramid Pooling,空间金字塔池化)、SPPF、SimSPPF、SPPCSPC及ASPP都是深度学习中重要的空间金字塔池化结构,它们在图像处理和目标检测任务中发挥着关键作用。以下是对这些结构的总结:

6.1、SPP(Spatial Pyramid Pooling)

  • 提出:由何恺明在2015年的论文《Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition》中提出。

  • 功能

    • 解决了卷积神经网络对图像相关重复特征提取的问题。
    • 避免了对图像区域的裁剪、缩放操作导致的图像失真等问题。
    • 提高了产生候选框的速度,节省了计算成本。
    • 可以对任意输入尺寸产生定长输出,这是滑窗池化所做不到的。
    • 使用的多梯度的空间划分,而滑窗池化只能有固定的窗大小。
    • 可以从各种大小的图片中提取特征信息,灵活性好。
  • 应用:常用于目标检测模型中,如YOLO系列等。

6.2、SPPF(Spatial Pyramid Pooling-Fast)

  • 提出:由YOLOv5的作者基于SPP提出,是SPP的一种快速实现方式。

  • 特点

    • 相比SPP,SPPF具有更高的计算效率,速度提升了2.5倍。
    • 保留了SPP的多尺度特征提取能力。
  • 应用:在YOLOv5等目标检测模型中,SPPF模块被用于对backbone提取的特征进行进一步的融合和增强,以提高目标检测的准确性。

6.3、SimSPPF(Simplified Spatial Pyramid Pooling-Fast)

  • 提出:由美团的YOLOv6提出,是SPPF的简化版本。

  • 特点

    • 设计更加简化,计算效率更高。
    • 通过一系列卷积和池化操作,将输入特征图转化为多尺度的特征表示。
    • 有效地提取多尺度特征,并融合这些特征以增强模型对不同大小物体的识别能力。
  • 应用:主要用于计算机视觉任务中的特征提取,特别是在对实时性要求较高的场景中。

6.4、SPPCSPC(Spatial Pyramid Pooling-Cross Stage Partial Connections)

  • 提出:结合了SPP和CSP(Cross Stage Partial Connections)两种设计思想。

  • 功能

    • 在SPP的基础上,使用多个不同的池化核尺寸进行特征池化,提取多尺度上下文信息。
    • 引入CSP结构,将特征分成两部分处理,最后再融合,既保留了原始特征,又增加了经过处理的上下文信息。
    • 减少参数冗余,提高计算效率。
  • 应用:在YOLOv7等目标检测模型中,SPPCSPC模块用于捕获多尺度特征,提升模型对目标尺寸变化的适应能力。

6.5、ASPP(Atrous Spatial Pyramid Pooling)

  • 提出:受到SPP的启发,在语义分割模型DeepLabv2中提出。

  • 功能

    • 使用具有不同采样率的多个并行空洞卷积。
    • 为每个采样率提取的特征在单独的分支中进一步处理,并融合以生成最终的结果。
    • 通过不同的空洞率构建不同的感受野的卷积核,用来获取多尺度物体信息。
  • 应用:主要用于语义分割任务中,如DeepLab系列等。

6.6、总结

SPP、SPPF、SimSPPF、SPPCSPC及ASPP都是深度学习中重要的空间金字塔池化结构,它们具有各自的特点和应用场景。SPP是基础的空间金字塔池化结构,SPPF和SimSPPF是SPP的快速和简化版本,分别用于提高计算效率和简化设计。SPPCSPC结合了SPP和CSP两种设计思想,用于捕获多尺度特征并减少参数冗余。ASPP则主要用于语义分割任务中,通过不同的空洞率构建不同的感受野来获取多尺度物体信息。这些结构在图像处理和目标检测任务中发挥着重要作用,为深度学习模型提供了强大的特征提取和表示能力。

参考:

  1. 【YOLOv5/v7改进系列】改进池化层为SPP、SPPF、SPPCSPC
  2. SPP、SPPF 、 SimSPPF 、 ASPP、 SPPCSPC详解_sppf模块-优快云博客
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

浩瀚之水_csdn

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

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

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

打赏作者

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

抵扣说明:

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

余额充值