(IEEE 2024)即插即用特征增强模块FEM,涨点起飞

文摘   2024-11-27 17:20   北京  

论文介绍

题目:FFCA-YOLO for Small Object Detection in Remote Sensing Images

论文地址:https://ieeexplore.ieee.org/document/10423050

QQ深度学习交流群:719278780

扫描下方二维码,加入深度学习论文指南星球!

加入即可获得,模块缝合、制作、写作技巧,学会“结构”创新、“创新点”创新,从三区到顶会,小论文大论文,毕业一站式服务

创新点

  • FFCA-YOLO模型的设计:该研究提出了一种高效的小目标检测模型FFCA-YOLO,并针对有限计算资源进行了优化,适合未来的实时遥感应用。该模型相较于基准模型和一些当前最先进的模型,具备了较高的性能。

  • 轻量级、模块化设计:论文中提出了三个创新性的轻量级可插拔模块:特征增强模块(FEM)、特征融合模块(FFM)和空间上下文感知模块(SCAM)。这些模块分别提升了网络的局部区域感知、多尺度特征融合以及跨通道和空间的全局关联能力,从而增强了小目标的特征表达,并抑制了复杂背景的干扰。

  • 自建小目标数据集USOD:论文构建了一个新的小目标数据集USOD,具有99.9%以上的小目标比例,包含了低光照和阴影遮挡等复杂条件的场景,并设置了不同图像退化条件的测试集,作为遥感小目标检测的基准数据集。

方法

整体结构

       FFCA-YOLO模型在YOLOv5框架基础上,增加了三个轻量级模块:特征增强模块(FEM)用于丰富局部特征信息,特征融合模块(FFM)通过改进的多尺度融合策略加权整合特征,空间上下文感知模块(SCAM)用全局池化获取通道和空间的上下文信息,从而提升小目标和背景的区分能力。此外,模型的轻量化版本L-FFCA-YOLO通过部分卷积(PConv)减少了计算复杂度,适合在资源受限的环境中实现实时检测。

  • 骨干网络:FFCA-YOLO选择了YOLOv5作为基础框架,但与原始YOLOv5不同的是,它只使用了四个卷积下采样操作作为特征提取的骨干网络。骨干网络的结构经过优化,旨在减少计算复杂度的同时保持较好的特征提取能力。

  • 特征增强模块(FEM):为了提高对小目标的检测能力,FEM模块通过多分支空洞卷积结构增加了特征丰富性,扩展了网络的局部感知能力,提升了对小目标的语义信息表达。

  • 特征融合模块(FFM):FFM模块通过改进的多尺度特征融合策略,将不同尺度的特征进行加权重组,使网络能够更有效地捕捉多尺度信息。FFM还改进了双向特征金字塔网络(BiFPN),并提出了CRC通道重加权策略,以更高效地利用多尺度特征。

  • 空间上下文感知模块(SCAM):SCAM模块通过全局池化操作获取空间和通道的上下文信息,用于增强网络对全局信息的建模能力。该模块利用全局平均池化(GAP)和全局最大池化(GMP)指导通道选择,提升了小目标和背景之间的区分能力。

  • 轻量化版本L-FFCA-YOLO:为了进一步降低计算资源消耗,L-FFCA-YOLO在FFCA-YOLO的基础上使用部分卷积(PConv)重构了骨干网络和特征融合模块的部分结构,从而在保证精度的同时实现更快的速度和更小的参数规模。

即插即用模块作用

FEM 作为一个即插即用模块

  • 适用场景

    • 小目标检测任务,如遥感图像中的车辆、建筑等小物体检测。

    • 低分辨率或背景复杂的场景,例如低清晰度视频监控、航拍图像等。

    • 场景中小目标特征弱、易被背景干扰的情况。

  • 作用

    • 增强小目标特征:通过多分支空洞卷积结构捕捉丰富的局部特征,使得小目标的特征表达更明显。

    • 提升局部上下文信息感知:扩展感受野,帮助模型在识别小目标时考虑周围的上下文信息。

    • 抑制背景干扰:在复杂背景下提升模型区分目标与背景的能力,减少误检和漏检。

消融实验结果

  • 分析了特征增强模块(FEM)、特征融合模块(FFM)和空间上下文感知模块(SCAM)对模型性能的影响。

  • 消融实验结果表明,每个模块的加入都显著提高了各项评价指标,尤其是在小目标检测方面。具体来说,FEM增强了模型对复杂背景中小目标的区分能力,FFM改善了多尺度特征的融合效果,而SCAM通过全局上下文信息的建模进一步增强了小目标的特征表示。因此,这些模块的结合使FFCA-YOLO在小目标检测任务中具备更强的特征表达和背景抑制能力。

即插即用模块

import torch
import torch.nn as nn

#论文:FFCA-YOLO for Small Object Detection in Remote Sensing Images[TGRS]
#论文地址:https://ieeexplore.ieee.org/document/10423050

class FEM(nn.Module):
    def __init__(self, in_planes, out_planes, stride=1, scale=0.1, map_reduce=8):
        super(FEM, self).__init__()
        self.scale = scale
        self.out_channels = out_planes
        inter_planes = in_planes // map_reduce
        self.branch0 = nn.Sequential(
            BasicConv(in_planes, 2 * inter_planes, kernel_size=1, stride=stride),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=1, relu=False)
        )
        self.branch1 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1),
            BasicConv(inter_planes, (inter_planes // 2) * 3, kernel_size=(1, 3), stride=stride, padding=(0, 1)),
            BasicConv((inter_planes // 2) * 3, 2 * inter_planes, kernel_size=(3, 1), stride=stride, padding=(1, 0)),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=5, dilation=5, relu=False)
        )
        self.branch2 = nn.Sequential(
            BasicConv(in_planes, inter_planes, kernel_size=1, stride=1),
            BasicConv(inter_planes, (inter_planes // 2) * 3, kernel_size=(3, 1), stride=stride, padding=(1, 0)),
            BasicConv((inter_planes // 2) * 3, 2 * inter_planes, kernel_size=(1, 3), stride=stride, padding=(0, 1)),
            BasicConv(2 * inter_planes, 2 * inter_planes, kernel_size=3, stride=1, padding=5, dilation=5, relu=False)
        )

        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

class BasicConv(nn.Module):
    def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, dilation=1, groups=1, relu=True,
                 bn=True, bias=False)
:

        super(BasicConv, self).__init__()
        self.out_channels = out_planes
        self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding,
                              dilation=dilation, groups=groups, bias=bias)
        self.bn = nn.BatchNorm2d(out_planes, eps=1e-5, momentum=0.01, affine=True) if bn else 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


if __name__ == '__main__':

    input = torch.randn(1, 64, 128, 128)
    block = FEM(in_planes=64, out_planes=64)
    print(input.size())
    output = block(input)
    # 打印输出的形状    print(output.size())

便捷下载方式

浏览打开网址:https://github.com/ai-dawang/PlugNPlay-Modules

更多分析可见原文


ai缝合大王
聚焦AI前沿,分享相关技术、论文,研究生自救指南
 最新文章