【Block总结】PKI 模块,无膨胀多尺度卷积,增强特征提取的能力|即插即用

news2025/3/3 14:07:16

论文信息

标题: Poly Kernel Inception Network for Remote Sensing Detection

作者: Xinhao Cai, Qiuxia Lai, Yuwei Wang, Wenguan Wang, Zeren Sun, Yazhou Yao

论文链接:https://arxiv.org/pdf/2403.06258

代码链接:https://github.com/NUST-Machine-Intelligence-Laboratory/PKINet
在这里插入图片描述

创新点

Poly Kernel Inception Network (PKINet) 的主要创新在于其设计的卷积结构,旨在解决遥感图像目标检测中的几个关键挑战:

  • 多尺度特征提取: PKINet采用无膨胀的多尺度卷积核,能够有效提取不同尺度的目标特征,避免了传统大核卷积带来的背景噪声问题。

  • 上下文锚定注意力机制: 引入了上下文锚定注意(CAA)模块,以捕获远程上下文信息,增强特征提取的能力。

  • 轻量化设计: 通过并行使用深度卷积和1×1卷积,PKINet在保持高性能的同时,显著降低了模型的复杂性和计算成本。

方法

PKINet的核心方法包括以下几个方面:

  1. 无膨胀多尺度卷积: 通过使用不同大小的卷积核,PKINet能够在不同的感受野中提取丰富的纹理特征,而不依赖于膨胀卷积。

  2. 上下文锚定注意力模块: CAA模块通过全局平均池化和一维卷积,捕获远程像素之间的关系,增强了中心特征的表达能力。

  3. 自适应特征融合: 通过通道维度的自适应融合,PKINet能够有效整合局部和全局上下文信息,从而提高目标检测的准确性。

在这里插入图片描述

无膨胀多尺度卷积PKI 模块详解

Poly Kernel Inception Network (PKINet) 中的 PKI Module 是其核心组成部分,旨在有效提取遥感图像中的多尺度特征。以下是对 PKI Module 的详细解读,包括其设计理念、结构、功能和实验结果。

设计理念

PKI 模块的设计旨在解决遥感图像目标检测中面临的挑战,尤其是目标尺度的巨大变化和复杂背景。与传统方法不同,PKI 模块采用无膨胀的多尺度卷积核,以避免引入背景噪声,同时有效捕获局部上下文信息。

结构

PKI 模块主要由以下几个部分组成:

  1. 小卷积核:

    • 使用小卷积核(如 3 × 3 3 \times 3 3×3)提取局部特征,能够有效捕捉细节信息。
  2. 深度可分离卷积:

    • 采用一系列并行的深度可分离卷积(Depth-wise Convolutions),以捕获不同尺度的上下文信息。这种设计不仅减少了计算复杂度,还提高了特征提取的效率。
  3. 多尺度特征提取:

    • PKI 模块通过组合不同大小的卷积核(如 3 × 3 3 \times 3 3×3, 5 × 5 5 \times 5 5×5, 7 × 7 7 \times 7 7×7 等),实现对多尺度特征的提取,增强了模型对不同尺寸目标的适应能力。

功能

PKI 模块的主要功能包括:

  • 多尺度特征提取: 通过不同大小的卷积核,PKI 模块能够有效提取不同尺度的目标特征,适应遥感图像中目标的多样性。

  • 上下文信息捕获: 通过深度可分离卷积,PKI 模块能够捕获局部上下文信息,增强特征的表达能力。

  • 避免背景噪声: 由于不使用膨胀卷积,PKI 模块能够避免过于稀疏的特征表示,从而提高检测精度。

PKI 模块是 PKINet 的核心组件,通过创新的多尺度卷积设计和深度可分离卷积结构,有效提升了遥感图像目标检测的性能。其在特征提取和上下文信息捕获方面的优势,使得 PKINet 在多个基准数据集上取得了优异的表现,展示了其在实际应用中的潜力。

效果

在多个遥感目标检测基准数据集上进行的实验表明,PKINet在性能上优于传统方法,尤其是在处理目标尺度变化和复杂背景时表现突出。具体来说,PKINet在以下数据集上取得了显著的检测效果:

  • DOTA-v1.0
  • DOTA-v1.5
  • HRSC2016
  • DIOR-R

这些实验结果表明,PKINet不仅提高了检测精度,还在处理速度上也有良好的表现。

实验结果

实验中,PKINet在多个标准数据集上进行了广泛的评估,结果显示:

  • 检测精度: PKINet在各个数据集上均表现出色,尤其是在小目标和复杂背景下的检测能力显著提升。

  • 模型效率: 由于其轻量化设计,PKINet在计算资源的使用上更为高效,适合实际应用场景。

  • 对比分析: 与传统的目标检测模型相比,PKINet在多个指标上均有明显的优势,尤其是在处理多样化的上下文环境时。

总结

Poly Kernel Inception Network (PKINet) 通过创新的卷积结构和上下文注意力机制,成功应对了遥感图像目标检测中的多种挑战。其在特征提取和上下文信息捕获方面的优势,使得PKINet在多个基准数据集上取得了优异的性能,展示了其在实际应用中的潜力。未来的研究可以进一步探索PKINet在其他计算机视觉任务中的应用,以及如何进一步优化其结构以提升性能。

代码

import torch
import torch.nn as nn
from mmcv.cnn import ConvModule
from mmengine.model import BaseModule
from typing import Optional, Union, Sequence
import math
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
def make_divisible(x, divisor):
    # Returns nearest x divisible by divisor
    if isinstance(divisor, torch.Tensor):
        divisor = int(divisor.max())  # to int
    return math.ceil(x / divisor) * divisor
class GSiLU(BaseModule):
    """Global Sigmoid-Gated Linear Unit, reproduced from paper <SIMPLE CNN FOR VISION>"""
    def __init__(self):
        super().__init__()
        self.adpool = nn.AdaptiveAvgPool2d(1)

    def forward(self, x):
        return x * torch.sigmoid(self.adpool(x))


class CAA(BaseModule):
    """Context Anchor Attention"""
    def __init__(
            self,
            channels: int,
            h_kernel_size: int = 11,
            v_kernel_size: int = 11,
            norm_cfg: Optional[dict] = dict(type='BN', momentum=0.03, eps=0.001),
            act_cfg: Optional[dict] = dict(type='SiLU'),
            init_cfg: Optional[dict] = None,
    ):
        super().__init__(init_cfg)
        self.avg_pool = nn.AvgPool2d(7, 1, 3)
        self.conv1 = ConvModule(channels, channels, 1, 1, 0,
                                norm_cfg=norm_cfg, act_cfg=act_cfg)
        self.h_conv = ConvModule(channels, channels, (1, h_kernel_size), 1,
                                 (0, h_kernel_size // 2), groups=channels,
                                 norm_cfg=None, act_cfg=None)
        self.v_conv = ConvModule(channels, channels, (v_kernel_size, 1), 1,
                                 (v_kernel_size // 2, 0), groups=channels,
                                 norm_cfg=None, act_cfg=None)
        self.conv2 = ConvModule(channels, channels, 1, 1, 0,
                                norm_cfg=norm_cfg, act_cfg=act_cfg)
        self.act = nn.Sigmoid()

    def forward(self, x):
        attn_factor = self.act(self.conv2(self.v_conv(self.h_conv(self.conv1(self.avg_pool(x))))))
        return x*attn_factor

class InceptionBottleneck(BaseModule):
    """Bottleneck with Inception module"""
    def __init__(
            self,
            in_channels: int,
            out_channels: Optional[int] = None,
            kernel_sizes: Sequence[int] = (3, 5, 7, 9, 11),
            dilations: Sequence[int] = (1, 1, 1, 1, 1),
            expansion: float = 1.0,
            add_identity: bool = True,
            with_caa: bool = True,
            caa_kernel_size: int = 11,
            norm_cfg: Optional[dict] = dict(type='BN', momentum=0.03, eps=0.001),
            act_cfg: Optional[dict] = dict(type='SiLU'),
            init_cfg: Optional[dict] = None,
    ):
        super().__init__(init_cfg)
        out_channels = out_channels or in_channels
        hidden_channels = make_divisible(int(out_channels * expansion), 8)

        self.pre_conv = ConvModule(in_channels, hidden_channels, 1, 1, 0, 1,
                                   norm_cfg=norm_cfg, act_cfg=act_cfg)

        self.dw_conv = ConvModule(hidden_channels, hidden_channels, kernel_sizes[0], 1,
                                  autopad(kernel_sizes[0], None, dilations[0]), dilations[0],
                                  groups=hidden_channels, norm_cfg=None, act_cfg=None)
        self.dw_conv1 = ConvModule(hidden_channels, hidden_channels, kernel_sizes[1], 1,
                                   autopad(kernel_sizes[1], None, dilations[1]), dilations[1],
                                   groups=hidden_channels, norm_cfg=None, act_cfg=None)
        self.dw_conv2 = ConvModule(hidden_channels, hidden_channels, kernel_sizes[2], 1,
                                   autopad(kernel_sizes[2], None, dilations[2]), dilations[2],
                                   groups=hidden_channels, norm_cfg=None, act_cfg=None)
        self.dw_conv3 = ConvModule(hidden_channels, hidden_channels, kernel_sizes[3], 1,
                                   autopad(kernel_sizes[3], None, dilations[3]), dilations[3],
                                   groups=hidden_channels, norm_cfg=None, act_cfg=None)
        self.dw_conv4 = ConvModule(hidden_channels, hidden_channels, kernel_sizes[4], 1,
                                   autopad(kernel_sizes[4], None, dilations[4]), dilations[4],
                                   groups=hidden_channels, norm_cfg=None, act_cfg=None)
        self.pw_conv = ConvModule(hidden_channels, hidden_channels, 1, 1, 0, 1,
                                  norm_cfg=norm_cfg, act_cfg=act_cfg)

        if with_caa:
            self.caa_factor = CAA(hidden_channels, caa_kernel_size, caa_kernel_size, None, None)
        else:
            self.caa_factor = None

        self.add_identity = add_identity and in_channels == out_channels

        self.post_conv = ConvModule(hidden_channels, out_channels, 1, 1, 0, 1,
                                    norm_cfg=norm_cfg, act_cfg=act_cfg)

    def forward(self, x):
        x = self.pre_conv(x)

        y = x  # if there is an inplace operation of x, use y = x.clone() instead of y = x
        x = self.dw_conv(x)
        x = x + self.dw_conv1(x) + self.dw_conv2(x) + self.dw_conv3(x) + self.dw_conv4(x)
        x = self.pw_conv(x)
        if self.caa_factor is not None:
            y = self.caa_factor(y)
        if self.add_identity:
            y = x * y
            x = x + y
        else:
            x = x * y

        x = self.post_conv(x)
        return x

if __name__ == "__main__":
    # 如果GPU可用,将模块移动到 GPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    # 输入张量 (batch_size, height, width,channels)
    x = torch.randn(1,32,40,40).to(device)
    # 初始化 HWD 模块
    dim=32
    block = InceptionBottleneck(32)
    print(block)
    block = block.to(device)
    # 前向传播
    output = block(x)
    print("输入:", x.shape)
    print("输出:", output.shape)

输出结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2289127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Blazor-@bind

数据绑定 带有 value属性的标记都可以使用bind 绑定&#xff0c;<div>、<span>等非输入标记&#xff0c;无法使用bind 指令的&#xff0c;默认绑定了 onchange 事件&#xff0c;onchange 事件是指在输入框中输入内容之后&#xff0c;当失去焦点时执行。 page &qu…

架构技能(六):软件设计(下)

我们知道&#xff0c;软件设计包括软件的整体架构设计和模块的详细设计。 在上一篇文章&#xff08;见 《架构技能&#xff08;五&#xff09;&#xff1a;软件设计&#xff08;上&#xff09;》&#xff09;谈了软件的整体架构设计&#xff0c;今天聊一下模块的详细设计。 模…

C++并发编程指南07

文章目录 [TOC]5.1 内存模型5.1.1 对象和内存位置图5.1 分解一个 struct&#xff0c;展示不同对象的内存位置 5.1.2 对象、内存位置和并发5.1.3 修改顺序示例代码 5.2 原子操作和原子类型5.2.1 标准原子类型标准库中的原子类型特殊的原子类型备选名称内存顺序参数 5.2.2 std::a…

MySQL 容器已经停止(但仍然存在),但希望重新启动它,并使它的 3306 端口映射到宿主机的 3306 端口是不可行的

重新启动容器并映射端口是不行的 由于你已经有一个名为 mysql-container 的 MySQL 容器&#xff0c;你可以使用 docker start 启动它。想要让3306 端口映射到宿主机是不行的&#xff0c;实际上&#xff0c;端口映射是在容器启动时指定的。你无法在容器已经创建的情况下直接修改…

春晚舞台上的人形机器人:科技与文化的奇妙融合

文章目录 人形机器人Unitree H1的“硬核”实力传统文化与现代科技的创新融合网友热议与文化共鸣未来展望&#xff1a;科技与文化的更多可能结语 2025 年央视春晚的舞台&#xff0c;无疑是全球华人目光聚焦的焦点。就在这个盛大的舞台上&#xff0c;一场名为《秧BOT》的创意融合…

将pandas.core.series.Series类型的小数转化成百分数

大年初二&#xff0c;大家过年好&#xff0c;蛇年行大运&#xff01; 今天在编写一个代码的时候&#xff0c;使用 import pandas as pd产生了pandas.core.series.Series类型的数据&#xff0c;里面有小数&#xff0c;样式如下&#xff1a; 目的&#xff1a;将这些小数转化为百…

详细解释java当中的所有知识点(前言及数据类型及变量)(第一部分)

会将java当中的所有的知识点以及相关的题目进行分享&#xff0c;这是其中的第一部分&#xff0c;用红色字体标注出重点&#xff0c;以及加粗的方式进行提醒 目录 一、Java语言概述 1.Java语言简介 2.语言优势 二、main方法 1.Java程序结构组成 2.运行Java程序 3.注释 4.…

字节iOS面试经验分享:HTTP与网络编程

字节iOS面试经验分享&#xff1a;HTTP与网络编程 &#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 目录 字节iOS面试经验分享&#xff1a;HTT…

代码随想录_栈与队列

栈与队列 232.用栈实现队列 232. 用栈实现队列 使用栈实现队列的下列操作&#xff1a; push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。 思路: 定义两个栈: 入队栈, 出队栈, 控制出入…

【Oracle篇】使用Hint对优化器的执行计划进行干预(含单表、多表、查询块、声明四大类Hint干预)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;从事IT领域✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对SQLserver、NoSQL(…

论文阅读(九):通过概率图模型建立连锁不平衡模型和进行关联研究:最新进展访问之旅

1.论文链接&#xff1a;Modeling Linkage Disequilibrium and Performing Association Studies through Probabilistic Graphical Models: a Visiting Tour of Recent Advances 摘要&#xff1a; 本章对概率图模型&#xff08;PGMs&#xff09;的最新进展进行了深入的回顾&…

【Matlab高端绘图SCI绘图模板】第006期 对比绘柱状图 (只需替换数据)

1. 简介 柱状图作为科研论文中常用的实验结果对比图&#xff0c;本文采用了3组实验对比的效果展示图&#xff0c;代码已调试好&#xff0c;只需替换数据即可生成相关柱状图&#xff0c;为科研加分。通过获得Nature配色的柱状图&#xff0c;让你的论文看起来档次更高&#xff0…

YOLOv8源码修改(4)- 实现YOLOv8模型剪枝(任意YOLO模型的简单剪枝)

目录 前言 1. 需修改的源码文件 1.1添加C2f_v2模块 1.2 修改模型读取方式 1.3 增加 L1 正则约束化训练 1.4 在tensorboard上增加BN层权重和偏置参数分布的可视化 1.5 增加剪枝处理文件 2. 工程目录结构 3. 源码文件修改 3.1 添加C2f_v2模块和模型读取 3.2 添加L1正则…

后端token校验流程

获取用户信息 前端中只有 await userStore.getInfo() 表示从后端获取数据 在页面中找到info对应的url地址&#xff0c;在IDEA中查找 这里是getInfo函数的声明&#xff0c;我们要找到这个函数的使用&#xff0c;所以点getInfo() Override public JSONObject getInfo() {JSO…

Ansible自动化运维实战--通过role远程部署nginx并配置(8/8)

文章目录 1、准备工作2、创建角色结构3、编写任务4、准备配置文件&#xff08;金甲模板&#xff09;5、编写变量6、编写处理程序7、编写剧本8、执行剧本Playbook9、验证-游览器访问每台主机的nginx页面 在 Ansible 中&#xff0c;使用角色&#xff08;Role&#xff09;来远程部…

C语言自定义数据类型详解(二)——结构体类型(下)

书接上回&#xff0c;前面我们已经给大家介绍了如何去声明和创建一个结构体&#xff0c;如何初始化结构体变量等这些关于结构体的基础知识。下面我们将继续给大家介绍和结构体有关的知识&#xff1a; 今天的主题是&#xff1a;结构体大小的计算并简单了解一下位段的相关知识。…

Maven的单元测试

1. 单元测试的基本概念 单元测试&#xff08;Unit Testing&#xff09; 是一种软件测试方法&#xff0c;专注于测试程序中的最小可测试单元——通常是单个类或方法。通过单元测试&#xff0c;可以确保每个模块按预期工作&#xff0c;从而提高代码的质量和可靠性。 2.安装和配…

Jetson Xavier NX 安装 CUDA 支持的 PyTorch 指南

本指南将帮助开发者完成在 Jetson Xavier NX 上安装 CUDA 支持的 PyTorch。 安装方法 在 Jetson 上安装 Pytorch 只有两种方法。 一种是直接安装他人已经编译好的 PyTorch 轮子&#xff1b;一种是自己从头开始开始构建 PyTorch 轮子并且安装。 使用轮子安装 可以从我的 Gi…

GWO优化GRNN回归预测matlab

灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;简称 GWO&#xff09;&#xff0c;是一种群智能优化算法&#xff0c;由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出。该算法的设计灵感源自灰狼群体的捕食行为&#xff0c;核心思想在于模拟灰狼社会的结构与行…

Unity 粒子特效在UI中使用裁剪效果

1.使用Sprite Mask 首先建立一个粒子特效在UI中显示 新建一个在场景下新建一个空物体&#xff0c;添加Sprite Mask组件&#xff0c;将其的Layer设置为UI相机渲染的UI层&#xff0c; 并将其添加到Canvas子物体中&#xff0c;调整好大小&#xff0c;并选择合适的Sprite&#xff…