【Block总结】MKP,多尺度卷积核级联结构,增强感受野适应性|AAAI 2025

1 论文信息

FBRT-YOLO(Faster and Better for Real-Time Aerial Image Detection)是由北京理工大学团队提出的专用于航拍图像实时目标检测的创新框架,发表于AAAI 2025。论文针对航拍场景中小目标检测的核心难题展开研究,重点解决小目标因分辨率低背景干扰多导致的定位困难,以及现有方法在实时性精度间的失衡问题。

航拍图像目标检测是无人机、遥感监测等应用的关键技术,但面临独特挑战:图像中目标(如车辆、行人)通常仅由少量像素(<0.1%图像面积)构成,且易受云层、建筑群等复杂背景干扰。传统方法通过增加分辨率提升精度,但显著增加计算负担,难以满足嵌入式设备(如无人机芯片)的实时需求。FBRT-YOLO通过轻量化设计,在Visdrone、UAVDT和AI-TOD三大航拍数据集上实现了精度与速度的突破性平衡。

论文链接:

2 创新点

2.1 特征互补映射模块(FCM)

FCM模块致力于解决深层网络中小目标空间信息丢失这一根本问题。传统特征金字塔(如FPN)虽融合深浅层特征,但主干网络在传递过程中仍会弱化小目标的精确位置信息。FCM通过“拆分-变换-互补映射-聚合”四步策略实现信息融合:

  1. 通道分割:将输入特征按比例α拆分为两部分( X 1 ∈ R α C × H × W , X 2 ∈ R ( 1 − α ) C × H × W ) X¹∈R^{αC×H×W}, X²∈R^{(1-α)C×H×W}) X1RαC×H×W,X2R(1α)C×H×W,其中α随网络深度动态调整(深层α更低以保留更多空间信息)。
  2. 定向变换:X¹分支通过3×3卷积提取语义信息,X²分支通过逐点卷积提取空间位置信息
  3. 互补映射:通过通道交互(生成通道权重 W c W_c Wc)和空间交互(生成空间权重 W s W_s Ws)计算信息权重,强化关键特征。
  4. 特征聚合:按公式 Y = W c ⋅ X 1 + W s ⋅ X 2 Y = W_c·X¹ + W_s·X² Y=WcX1+WsX2融合信息,使深层特征同时保有语义和位置信息。

2.2 多内核感知单元(MKP)

针对航拍图像中目标尺度差异大的挑战,MKP取代了YOLO的最终下采样层,采用多尺度卷积核级联结构增强感受野适应性:

  • 并行使用3×3、5×5、7×7卷积核提取不同尺度特征
  • 通过逐点卷积(A)整合跨尺度信息,公式表达为: M K P ( X ) = A ( C o n v k = 3 ( X ) ⊕ C o n v k = 5 ( X ) ⊕ C o n v k = 7 ( X ) ) MKP(X) = A(Conv_{k=3}(X) ⊕ Conv_{k=5}(X) ⊕ Conv_{k=7}(X)) MKP(X)=A(Convk=3(X)Convk=5(X)Convk=7(X))
    该设计避免单一卷积核的局限性:小卷积核感受野不足,大卷积核引入过多背景噪声。

2.3 冗余驱动的轻量化设计

传统检测器在高分辨率图像处理中存在结构冗余。FBRT-YOLO通过两项精简策略优化效率:

  1. 下采样层重构:用分组卷积替代标准卷积执行空间下采样,后续接逐点卷积扩展通道,参数量降至标准卷积的1/4(公式对比: P a r a m s s t d = k 2 C i n C o u t , P a r a m s o p t = k 2 C i n G + C i n C o u t Params_{std}=k²C_inC_out, Params_{opt}=k²C_inG + C_inC_out Paramsstd=k2CinCout,Paramsopt=k2CinG+CinCout,G为分组数)。
  2. 检测头简化:结合MKP单元移除冗余检测头,减少输出层计算量。

3 方法

3.1 整体架构

FBRT-YOLO以YOLOv8为基线,主干网络嵌入FCM模块替代原C2f单元,并在最后一层用MKP单元替换下采样操作。整体架构分为三阶段:

  1. 特征提取:输入图像经多层卷积,每阶段输出接入FCM模块融合空间-语义信息。
  2. 多尺度感知:MKP单元在最终阶段捕获大范围上下文,输出多尺度特征图。
  3. 检测头:精简后的头部输出预测框(类别、置信度、坐标)。

3.2 MKP单元优化

  • 卷积核组合实验表明3/5/7为最佳尺寸(过小则感受野不足,过大引入噪声)
  • 不同尺度间加入批归一化LeakyReLU,避免梯度消失。

3.3 MKP设计优势

  1. 计算高效:深度可分离卷积大幅减少计算量
  2. 多尺度特征融合:不同尺寸的卷积核捕获不同范围的特征
  3. 残差学习:避免信息丢失,促进梯度流动
  4. 通道交互:1×1卷积促进通道间的信息交换
  5. 尺寸不变:适合嵌入各种网络架构

【Block总结】MKP,多尺度卷积核级联结构,增强感受野适应性|AAAI 2025_第1张图片

4 效果

4.1 性能对比实验

在三大航拍数据集上的测试表明,FBRT-YOLO全面超越现有实时检测器:

  • Visdrone数据集:FBRT-YOLO-S模型AP达30.1%,较YOLOv8-S提升2.3%,参数量减少74%。
  • UAVDT数据集:AP为18.4%,超过GLSAN(17.1%)和CEASC(17.6%)。
  • AI-TOD数据集(小目标为主):AP50提升2.2%,GFLOPs降低20%。

表2:Visdrone数据集上模型性能对比

模型 AP(%) 参数量(M) GFLOPs 推理速度(FPS)
YOLOv8-S 27.8 11.1 28.6 142
FBRT-YOLO-S 30.1 2.9 22.8 189
RT-DETR-R34 28.9 19.2 98.3 156
FBRT-YOLO-M 30.2 18.7 76.5 173

4.2 消融实验

以YOLOv8-S为基线,逐步引入改进组件:

  1. 冗余优化:参数减少18%,计算负载降11%,精度略降0.2%(AP)。
  2. 添加FCM:AP50提升1.4%,因特征增强补偿了精度损失。
  3. 替换MKP:AP提升1.6%,训练收敛速度加快30%。

可视化热图显示,FBRT-YOLO对密集小目标的响应强度显著高于基线模型,尤其在车辆群、行人小目标等场景中关注区域更精确。

4.3 效率优势

  • 边缘部署潜力:FBRT-YOLO-N仅2.9M参数,在嵌入式GPU上达189 FPS,较YOLOv8-N加速45%。
  • 计算负载优化:MKP单元通过多核并行计算,单帧处理延迟降至5ms以下,满足无人机实时避障需求。
    【Block总结】MKP,多尺度卷积核级联结构,增强感受野适应性|AAAI 2025_第2张图片

5 总结

FBRT-YOLO通过特征互补映射模块(FCM)多内核感知单元(MKP) 的创新设计,解决了航拍图像检测中小目标信息丢失多尺度适应性不足的核心问题。其贡献主要体现在三方面:

  1. 理论层面:提出空间-语义信息互补映射机制,缓解深层网络位置信息衰减问题;
  2. 工程层面:轻量化设计(参数量最高降74%)满足嵌入式设备实时需求;
  3. 应用层面:在Visdrone等数据集上AP提升1.1-2.3%,为无人机安防、灾害监测提供高效解决方案。

代码

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

def autopad(k, p=None, d=1):  # kernel, padding, dilation
    """Pad to 'same' shape outputs."""
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p

class Conv(nn.Module):
    """Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""

    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        """Initialize Conv layer with given arguments including activation."""
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        """Apply convolution, batch normalization and activation to input tensor."""
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):
        """Perform transposed convolution of 2D data."""
        return self.act(self.conv(x))

class Pzconv(nn.Module):
            def __init__(self, dim):
                super().__init__()
                self.conv1 = nn.Conv2d(
                    dim, dim, 3,
                    1, 1, groups=dim
                )
                self.conv2 = Conv(dim, dim, k=1, s=1, )
                self.conv3 = nn.Conv2d(
                    dim, dim, 5,
                    1, 2, groups=dim
                )
                self.conv4 = Conv(dim, dim, 1, 1)
                self.conv5 = nn.Conv2d(
                    dim, dim, 7,
                    1, 3, groups=dim
                )

            def forward(self, x):
                x1 = self.conv1(x)
                x2 = self.conv2(x1)
                x3 = self.conv3(x2)
                x4 = self.conv4(x3)
                x5 = self.conv5(x4)
                x6 = x5 + x
                return x6



        # print(x.shape)
if __name__ == "__main__":
    # 定义输入张量大小(Batch、Channel、Height、Wight)
    B, C, H, W = 16, 64, 40, 40
    input_tensor = torch.randn(B,C,H,W)  # 随机生成输入张量
    dim=C
    # 创建 ARConv 实例
    block = Pzconv(dim=64)
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    sablock = block.to(device)
    print(sablock)
    input_tensor = input_tensor.to(device)
    # 执行前向传播
    output = sablock(input_tensor)
    # 打印输入和输出的形状
    print(f"Input: {input_tensor.shape}")
    print(f"Output: {output.shape}")

Pzconv模块代码详解

辅助函数和基础模块

def autopad(k, p=None, d=1):
    """自动计算padding大小以保持输出尺寸不变"""
    if d > 1:
        # 计算实际卷积核大小(考虑膨胀率)
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]
    if p is None:
        # 自动计算padding(卷积核大小的一半)
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
    return p

class Conv(nn.Module):
    """标准卷积模块(卷积+BN+激活)"""
    default_act = nn.SiLU()  # 默认激活函数为SiLU
    
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        super().__init__()
        # 创建卷积层(自动计算padding)
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        self.bn = nn.BatchNorm2d(c2)  # 批归一化
        # 设置激活函数(默认为SiLU)
        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):
        """直接应用卷积和激活函数(跳过批归一化)"""
        return self.act(self.conv(x))

Pzconv模块核心实现

class Pzconv(nn.Module):
    def __init__(self, dim):
        """
        初始化Pzconv模块
        :param dim: 输入和输出的通道数
        """
        super().__init__()
        
        # 3x3深度可分离卷积(保持尺寸不变)
        self.conv1 = nn.Conv2d(dim, dim, 3, 1, 1, groups=dim)
        
        # 1x1标准卷积(包含BN和激活)
        self.conv2 = Conv(dim, dim, k=1, s=1)
        
        # 5x5深度可分离卷积(保持尺寸不变)
        self.conv3 = nn.Conv2d(dim, dim, 5, 1, 2, groups=dim)
        
        # 1x1标准卷积(包含BN和激活)
        self.conv4 = Conv(dim, dim, k=1, s=1)
        
        # 7x7深度可分离卷积(保持尺寸不变)
        self.conv5 = nn.Conv2d(dim, dim, 7, 1, 3, groups=dim)
    
    def forward(self, x):
        """前向传播过程"""
        # 第一层:3x3深度可分离卷积
        x1 = self.conv1(x)
        
        # 第二层:1x1标准卷积(带BN和激活)
        x2 = self.conv2(x1)
        
        # 第三层:5x5深度可分离卷积
        x3 = self.conv3(x2)
        
        # 第四层:1x1标准卷积(带BN和激活)
        x4 = self.conv4(x3)
        
        # 第五层:7x7深度可分离卷积
        x5 = self.conv5(x4)
        
        # 残差连接:原始输入 + 最终输出
        x6 = x5 + x
        
        return x6

测试代码

if __name__ == "__main__":
    # 定义输入张量大小(Batch, Channel, Height, Width)
    B, C, H, W = 16, 64, 40, 40
    input_tensor = torch.randn(B, C, H, W)  # 随机生成输入张量
    
    # 创建Pzconv实例
    block = Pzconv(dim=C)
    
    # 检测并设置设备(GPU优先)
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    sablock = block.to(device)
    input_tensor = input_tensor.to(device)
    
    # 执行前向传播
    output = sablock(input_tensor)
    
    # 打印输入和输出的形状
    print(f"Input: {input_tensor.shape}")
    print(f"Output: {output.shape}")

关键设计解析

1. 多尺度特征提取

Pzconv模块结合了三种不同尺度的卷积核:

  • 3×3卷积:捕捉局部特征
  • 5×5卷积:捕捉中等范围特征
  • 7×7卷积:捕捉更大范围的上下文信息

2. 深度可分离卷积

模块中的conv1conv3conv5使用了深度可分离卷积:

  • groups=dim参数使卷积在通道维度上独立进行
  • 大大减少了计算量和参数量
  • 保持空间维度不变(padding设置得当)

3. 特征变换与非线性激活

模块中的conv2conv4是1×1标准卷积:

  • 包含批归一化(BN)和激活函数(SiLU)
  • 增加非线性表达能力
  • 进行通道间的信息交互

4. 残差连接

  • 最终输出x5与原始输入x相加
  • 缓解深层网络的梯度消失问题
  • 保留原始特征信息

5. 尺寸保持

所有卷积层都通过合理的padding设置保持了特征图的空间尺寸不变:

  • 3×3卷积:padding=1
  • 5×5卷积:padding=2
  • 7×7卷积:padding=3

你可能感兴趣的:(目标跟踪,人工智能,计算机视觉)