FPN详述

article/2025/9/22 8:43:17

简介

为了使用更多的语义信息,目标检测模型一般在卷积神经网络最后一层的特征图上进行后续操作(随着不断地下采样,语义信息更丰富,空间信息更稀少),而这一层对应的下采样率一般是比较大的,如16或者32。这就造成原始图像上地小目标在特征图上有效信息较少,小物体检测性能急剧下降,这就是目标检测中的多尺度问题,这个问题很直观,小目标在原图中对应的像素本就不多,下采样后很难找到对应信息。

为了解决多尺度问题,关键在于如何获取多尺度的特征,从数据准备的角度出发有图像金字塔这一策略,它的想法就是将图像调整为多个尺度,不同尺度图像对应不同的特征,这个思路的缺点就是计算量非常之大。不过,它也为后来的一些方法提供了思考,要知道,卷积神经网络层层递进,尺度和语义信息不断变化的过程就是一个金字塔结构,如何能够有效融合不同层卷积生成的特征图,应该可以较好地改善多尺度检测问题,FPN(Feature Pyramid Network)就是以此为出发点诞生的工作,极大地推动了后来目标检测的发展。

  • 论文标题

    Feature Pyramid Networks for Object Detection

  • 论文地址

    http://arxiv.org/abs/1612.03144

  • 论文源码

    https://github.com/jwyang/fpn.pytorch(非官方)

网络结构

FPN的结构如下图所示,主要有自下而上、自上而下、横向连接和卷积融合四个操作流程,我们一个个来看。不过,在此之前先对下图做一些必要的说明,图中最左侧的一列表示输入图像经过多个stage的卷积层不断下采样修改特征图的过程,其中C1为最浅几层,空间尺度大语义信息极少,一般不做考虑。

在这里插入图片描述

首先,来看最左侧的自下而上的操作,这个流是一个普通的ResNet网络,用来提取语义信息,C1至C5代表网络的5个stage(即不同的卷积层),每个stage内部特征图尺寸不变,从C1到C5特征图尺寸递减。由这个卷积网络提取特征的过程,就是自下而上的过程。

接着,我们来看中间那个自上而下操作,首先,对最小的特征图进行1x1卷积降维通道得到P5,然后对P5依此进行上采样得到P4、P3和P2,这个步骤是为了保证P4、P3和P2与C4、C3和C2长宽相同,以方便后面的逐元素相加。需要注意的是,这里的上采样实际上是最近邻上采样(临近元素复制),而不是线性插值。

然后,就是所谓的横向连接(Lateral Connection),这个步骤的目的就是将上采样后的高语义特征与下采样之前对应大小的定位细节特征进行融合。不过,上采样的尺寸虽然和浅层特征图一样,但是通道数是不同的,因此为了相加,需要将C2、C3和C4通过1x1卷积调整和P2、P3和P4通道数目一致,均为256。继而逐元素相加得到真正的P2、P3和P4,这个过程就叫做横向连接。

最后就是卷积融合的过程,得到相加的P2、P3和P4之后,再通过3x3卷积对这三个特征图进行变换以消除上采样过程带来的重叠效应,生成最终的P2、P3和P4,它们与P5一同输出进行后续任务。

至此,FPN网络结构最核心的部分就讲完了,不过实际目标检测需要在特征图上进行RoI特征提取(通过anchor等),而FPN有四个特征图,因此选用哪个就是值得考虑的。FPPN的方案是,对于不同尺寸的RoI区域,使用不同的特征图,大尺寸RoI需要更加精细的语义信息,即使深层特征图也会有较多信息保留,如在P5上进行;而小尺寸RoI因为尺寸小,高语义信息很难定位,因此采样浅层特征图,如P2。

实验

在检测网络中,将neck换为FPN,获得了非常恐怖的效果提升,包括后来的anchor-free的发展,也与FPN的成功是分不开的。

在这里插入图片描述

代码实现

FPN实现起来不是很难,很多工具箱都做了封装,这里就给出一个比较使用的PyTorch实现版本。

import torch.nn as nn
import torch.nn.functional as Fclass Bottleneck(nn.Module):expansion = 4def __init__(self, in_planes, planes, stride=1, downsample=None):super(Bottleneck, self).__init__()self.bottleneck = nn.Sequential(nn.Conv2d(in_planes, planes, 1, bias=False),nn.BatchNorm2d(planes),nn.ReLU(inplace=True),nn.Conv2d(planes, planes, 3, stride, 1, bias=False),nn.BatchNorm2d(planes),nn.ReLU(inplace=True),nn.Conv2d(planes, self.expansion * planes, 1, bias=False),nn.BatchNorm2d(self.expansion * planes),)self.relu = nn.ReLU(inplace=True)self.downsample = downsampledef forward(self, x):identity = xout = self.bottleneck(x)if self.downsample is not None:identity = self.downsample(x)out += identityout = self.relu(out)return outclass FPN(nn.Module):def __init__(self, layers):super(FPN, self).__init__()self.inplanes = 64self.conv1 = nn.Conv2d(3, 64, 7, 2, 3, bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(3, 2, 1)self.layer1 = self._make_layer(64, layers[0])self.layer2 = self._make_layer(128, layers[1], 2)self.layer3 = self._make_layer(256, layers[2], 2)self.layer4 = self._make_layer(512, layers[3], 2)self.toplayer = nn.Conv2d(2048, 256, 1, 1, 0)self.smooth1 = nn.Conv2d(256, 256, 3, 1, 1)self.smooth2 = nn.Conv2d(256, 256, 3, 1, 1)self.smooth3 = nn.Conv2d(256, 256, 3, 1, 1)self.latlayer1 = nn.Conv2d(1024, 256, 1, 1, 0)self.latlayer2 = nn.Conv2d(512, 256, 1, 1, 0)self.latlayer3 = nn.Conv2d(256, 256, 1, 1, 0)def _make_layer(self, planes, blocks, stride=1):downsample = Noneif stride != 1 or self.inplanes != Bottleneck.expansion * planes:downsample = nn.Sequential(nn.Conv2d(self.inplanes, Bottleneck.expansion * planes, 1, stride, bias=False),nn.BatchNorm2d(Bottleneck.expansion * planes))layers = []layers.append(Bottleneck(self.inplanes, planes, stride, downsample))self.inplanes = planes * Bottleneck.expansionfor i in range(1, blocks):layers.append(Bottleneck(self.inplanes, planes))return nn.Sequential(*layers)def _upsample_add(self, x, y):_, _, H, W = y.shapereturn F.upsample(x, size=(H, W), mode='bilinear') + ydef forward(self, x):c1 = self.maxpool(self.relu(self.bn1(self.conv1(x))))c2 = self.layer1(c1)c3 = self.layer2(c2)c4 = self.layer3(c3)c5 = self.layer4(c4)p5 = self.toplayer(c5)p4 = self._upsample_add(p5, self.latlayer1(c4))p3 = self._upsample_add(p4, self.latlayer2(c3))p2 = self._upsample_add(p3, self.latlayer3(c2))p4 = self.smooth1(p4)p3 = self.smooth2(p3)p2 = self.smooth3(p2)return p2, p3, p4, p5if __name__ == '__main__':fpn = FPN([3, 4, 6, 3])print(fpn)

总结

FPN通过金字塔结构将深层语义信息回传补充浅层语义信息,从而获得了高分辨率、强语义的多层特征,在小目标检测、实例分割领域有着不俗的表现。本文涉及的代码都可以在我的Github找到,欢迎star或者fork。


http://chatgpt.dhexx.cn/article/231PK30F.shtml

相关文章

FPN与Unet的异同

来源:目标检测的FPN和Unet有差别吗? - 知乎 (zhihu.com) 作者:CW不要無聊的風格 链接:https://www.zhihu.com/question/351279839/answer/1598104355 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业…

FPN以及其他结构FPN——Bi-FPN重点(仅供自己学习使用)

FPN FPN特征金字塔结构。 由于目标检测中对小物体检测很困难,因为卷积过程中,大物体的像素点多,小物体的像素点少,随着卷积的深入,大物体的特征容易被保留,小物体的特征越往后越容易被忽略。所以产生了FPN结…

FPN(Feature Pyramid Networks)详解

图像金字塔结构 图a 图a是在传统的图像处理当中是比较常见的一个方法。针对我们要检测不同尺度的目标时,会将图片缩放成不同的尺度,然后将每个尺度的图片依次通过我们的算法进行预测。 优点是它创建的多尺度特征的所有层次都包含很强的语义特征&#xf…

FPN解读

前两篇博客中都说到了FPN这个神器,今天就花了点时间看了下这篇论文,喜欢这个很赞很干净的结构。 Motivation 凡是都要从motivation说起,哈哈哈。rcnn系列在单个scale的feature map做检测(b),尽管conv已经对scale有些鲁棒了&#…

目标检测之FPN网络详解

点击上方“小白学视觉”,选择加"星标"或“置顶” 重磅干货,第一时间送达特征图金字塔网络FPN(Feature Pyramid Networks)是2017年提出的一种网络,FPN主要解决的是物体检测中的多尺度问题,通过简单…

FPN网络

论文是CVPR2017年的文章,采用特征金字塔做目标检测,有许多亮点,特来分享。 论文链接:https://arxiv.org/abs/1612.03144 译文:https://blog.csdn.net/quincuntial/article/details/80152314 FPN解决了什么问题&…

各种FPN:PANet、ASFF、NAS-FPN、BiFPN、Recursive-FPN...

早期的物体检测算法,无论是一步式的,还是两步式的,通常都是在Backbone的最后一个stage(特征图分辨率相同的所有卷积层归类为一个stage)最后一层的特征图,直接外接检测头做物体检测。此种物体检测算法&#…

FPN网络详解

特征图金字塔网络FPN(Feature Pyramid Networks)是2017年提出的一种网络,FPN主要解决的是物体检测中的多尺度问题,通过简单的网络连接改变,在基本不增加原有模型计算量的情况下,大幅度提升了小物体检测的性…

FPN详解

论文题目:Feature Pyramid Networks for Object Detection 论文链接:论文链接 论文代码:Caffe版本代码链接 一、FPN初探 1. 图像金字塔 图1 图像金字塔 图2 高斯金字塔效果 如上图所示,这是一个图像金字塔,做CV的你…

卷积神经网络——FPN(Feature Pyramid Networks)介绍

FPN(Feature Pyramid Networks):特征金字塔网络,是用来提取不同尺度特征图的,提供给后面的网络执行预测任务。 为什么需要FPN呢?简要介绍一下,在目标检测的网络中,要识别不同大小的物体是该网络实现检测的基…

详解FPN网络

目录 导读 摘要 简介 相关工作 FPN算法 FPN应用于RPN FPN应用于Fast RCNN 对比实验 FPN对RPN网络的影响 FPN对Fast RCNN网络的影响 总结 参考文献 导读 《Feature Pyramid Networks for Object Detection》这篇文章主要是用来解决Faster RCNN物体检测算法在处理多尺…

深度学习中的FPN详解

深度学习入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删。 目录 一、FPN提出原因 二、FPN的参考思想 三、特征金字塔 四、FPN具体思路 一、FPN提出原因 卷积网络中,深层网…

CICD概念 k8s DevOps

概念 先看下docker官网给的相关文档 Continuous Integration (CI) and Continuous Delivery (CD) methodologies are key traits of a modern software development practice. Docker Enterprise Edition (Docker EE) can be a catalyst for this DevOps mindset, integrating …

Gitlab CICD配置runner

首先要安装gitlab-runner,安装过程略 1.进入Gitlab项目界面,点击侧边栏Settings->CD/CD→Runners Collapse→Specific runners,获得URL与token 2.登录装有gitlab-runner的电脑,命令行输入gitlab-runner register注册runner&am…

CICD与DevOps

CICD与DevOps 文章声明,本文选自网上关于CICD与DevOps的讲解综合,如有侵权,联系删除 什么是CI/CD 什么是持续集成(CI-Continuous integration) 持续集成是指多名开发者在开发不同功能代码的过程当中,可以频繁的将代码行合并到一…

【云原生-DevOps】企业级DevOps平台搭建及技术选型-CICD篇

又是开篇 上一篇文章我们大概分享了DevOps项目管理中怎么企业级搭建本篇文章主要介绍两个子系统【CICD、效能看板】 CICD系统 CI(Continuous Integration):指持续集成,它属于开发人员的自动化流程。持续集成是一种软件开发实践&…

CICD和K8S实战

部署流程 拉取镜像,用docker 部署harbor镜像仓库 harbor是一个docker私有镜像仓库。 1、创建项目 2、创建成员 3、为项目添加成员。 后续是jenkins往harbor上传镜像,所以还需要一台jenkins服务器。 向harbor上传镜像 业务服务器 用来最终测试cd的结果。…

CICD构建实验

CICD CICD是一个可以集部署、拉取、上传等于一体的架构环境,它支持一线进行部署,免去了人工一条条的进行部署环境的工作流程,大大降低了人力手工运维成本和出错率。 CICD的搭建需要至少三台服务器,他们分别监管着Harbor&#xff…

请问什么是 CICD

CI,Continuous Integration,持续集成。CD,Continuous Deployment,持续部署。CICD 一般合称,无需特意区分二者区别。从开发、测试到上线的过程中,借助于 CICD 进行一些自动化处理,保障项目质量。 CICD 与 git 集成在一起,可理解为服务器端的 git hooks: 当代码 push 到…