本文是发表于AAAI 2025的文章,介绍了一种新的红外小目标检测方法。代码开源:https://github.com/JN-Yang/PConv-SDloss-Data
近年来,基于卷积神经网络 (CNN) 的红外小目标检测方法取得了显著成果。然而,这些方法通常使用标准卷积,忽略了红外小目标像素分布的空间特征。为此,本文提出了一种新型的风车形卷积 (PConv) 模块,用于替换骨干网络底层的标准卷积。PConv 更好地与红外小目标的 Gaussian 空间分布对齐,提高了特征提取能力,显著扩展了感受野,并且仅引入了最小的参数增加。此外,尽管现有的损失函数结合了尺度损失和位置损失,但它们没有充分考虑到这些损失在不同目标尺度上的敏感性差异,从而限制了在暗弱小目标上的检测性能。为了克服这一缺陷,本文提出了一种基于尺度的动态 (SD) 损失,该损失根据目标大小动态调整尺度和位置损失的影响,从而提高了网络检测不同尺度目标的能力。本文构建了一个新的基准数据集 SIRST-UAVB,这是迄今为止最大的最具挑战性的真实场景单帧红外小目标检测数据集。本文贡献在三方面:
1.风车形卷积 (PConv)
2.基于尺度的动态损失 (SD Loss)
3.SIRST-UAVB 数据集
下面重点介绍前两方面
创新点1:风车形卷积 (PConv)
不对称填充: PConv 使用非对称填充来创建水平和垂直的卷积核。
X 1 ( h ′ , w ′ , c ′ ) = S i L U ( B N ( X P ( 1 , 0 , 0 , 3 ) ( h 1 , w 1 , c 1 ) ⊗ W 1 ( 1 , 3 , c ′ ) ) ) , X 2 ( h ′ , w ′ , c ′ ) = S i L U ( B N ( X P ( 0 , 3 , 0 , 1 ) ( h 1 , w 1 , c 1 ) ⊗ W 2 ( 3 , 1 , c ′ ) ) ) , X 3 ( h ′ , w ′ , c ′ ) = S i L U ( B N ( X P ( 0 , 1 , 3 , 0 ) ( h 1 , w 1 , c 1 ) ⊗ W 3 ( 1 , 3 , c ′ ) ) ) , X 4 ( h ′ , w ′ , c ′ ) = S i L U ( B N ( X P ( 3 , 0 , 1 , 0 ) ( h 1 , w 1 , c 1 ) ⊗ W 4 ( 3 , 1 , c ′ ) ) ) . \begin{gathered}{X_{1}}^{(h^{\prime},w^{\prime},c^{\prime})}=SiLU(BN(X_{P(1,0,0,3)}^{(h_{1},w_{1},c_{1})}\otimes W_{1}{}^{(1,3,c^{\prime})})),\\X_{2}^{(h^{\prime},w^{\prime},c^{\prime})}=SiLU(BN(X_{P(0,3,0,1)}^{(h_{1},w_{1},c_{1})}\otimes W_{2}^{(3,1,c^{\prime})})),\\X_{3}^{(h^{\prime},w^{\prime},c^{\prime})}=SiLU(BN(X_{P(0,1,3,0)}^{(h_{1},w_{1},c_{1})}\otimes W_{3}^{(1,3,c^{\prime})})),\\X_{4}^{(h^{\prime},w^{\prime},c^{\prime})}=SiLU(BN(X_{P(3,0,1,0)}^{(h_{1},w_{1},c_{1})}\otimes W_{4}^{(3,1,c^{\prime})})).\end{gathered} X1(h′,w′,c′)=SiLU(BN(XP(1,0,0,3)(h1,w1,c1)⊗W1(1,3,c′))),X2(h′,w′,c′)=SiLU(BN(XP(0,3,0,1)(h1,w1,c1)⊗W2(3,1,c′))),X3(h′,w′,c′)=SiLU(BN(XP(0,1,3,0)(h1,w1,c1)⊗W3(1,3,c′))),X4(h′,w′,c′)=SiLU(BN(XP(3,0,1,0)(h1,w1,c1)⊗W4(3,1,c′))).
例如,第一个卷积核 W 1 ( 1 , 3 , c ′ ) W_{1}^{(1,3,c^{\prime})} W1(1,3,c′)使用 1 × 3 1 \times 3 1×3的卷积核,用(1, 0, 0, 3) 的填充参数,表示在左、右、上、下方向上分别填充 1、0、0、3 个像素,为了后续四个卷积拼接,每一个的输出通道数为 c ′ = c 4 c^{\prime}=\frac{c}{4} c′=4c。得到的结果是: h ′ = h 1 s + 1 , w ′ = w 1 s + 1 , c ′ = c 2 4 h^{\prime}=\frac{h_1}{s}+1,\quad w^{\prime}=\frac{w_1}{s}+1,\quad c^{\prime}=\frac{c_2}{4} h′=sh1+1,w′=sw1+1,c′=4c2。
扩散式卷积核: 卷积核向外扩散,有效性向外减弱,类似于高斯分布,像风车的叶片,能够更好地捕捉红外小目标的边缘和细节信息。
感受野扩展: PConv 的感受野比标准卷积更大,能够更全面地提取目标的特征,并减少信息损失。
参数效率: PConv 通过使用分组卷积,在扩大感受野的同时,尽量减少了参数数量,从而提高了模型的效率。
代码实现如下:
import torch
import torch.nn as nn
def autopad(k, p=None, d=1): # kernel, padding, dilation
# 为了输出的尺寸保持一致,自动计算填充
if d > 1: # 如果扩张因子d大于1
# 计算实际的卷积核大小(考虑扩张)
k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]
if p is None: # 如果没有传入填充p
# 自动计算填充为卷积核大小的一半
p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
return p # 返回计算得到的填充值
class Conv(nn.Module):
# 定义标准的卷积层,包含输入通道数、输出通道数、卷积核大小、步幅、填充、分组数、扩张率、激活函数等参数
default_act = nn.SiLU() # 默认为SiLU激活函数
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
# 初始化卷积层,传入的参数包括输入输出通道、卷积核大小、步幅、填充、分组数、扩张因子以及激活函数
super().__init__()
# 2D卷积层
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
self.bn = nn.BatchNorm2d(c2) # BatchNorm层
# 激活函数设置,默认为SiLU,如果传入了nn.Module类型的激活函数则使用该激活函数,否则不使用激活函数(Identity)
self.act = self.default_act 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):
# 融合的前向传播:只进行卷积和激活函数处理(不做BatchNorm)
return self.act(self.conv(x))
class PConv(nn.Module):
# 带有不对称填充方法的风车形卷积(PConv)
def __init__(self, c1, c2, k, s):
super().__init__()
# self.k = k
# 定义4个不同方向的填充方式,每个方向的填充方式是(左,上,右,下)
p = [(k, 0, 1, 0), (0, k, 0, 1), (0, 1, k, 0), (1, 0, 0, k)]
# 创建4个方向的不对称填充
self.pad = [nn.ZeroPad2d(padding=(p[g])) for g in range(4)]
# 卷积层,处理水平方向的卷积
self.cw = Conv(c1, c2 // 4, (1, k), s=s, p=0)
# 卷积层,处理垂直方向的卷积
self.ch = Conv(c1, c2 // 4, (k, 1), s=s, p=0)
# 卷积层,用于拼接后处理输出
self.cat = Conv(c2, c2, 2, s=1, p=0)
def forward(self, x):
# 对输入进行4个方向的填充,分别进行卷积处理后,进行拼接
yw0 = self.cw(self.pad[0](x)) # 处理左上方向的填充
yw1 = self.cw(self.pad[1](x)) # 处理右下方向的填充
yh0 = self.ch(self.pad[2](x)) # 处理左下方向的填充
yh1 = self.ch(self.pad[3](x)) # 处理右上方向的填充
# 将四个方向的卷积结果拼接在一起,通道数加倍后,传入一个卷积层
# 沿着通道维度拼接并返回最终结果
return self.cat(torch.cat([yw0, yw1, yh0, yh1], dim=1))
创新点2:Scale-based Dynamic Loss
现有的损失函数,如 DIoU 和 CIoU,没有充分考虑到 IoU 损失在不同目标尺度上的敏感性差异。小目标的 IoU 损失更容易受到标签误差的影响,导致模型训练不稳定。SD Loss 通过动态调整损失函数的权重,能够有效地减少标签误差对模型训练的影响,并提高模型的鲁棒性。
SD Loss 的计算方法:
-
计算目标尺度: 计算原始图像与当前特征图之间的缩放比例,从而确定当前目标的真实尺度。
R O C = w o × h o w c × h c , R_{OC}=\frac{w_o\times h_o}{w_c\times h_c}, ROC=wc×hcwo×ho,
2.计算权重: 根据目标尺度计算尺度损失和位置损失的权重,对于边界框标签,权重 β B \beta_B βB 与目标框面积成反比;对于掩码标签,权重 β M β_M βM 与目标面积成正比
3.动态调整: 将计算得到的权重与原始损失函数相乘,从而动态调整损失函数的权重。
文章应用价值
该方法应用于红外小目标检测任务,如无人驾驶、军事侦察、环境监测等,特别是在低质量视频数据的处理和小目标检测中展现出巨大的潜力。
开放性讨论
-
旋风形卷积在处理复杂背景或大规模目标时是否会遇到性能瓶颈?
-
动态尺度损失(SD Loss)是否能够扩展到其他类型的目标检测任务,尤其是多模态目标检测中-