FCOS代码解读

摘要:
FCOS可能是去年这个时候发表的一篇文章。一旦它问世,它注定会引领一种新的潮流。单级网络逐渐成为学术界和工业界的新宠。总的来说,当FCOS问世时,我仍然感到惊讶。提出了回归目标的编码方法,提出了解决大帧偏差问题的中心性,以及使用FPN来消除模糊性。可以想象,这个FCOSHead类必须实现正向,即下面三个分支的橙色框架图,以及计算目标和损失的代码。

论文解读:https://zhuanlan.zhihu.com/p/63868458

源码解读:

一:https://zhuanlan.zhihu.com/p/112126473

入门mmdetection(柒)---FCOS源码解读

入门mmdetection(柒)---FCOS源码解读
yuancoder
CV爱好者/旅行爱好者/

前面六篇文章借助sq的经典之作(Faster R-CNN)熟悉了mmdetection整个的设计风格和训练流程,这篇笔记想分享一下FCOS在mmdetection中的源码实现。

FCOS大概是去年这个时候出来的文章,一出来就注定要引领新的潮流,单阶段网络逐渐成为学术界和工业界的新宠。但其实FCOS本质思想,一方面几年前Densebox就已经有类似的了,另一方面,无非是框的anchor变成了点的anchor,并不能说是真正的anchor-free,还是没有跳脱滑窗匹配的命运。整体而言,FCOS出来了还是很惊艳了我,对回归目标的编码方式、centerness的提出解决大框偏离问题以及利用FPN缓解歧义的场景(如人的手上拿了个网球)。来开始欣赏代码吧:

# FCOS类继承了单阶段检测器类SingleStageDetector
class FCOS(SingleStageDetector):
    def __init__(self,backbone,neck,bbox_head,
                 train_cfg=None,test_cfg=None,pretrained=None):
        super(FCOS, self).__init__(backbone, neck, bbox_head, train_cfg,
                                   test_cfg, pretrained)

FCOS类继承了单阶段检测器类,这个和之前Faster R-CNN继承了双阶段检测器一样,实现都在对应的父类里面,所以我们截取部分重要的单阶段的代码块来看。

class SingleStageDetector(BaseDetector):
    def __init__(self,backbone,neck=None,bbox_head=None,
                 train_cfg=None,test_cfg=None,pretrained=None):
        super(SingleStageDetector, self).__init__()
     # 这里下面的build和之前介绍的一样,从config读取对应的type,然后返回一个实例
        self.backbone = builder.build_backbone(backbone)
        if neck is not None:
            self.neck = builder.build_neck(neck)
     # 这里self.bbox_head就是一个FCOSHead的实例
        self.bbox_head = builder.build_head(bbox_head)
        self.train_cfg = train_cfg
        self.test_cfg = test_cfg
        self.init_weights(pretrained=pretrained)

所以初始化函数就是创建backbone,neck以及head的实例,其中和Faster R-CNN不一样的只有head使用的是FCOSHead。可以想象,这个FCOSHead类里面必然实现了一个前向,就是下图橘色框起来那个三个分支的图(分别是分类H * W *C, 回归 H * W* 4 以及 centerness H * W * 1),以及计算target和loss的代码。先继续看SingleStageDetector的实现:

# 训练的前向函数forward_train,在BaseDetector的成员函数forward()里会调用,
# 上一章讲过,forward()会在batch_processor调用,在训练流程控制里
# 传进来的参数都是data_loader的输出,这个以后有机会再看,总之能拿到数据集的图片和标签
def forward_train(self,img,img_metas,gt_bboxes,gt_labels,gt_bboxes_ignore=None):
    x = self.extract_feat(img) #通过backbone和FPN提取多尺度的特征
    outs = self.bbox_head(x) #即FCOSHead的实例调用成员函数forward
    loss_inputs = outs + (gt_bboxes, gt_labels, img_metas, self.train_cfg)
    losses = self.bbox_head.loss( # 计算loss
            *loss_inputs, gt_bboxes_ignore=gt_bboxes_ignore)
    return losses

前向的代码封装的非常清晰,那么重点就是在FCOSHead里面了,我们来看这个类。

FCOS代码解读第3张
#首先初始化fcos头部网络结构,其实就是上图框框里的部分,
#两个分支,分别都有4个卷积,上面分叉为分类和centerness,下面接回归(当然,也可以把centerness和回归接在一起)
def _init_layers(self):
        self.cls_convs = nn.ModuleList()
        self.reg_convs = nn.ModuleList()
        for i in range(self.stacked_convs):
            chn = self.in_channels if i == 0 else self.feat_channels
            #stacked_convs=4, 即接4个3*3的卷积,channel为256
            self.cls_convs.append(
                ConvModule(
                    chn,
                    self.feat_channels,
                    3,
                    stride=1,
                    padding=1,
                    conv_cfg=self.conv_cfg,
                    norm_cfg=self.norm_cfg,
                    bias=self.norm_cfg is None))
            self.reg_convs.append(
                ConvModule(
                    chn,
                    self.feat_channels,
                    3,
                    stride=1,
                    padding=1,
                    conv_cfg=self.conv_cfg,
                    norm_cfg=self.norm_cfg,
                    bias=self.norm_cfg is None))
     # 分类的channel数需要注意一下,因为后面用的focal loss,所以为类别数-1
     # 即对coco数据集就不是81而是80
        # 本质上来说focal_loss调用的是BCE,并不引入类间竞争
        self.fcos_cls = nn.Conv2d(
            self.feat_channels, self.cls_out_channels, 3, padding=1)
        # 回归,输出channel为4,也和faster RCNN不一样,anchorbox有多个,anchor点只有一个
        # 譬如假如有9种anchor box,那么Faster R-CNN这边应该是36,而fcos只有4,减少了计算量
        self.fcos_reg = nn.Conv2d(self.feat_channels, 4, 3, padding=1)
        # 预测centerness,channel为1
        # centerness预测了当前anchor点的中心程度,推理的时候可以给框打分
        # 不在中心的框乘了centerness之后得分就降低了,容易被NMS过滤掉
        self.fcos_centerness = nn.Conv2d(self.feat_channels, 1, 3, padding=1)

        self.scales = nn.ModuleList([Scale(1.0) for _ in self.strides])

# 初始化了网络结构和权重之后就可以前向了,来看forward函数
def forward(self, feats):
    # 传进来的feats就是通过backbone和FPN提取多尺度的特征(一般是一个长度为5的tuple)
    # 注意这边用map把FPN的多个level给拆解了,可以简单理解为并行计算了
    return multi_apply(self.forward_single, feats, 

免责声明:内容来源于网络,仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇中间证书mongodb启动下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

WebStorm好用的插件推荐

随着时间的推移,编写JavaScript代码很多有用的插件都集成了WebStorm中,在WebStorm中即使不装任何插件,都能很舒服的进行开发网页应用、Node应用。插件对于WebStorm并不是特别的重要,但是某些插件实在是比较好用,所以本篇文章就整理一下比较好用的插件。使用该插件,可以直接在WebStorm中内嵌一个翻译界面。...

ARM内核全解析,从ARM7,ARM9到Cortex-A7,A8,A9,A12,A15到Cortex-A53,A57

Cortex-A50是继Cortex-A15之后的又一重量级产品,将会直接影响到主流PC市场的占有率。ARM处理器架构发展●Cortex-A57、A53处理器Cortex-A53、Cortex-A57两款处理器属于Cortex-A50系列,首次采用64位ARMv8架构,意义重大,这也是ARM最近刚刚发布的两款产品。Cortex-A12架构图ARM表示Cort...

SIP 协议

SIP是会话层的信令控制协议。SIP是一种类似于HTTP的基于文本的协议。SIP可以缩短应用程序,特别是高级应用程序的开发时间。由于基于IP协议的SIP使用IP网络,固定网络运营商将逐渐意识到SIP技术对他们的深远意义。随着国际电信联盟SS7标准和ITUH 323视频协议组合标准的长期存在,SIP的工作独立于底层网络传输协议和媒体。SIP的四个基本功能是定位...

ubuntu 安装ncurses

ubuntu安装ncursesncurses是字符终端下屏幕控制的基本库。可能很多新开发的程序都不使用了,不过如果要编译一些老程序,还经常遇得到。...

remote Incorrect username or password ( access token)问题解决

解决办法:打开电脑的控制面板--˃用户账户--˃管理Windows凭据1.找到刚才操作的账号,更改账号密码,保存。...

XXL-Job路由策略

企业项目中的所有任务转移都通过XXL Job进行管理。路由策略与Nginx相似。事实上,XXL Job封装了Quartz。分片任务分片广播可以根据分片参数进行开发:所有作业一起执行!不再有集群。Job将重复轮训。一些更好的阻塞处理策略是:调度过于密集,执行者无法处理。策略包括:单机串行(默认)、放弃后续调度和覆盖先前调度。...