VX: shixiaodayyds,备注【即插即用】,添加即插即用模块交流群。


模块出处

在这里插入图片描述

Paper:HS-FPN: High Frequency and Spatial Perception FPN for Tiny Object Detection

Code:https://github.com/ShiZican/HS-FPN

模块介绍

High Frequency Perception(HFP):通过高通滤波器生成高频响应。这些高频响应被用作空间和通道视角的掩码权重,以丰富和突出原始特征图中微小物体的特征。
在这里插入图片描述
HFP设计思路:高频生成→双路径注意力→特征融合。

  • 输入特征图先经过DCT 离散余弦变换转换到频率域,再通过高通滤波器(权重矩阵)屏蔽左上角低频区域(对应图像中均匀背景),保留高频区域(对应小目标的边缘、纹理等细节),最后通过逆 DCT 变换将高频信息转回空间域,得到高频响应图。
  • 将高频响应图作为空间掩码,与原始特征图逐像素相乘,强化小目标所在空间区域的特征,抑制背景干扰。对高频响应图做自适应池化(最大 + 平均),提取通道级统计信息,通过分组卷积生成通道权重,与原始特征图逐通道相乘,放大包含小目标信息的通道特征。
  • 空间路径与通道路径的输出特征相加,再经过 3×3 卷积和分组归一化,消除冗余信息并稳定特征分布,最终输出增强后的小目标特征图(维度与输入一致,确保可插入现有 FPN 结构)。

HS-FPN:在这里插入图片描述

模块提出的动机(Motivation)

特征金字塔网络(FPN)的引入显着提高了目标检测性能。然而,在检测微小物体方面仍然存在重大挑战,因为它们的特征只占特征图的一小部分。虽然 FPN 集成了多尺度特征,但它并没有直接增强或丰富微小物体的特征。此外,FPN缺乏空间感知能力。为了解决这些问题,提出HFP。

在这里插入图片描述

适用范围与模块效果

适用范围:最适合小目标检测相关任务,以及其他需要高频信息增强的场景。

缝合位置:放在需要特征增强的位置。

模块效果:HFP以及各组件消融,使用HFP明显涨点(第一行和第四行对比)
在这里插入图片描述
HFP前后的特征映射可视化:
在这里插入图片描述

在这里插入图片描述

模块代码及使用方式

模块代码(详细注释与特征流前向传播过程中的维度变化):

import torch
import torch.nn as nn
import torch_dct as DCT
import torch.nn.functional as F
from mmcv.cnn import ConvModule
from mmcv.runner import BaseModule

# ------------------------------------------------------------------#
# Spatial Path of HFP
# Only p1&p2 use dct to extract high_frequency response
# ------------------------------------------------------------------#
class DctSpatialInteraction(BaseModule):
    def __init__(self,
                 in_channels,
                 ratio,
                 isdct=True,  # 核心开关:True(P1/P2层,用DCT提高频);False(P3/P4层,用1×1卷积)
                 init_cfg=dict(type='Xavier', layer='Conv2d', distribution='uniform')):
        super().__init__(init_cfg)
        self.ratio = ratio  # 高通滤波比例,控制低频抑制范围(如(0.25,0.25)表示屏蔽左上角25%低频区域)
        self.isdct = isdct
        # 非DCT模式下,用1×1卷积生成空间注意力(适配高分辨率层,降低计算量)
        if not self.isdct:
            self.spatial1x1 = nn.Sequential(
                *[ConvModule(in_channels, 1, kernel_size=1, bias=False)]  # 输出1通道空间掩码
            )

    def forward(self, x):
        _, _, h0, w0 = x.size()  # x: 输入特征图 (batch, channels, height, width)
        # 非DCT模式:直接用1×1卷积生成空间掩码,通过sigmoid归一化权重
        if not self.isdct:
            return x * torch.sigmoid(self.spatial1x1(x))  # 特征×空间权重,增强目标区域

        # DCT模式:从频率域提取高频信息(核心逻辑)
        idct = DCT.dct_2d(x, norm='ortho')  # 1. 对输入特征做2D离散余弦变换,转换到频率域
        # 2. 生成高通滤波权重:左上角(低频区)设为0,其余(高频区)设为1
        weight = self._compute_weight(h0, w0, self.ratio).to(x.device)
        weight = weight.view(1, h0, w0).expand_as(idct)  # 适配特征图维度,批量应用权重
        dct = idct * weight  # 3. 滤波:屏蔽低频(背景),保留高频(小目标边缘/细节)
        dct_ = DCT.idct_2d(dct, norm='ortho')  # 4. 逆DCT变换,将频率域信息转回空间域,生成高频掩码
        return x * dct_  # 5. 特征×高频掩码,强化小目标空间特征

    def _compute_weight(self, h, w, ratio):
        # 计算低频屏蔽区域:高度前h0行、宽度前w0列设为0
        h0 = int(h * ratio[0])  # 低频高度范围(如h=32,ratio=0.25 → h0=8)
        w0 = int(w * ratio[1])  # 低频宽度范围
        weight = torch.ones((h, w), requires_grad=False)  # 初始全1权重
        weight[:h0, :w0] = 0  # 屏蔽低频区域
        return weight


# ------------------------------------------------------------------#
# Channel Path of HFP
# Only p1&p2 use dct to extract high_frequency response
# ------------------------------------------------------------------#
class DctChannelInteraction(BaseModule):
    def __init__(self,
                 in_channels,
                 patch,  # 池化补丁大小(如(8,8)),控制通道注意力的感受野
                 ratio,
                 isdct=True,  # 同空间路径,控制是否启用DCT高频提取
                 init_cfg=dict(type='Xavier', layer='Conv2d', distribution='uniform')):
        super().__init__(init_cfg)
        self.in_channels = in_channels
        self.h = patch[0]  # 补丁高度
        self.w = patch[1]  # 补丁宽度
        self.ratio = ratio
        self.isdct = isdct
        # 分组卷积(groups=32):降低计算量,增强通道特异性(适配多通道特征)
        self.channel1x1 = nn.Sequential(
            *[ConvModule(in_channels, in_channels, kernel_size=1, groups=32, bias=False)],
        )
        self.channel2x1 = nn.Sequential(
            *[ConvModule(in_channels, in_channels, kernel_size=1, groups=32, bias=False)],
        )
        self.relu = nn.ReLU()  # 激活函数,增强非线性表达

    def forward(self, x):
        n, c, h, w = x.size()  # n=batch_size, c=channels
        # 非DCT模式:用最大/平均池化提取通道统计信息,生成通道权重
        if not self.isdct:
            amaxp = F.adaptive_max_pool2d(x, output_size=(1, 1))  # 通道最大池化(突出显著特征)
            aavgp = F.adaptive_avg_pool2d(x, output_size=(1, 1))  # 通道平均池化(保留全局信息)
            # 融合池化结果,生成通道权重(相加而非拼接,避免通道维度膨胀)
            channel = self.channel1x1(self.relu(amaxp)) + self.channel1x1(self.relu(aavgp))
            return x * torch.sigmoid(self.channel2x1(channel))  # 特征×通道权重,放大目标通道

        # DCT模式:结合频率域与通道统计信息(核心逻辑)
        idct = DCT.dct_2d(x, norm='ortho')  # 1. 特征转频率域
        weight = self._compute_weight(h, w, self.ratio).to(x.device)
        weight = weight.view(1, h, w).expand_as(idct)
        dct = idct * weight  # 2. 高通滤波,保留高频
        dct_ = DCT.idct_2d(dct, norm='ortho')  # 3. 逆DCT转回空间域

        # 4. 池化提取高频区域的通道统计信息(聚焦小目标细节)
        amaxp = F.adaptive_max_pool2d(dct_, output_size=(self.h, self.w))  # 高频区域最大池化
        aavgp = F.adaptive_avg_pool2d(dct_, output_size=(self.h, self.w))  # 高频区域平均池化
        # 求和压缩空间维度,得到通道级统计量(n, c, 1, 1)
        amaxp = torch.sum(self.relu(amaxp), dim=[2, 3]).view(n, c, 1, 1)
        aavgp = torch.sum(self.relu(aavgp), dim=[2, 3]).view(n, c, 1, 1)

        # 5. 生成通道权重并应用
        channel = self.channel1x1(amaxp) + self.channel1x1(aavgp)  # 融合池化结果
        return x * torch.sigmoid(self.channel2x1(channel))  # 特征×通道权重,增强目标通道特征

    def _compute_weight(self, h, w, ratio):
        # 与空间路径一致,生成高通滤波权重(屏蔽低频,保留高频)
        h0 = int(h * ratio[0])
        w0 = int(w * ratio[1])
        weight = torch.ones((h, w), requires_grad=False)
        weight[:h0, :w0] = 0
        return weight

    # ------------------------------------------------------------------#


# High Frequency Perception Module HFP
# ------------------------------------------------------------------#
class HFP(BaseModule):
    def __init__(self,
                 in_channels,
                 ratio,  # 高通滤波比例(如(0.25,0.25),实验验证最优值)
                 patch=(8, 8),  # 通道路径池化补丁大小
                 isdct=True,  # 控制是否启用DCT高频提取
                 init_cfg=dict(type='Xavier', layer='Conv2d', distribution='uniform')):
        super().__init__(init_cfg)
        # 初始化双路径模块
        self.spatial = DctSpatialInteraction(in_channels, ratio=ratio, isdct=isdct)  # 空间路径
        self.channel = DctChannelInteraction(in_channels, patch=patch, ratio=ratio, isdct=isdct)  # 通道路径
        # 输出卷积层:融合双路径特征,调整通道一致性并抑制噪声
        self.out = nn.Sequential(
            *[ConvModule(in_channels, in_channels, kernel_size=3, padding=1),  # 3×3卷积增强局部关联
              nn.GroupNorm(32, in_channels)]  # 分组归一化,稳定训练(适配多通道)
        )

    def forward(self, x):
        spatial = self.spatial(x)  # 1. 空间路径输出:增强小目标空间区域
        channel = self.channel(x)  # 2. 通道路径输出:增强小目标特征通道
        return self.out(spatial + channel)  # 3. 双路径特征相加+卷积归一化,输出最终增强特征

if __name__ == '__main__':
    device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
    x = torch.randn(1, 64, 32, 32).to(device)
    hfp = HFP(64,2).to(device)
    y = hfp(x)

    print("微信公众号:十小大的底层视觉工坊")
    print("知乎、CSDN:十小大")
    print("输入特征维度:", x.shape)
    print("输出特征维度:", y.shape)

运行结果:

在这里插入图片描述


至此本文结束。

如果本文对你有所帮助,请点赞收藏,创作不易,感谢您的支持!

点击下方👇公众号区域,扫码关注,可免费领取一份200+即插即用模块资料

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐