论文题目GST-Net: Global Spatio-Temporal Detection Network for Infrared Small Objects in Complex Ground Scenarios中文题目GST-Net复杂地面场景下红外小目标的全局时空检测框架应用任务红外小目标检测 (IRSTD)、视频目标检测、特征增强论文原文 (Paper)https://ieeexplore.ieee.org/abstract/document/11098927官方代码 (Code)https://github.com/elvintanhust/GST-Det摘要本文结合红外小目标检测 (IRSTD)领域的经典论文《GST-Net》中的设计思想针对复杂地面背景下目标微弱、易被噪声淹没的痛点提供了一个通用的即插即用模块——Res_CBAM_block。该模块将经典的CBAM (Convolutional Block Attention Module)嵌入到残差结构中通过**通道注意力关注“什么”和空间注意力关注“哪里”**的串联有效抑制背景杂波增强小目标的特征响应是构建高性能红外检测 Backbone 的基础组件。目录第一部分模块原理与实战分析1. 论文背景与解决的痛点2. 核心模块原理揭秘3. 架构图解4. 适用场景与魔改建议第二部分核心完整代码第三部分结果验证与总结第一部分模块原理与实战分析1. 论文背景与解决的痛点在红外小目标检测尤其是涉及视频序列的 GST-Net 任务中我们面临着极其恶劣的成像环境低信噪比 (Low SCR)目标通常只有几个像素大且亮度可能比背景还低。复杂背景干扰地面场景中包含树木、道路、建筑物等高频纹理这些纹理在卷积神经网络眼中很容易被误判为目标。特征淹没随着网络层数加深微小的目标特征很容易在下采样过程中丢失。痛点总结我们需要一种机制能够在特征提取的每一个阶段都显式地告诉网络“哪里是目标哪里是背景”防止目标信息流失。2. 核心模块原理揭秘虽然 GST-Net 论文中提出了复杂的 RMPE 和 GSTDEM 模块但其底层特征提取往往依赖于强大的注意力机制。这里提供的Res_CBAM_block是实现特征增强的“万金油”模块其核心逻辑如下双重注意力机制 (Dual Attention)通道注意力 (Channel Attention)利用全局平均池化和最大池化压缩空间维度学习每个通道的权重。它负责判断哪些特征通道包含目标信息例如抑制包含大面积背景噪声的通道。空间注意力 (Spatial Attention)在通道维度进行压缩学习空间上的权重图。它负责定位图像的哪个位置是目标高亮小目标区域。残差连接 (Residual Connection)直接将注意力增强后的特征与原始输入相加。这保证了梯度能够顺畅传播防止因为多层注意力导致的网络退化同时实现了“特征细化”的效果。fea_add_module (特征融合)一个简单但有效的逐元素加法模块通常用于融合不同层级或不同分支如时空双流的特征。3. 架构图解4. 适用场景与魔改建议这套代码非常适合用于以下场景的改进红外/遥感小目标检测替换 ResNet 中的 BasicBlock显著降低虚警率。U-Net 编码器增强在 U-Net 的下采样路径中加入 Res_CBAM保护小目标特征不被丢失。特征融合阶段在 FPN特征金字塔的横向连接处使用增强多尺度特征的表达能力。第二部分核心完整代码importtorchimporttorch.nnasnnclassChannelAttention(nn.Module):Channel Attention Module from CBAMdef__init__(self,in_planes,ratio16):super().__init__()self.avg_poolnn.AdaptiveAvgPool2d(1)self.max_poolnn.AdaptiveMaxPool2d(1)self.fc1nn.Conv2d(in_planes,in_planes//ratio,1,biasFalse)self.relu1nn.ReLU()self.fc2nn.Conv2d(in_planes//ratio,in_planes,1,biasFalse)self.sigmoidnn.Sigmoid()defforward(self,x):avg_outself.fc2(self.relu1(self.fc1(self.avg_pool(x))))max_outself.fc2(self.relu1(self.fc1(self.max_pool(x))))outavg_outmax_outreturnself.sigmoid(out)classSpatialAttention(nn.Module):Spatial Attention Module from CBAMdef__init__(self,kernel_size7):super().__init__()assertkernel_sizein(3,7),kernel size must be 3 or 7padding3ifkernel_size7else1self.conv1nn.Conv2d(2,1,kernel_size,paddingpadding,biasFalse)self.sigmoidnn.Sigmoid()defforward(self,x):avg_outtorch.mean(x,dim1,keepdimTrue)max_out,_torch.max(x,dim1,keepdimTrue)xtorch.cat([avg_out,max_out],dim1)xself.conv1(x)returnself.sigmoid(x)classRes_CBAM_block(nn.Module):Residual Block with CBAM (Convolutional Block Attention Module)def__init__(self,in_channels,out_channels,stride1):super().__init__()self.conv1nn.Conv2d(in_channels,out_channels,kernel_size3,stridestride,padding1)self.bn1nn.BatchNorm2d(out_channels)self.relunn.ReLU(inplaceTrue)self.conv2nn.Conv2d(out_channels,out_channels,kernel_size3,padding1)self.bn2nn.BatchNorm2d(out_channels)ifstride!1orout_channels!in_channels:self.shortcutnn.Sequential(nn.Conv2d(in_channels,out_channels,kernel_size1,stridestride),nn.BatchNorm2d(out_channels))else:self.shortcutNoneself.caChannelAttention(out_channels)self.saSpatialAttention()defforward(self,x):residualxifself.shortcutisnotNone:residualself.shortcut(x)outself.conv1(x)outself.bn1(out)outself.relu(out)outself.conv2(out)outself.bn2(out)outself.ca(out)*out outself.sa(out)*out outresidual outself.relu(out)returnoutclassfea_add_module(nn.Module):Feature Addition Module with Dual-stream Attention Fusiondef__init__(self,channels):super().__init__()self.ca1ChannelAttention(channels*2)self.ca2ChannelAttention(channels)self.saSpatialAttention()self.relunn.ReLU(inplaceTrue)self.shortcut1nn.Sequential(nn.Conv2d(channels*2,channels*2,kernel_size1,stride1),nn.BatchNorm2d(channels*2))self.shortcut2nn.Sequential(nn.Conv2d(channels,channels,kernel_size1,stride1),nn.BatchNorm2d(channels))self.center_layernn.Sequential(nn.Conv2d(2*channels,channels,kernel_size3,stride1,padding1),nn.BatchNorm2d(channels),nn.ReLU(inplaceTrue),nn.Conv2d(channels,channels,kernel_size3,padding1),nn.BatchNorm2d(channels))defforward(self,S,T):STtorch.cat((S,T),dim1)out1self.ca1(ST)*self.sa(ST)*ST res1self.shortcut1(ST)out1res1 out2self.center_layer(out1)res2self.shortcut2(out2)outself.ca2(out2)*self.sa(out2)*out2 outres2 outself.relu(out)returnoutif__name____main__:devicetorch.device(cudaiftorch.cuda.is_available()elsecpu)print(*60)print(Testing SPSA Modules)print(*60)# Test ChannelAttentionprint(\n1. Testing ChannelAttention)xtorch.randn(1,32,256,256).to(device)caChannelAttention(in_planes32).to(device)print(f Module:{ca.__class__.__name__})outputca(x)print(f 输入张量形状:{x.shape})print(f 输出张量形状:{output.shape})assertoutput.shape(1,32,1,1),ChannelAttention output shape mismatch!print( ✓ ChannelAttention test passed!)# Test SpatialAttentionprint(\n2. Testing SpatialAttention)xtorch.randn(1,32,256,256).to(device)saSpatialAttention(kernel_size7).to(device)print(f Module:{sa.__class__.__name__})outputsa(x)print(f 输入张量形状:{x.shape})print(f 输出张量形状:{output.shape})assertoutput.shape(1,1,256,256),SpatialAttention output shape mismatch!print( ✓ SpatialAttention test passed!)# Test Res_CBAM_blockprint(\n3. Testing Res_CBAM_block)xtorch.randn(1,32,256,256).to(device)res_cbamRes_CBAM_block(in_channels32,out_channels64,stride2).to(device)print(f Module:{res_cbam.__class__.__name__})outputres_cbam(x)print(f 输入张量形状:{x.shape})print(f 输出张量形状:{output.shape})assertoutput.shape(1,64,128,128),Res_CBAM_block output shape mismatch!print( ✓ Res_CBAM_block test passed!)# Test Res_CBAM_block with same channelsprint(\n4. Testing Res_CBAM_block (same channels))xtorch.randn(1,32,256,256).to(device)res_cbamRes_CBAM_block(in_channels32,out_channels32,stride1).to(device)print(f Module:{res_cbam.__class__.__name__})outputres_cbam(x)print(f 输入张量形状:{x.shape})print(f 输出张量形状:{output.shape})assertoutput.shape(1,32,256,256),Res_CBAM_block output shape mismatch!print( ✓ Res_CBAM_block test passed!)# Test fea_add_moduleprint(\n5. Testing fea_add_module)storch.randn(1,32,256,256).to(device)ttorch.randn(1,32,256,256).to(device)fea_addfea_add_module(channels32).to(device)print(f Module:{fea_add.__class__.__name__})outputfea_add(s,t)print(f 输入张量S形状:{s.shape})print(f 输入张量T形状:{t.shape})print(f 输出张量形状:{output.shape})assertoutput.shape(1,32,256,256),fea_add_module output shape mismatch!print( ✓ fea_add_module test passed!)print(\n*60)print(All tests passed successfully! ✓)print(*60)第三部分结果验证与总结总结在 GST-Net 等高性能红外检测框架中注意力机制是提升性能的基石。Res_CBAM_block虽然结构简单但它通过模拟人类视觉的“聚焦”过程有效地解决了小目标特征微弱的难题。无论你是做视频检测还是单帧检测加上这个模块大概率能看到 Loss 下降和 Recall 提升喜欢这篇硬核复现的话欢迎点赞收藏订阅专栏获取更多 CV/红外目标检测 顶会论文的即插即用代码