【Detectron2】详解Detectron2中Mask RCNN的部分代码

2023-10-27

整体来说,Backbone、RPN和Fast RCNN是三个相对独立的模块。Backbone对每张图片产生5 level的特征,并送入RPN。

RPN对送入的特征,首先经过3x3卷积,随后用sibling 1x1卷积产生分类和bbox信息,分类是指该anchor是否包含Object,bbox信息为四维,包括(dx, dy, dw, dh)。初始anchor加上偏移量后用于判断正负或忽略样本,并确定归属的gt instance。然后从中采样256个anchor(正负样本各一半)用于计算损失。最后,通过cls_score排序和NMS筛选出1000个样本,送入Fast RCNN。

Fast RCNN对送入样本重新确定正负样本,并确定归属的gt instance。然后从中采样512个proposals(正负样本比为1:3),送入RoIAlign,根据proposal的w,h确定在哪一层(注意这里不包含P5采样得到的P6层),用对应层的比例缩放proposal,切出ROI。其中包括设置采样点(论文中采样点设4最好,设1效果差不多),双线性插值(根据落在的坐标方格进行插值,双线性就是线性插值两次,第一次先对x坐标插值,第二次对y坐标插值),maxpooling。

用ROI计算classificaiton和bbox regression:和gt计算 softmax cross entropy loss和smooth L1 loss。

需要注意的是,只有在测试时,会在Fast RCNN中使用NMS的选取最后的结果。


如果不选择用cfg初始化模型,则Mask RCNN的初始化代码如下:可以简单的分为三个部分:(1) backbone = FPN(), (2) proposal_generator = RPN(); (3) roi_heads=StandardROIHeads()。

model = GeneralizedRCNN(
    backbone=FPN(
        ResNet(
            BasicStem(3, 64, norm="FrozenBN"),
            ResNet.make_default_stages(50, stride_in_1x1=True, norm="FrozenBN"),
            out_features=["res2", "res3", "res4", "res5"],
        ).freeze(2),
        ["res2", "res3", "res4", "res5"],
        256,
        top_block=LastLevelMaxPool(),
    ),
    proposal_generator=RPN(
        in_features=["p2", "p3", "p4", "p5", "p6"],
        head=StandardRPNHead(in_channels=256, num_anchors=3),
        anchor_generator=DefaultAnchorGenerator(
            sizes=[[32], [64], [128], [256], [512]],
            aspect_ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64],
            offset=0.0,
        ),
        anchor_matcher=Matcher([0.3, 0.7], [0, -1, 1], allow_low_quality_matches=True),
        box2box_transform=Box2BoxTransform([1.0, 1.0, 1.0, 1.0]),
        batch_size_per_image=256,
        positive_fraction=0.5,
        pre_nms_topk=(2000, 1000),
        post_nms_topk=(1000, 1000),
        nms_thresh=0.7,
    ),
    roi_heads=StandardROIHeads(
        num_classes=80,
        batch_size_per_image=512,
        positive_fraction=0.25,
        proposal_matcher=Matcher([0.5], [0, 1], allow_low_quality_matches=False),
        box_in_features=["p2", "p3", "p4", "p5"],
        box_pooler=ROIPooler(7, (1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), 0, "ROIAlignV2"),
        box_head=FastRCNNConvFCHead(
            ShapeSpec(channels=256, height=7, width=7), conv_dims=[], fc_dims=[1024, 1024]
        ),
        box_predictor=FastRCNNOutputLayers(
            ShapeSpec(channels=1024),
            test_score_thresh=0.05,
            box2box_transform=Box2BoxTransform((10, 10, 5, 5)),
            num_classes=80,
        ),
        mask_in_features=["p2", "p3", "p4", "p5"],
        mask_pooler=ROIPooler(14, (1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), 0, "ROIAlignV2"),
        mask_head=MaskRCNNConvUpsampleHead(
            ShapeSpec(channels=256, width=14, height=14),
            num_classes=80,
            conv_dims=[256, 256, 256, 256, 256],
        ),
    ),
    pixel_mean=[103.530, 116.280, 123.675],
    pixel_std=[1.0, 1.0, 1.0],
    input_format="BGR",
)

以下涉及的符号表示:

  • N: number of images in the minibatch
  • L: number of feature maps per image on which RPN is run
  • A: number of cell anchors (must be the same for all feature maps),指feature map上的每个点产生3种aspect_ratios的anchors
  • Hi, Wi: height and width of the i-th feature map
  • B: size of the box parameterization,指bbox的参数量4

1. Backbone

backbone使用ResNet-FPN,产生["p2", "p3", "p4", "p5", "p6"],共5层特征,每层特征的维度为:[N, C, Hi, Wi]。输出为一个dict,dict的keys是in_features的五个元素。

2. RPN

用于初筛anchors,并产生Fast RCNN中使用的proposals。

 proposal_generator=RPN(
        in_features=["p2", "p3", "p4", "p5", "p6"],
        head=StandardRPNHead(in_channels=256, num_anchors=3),
        anchor_generator=DefaultAnchorGenerator(
            sizes=[[32], [64], [128], [256], [512]],
            aspect_ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64],
            offset=0.0,
        ),
        anchor_matcher=Matcher([0.3, 0.7], [0, -1, 1], allow_low_quality_matches=True),
        box2box_transform=Box2BoxTransform([1.0, 1.0, 1.0, 1.0]),
        batch_size_per_image=256,
        positive_fraction=0.5,
        pre_nms_topk=(2000, 1000),
        post_nms_topk=(1000, 1000),
        nms_thresh=0.7,

对应RPN forward()的代码如下:

        features = [features[f] for f in self.in_features]
        anchors = self.anchor_generator(features)

        pred_objectness_logits, pred_anchor_deltas = self.rpn_head(features)
        # Transpose the Hi*Wi*A dimension to the middle:
        pred_objectness_logits = [
            # (N, A, Hi, Wi) -> (N, Hi, Wi, A) -> (N, Hi*Wi*A)
            score.permute(0, 2, 3, 1).flatten(1)
            for score in pred_objectness_logits
        ]
        pred_anchor_deltas = [
            # (N, A*B, Hi, Wi) -> (N, A, B, Hi, Wi) -> (N, Hi, Wi, A, B) -> (N, Hi*Wi*A, B)
            x.view(x.shape[0], -1, self.anchor_generator.box_dim, x.shape[-2], x.shape[-1])
            .permute(0, 3, 4, 1, 2)
            .flatten(1, -2)
            .float()  # ensure fp32 for decoding precision
            for x in pred_anchor_deltas
        ]

        if self.training:
            assert gt_instances is not None, "RPN requires gt_instances in training!"
            gt_labels, gt_boxes = self.label_and_sample_anchors(anchors, gt_instances)
            losses = self.losses(
                anchors, pred_objectness_logits, gt_labels, pred_anchor_deltas, gt_boxes
            )
        else:
            losses = {}
        proposals = self.predict_proposals(
            anchors, pred_objectness_logits, pred_anchor_deltas, images.image_sizes
        )

可以提炼为以下几个部分:

  1. features = [features[f] for f in self.in_features]: 从backbone取得的图片特征,共有5 level,每个level的特征为[batch_size, channel, w, h]
  2. anchors = self.anchor_generator(features) -> DefaultAnchorGenerator():每个level的feature map对应一种anchor sizes,feature map上的每个点对应三种aspect_ratios。该函数旨在生成所有的anchors。
  3. anchors pred_objectness_logits, pred_anchor_deltas = self.rpn_head(features) -> StandardRPNHead():送入特征,算出是否是目标和(dx, dy, dw, dh)。pred_objectness_logits[in_features] = [N, A, Hi, Wi],pred_objectness_logits[in_features] = [N, A*B, Hi, Wi]
  4. reshape
  5. gt_labels, gt_boxes = self.label_and_sample_anchors(anchors, gt_instances):其中包括self.anchor_matcher(),通过预设的ROI_THRESHOLDS=[0.3, 0.7],会将每个anchors分为正负样本,并返回每个anchors对应的gt_instances。
  6. losses = self.losses() : 随机选取batch_size_per_image=256个anchors,其中positive_fraction=0.5为正样本,0.5为负样本,用作训练
  7. proposals = predict_proposals(anchors, pred_objectness_logits, pred_anchor_deltas, images.image_sizes)->find_top_rpn_proposals(),该函数用于产生proposals,执行流程包括,根据cls_score选取pre_nms_topk个anchors,根据rpn_bbpx_pred对anchors的location进行微调,获得调整后的bbox,随后根据nms_thresh=0.7执行NMS,然后去除超过边界和过小的anchors,最后根据cls_score选取post_nms_topk个样本
  8. return proposals, losses

3. roi_heads = StandardROIHeads()。

roi_heads=StandardROIHeads(
        num_classes=80,
        batch_size_per_image=512,
        positive_fraction=0.25,
        proposal_matcher=Matcher([0.5], [0, 1], allow_low_quality_matches=False),
        box_in_features=["p2", "p3", "p4", "p5"],
        box_pooler=ROIPooler(7, (1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), 0, "ROIAlignV2"),
        box_head=FastRCNNConvFCHead(
            ShapeSpec(channels=256, height=7, width=7), conv_dims=[], fc_dims=[1024, 1024]
        ),
        box_predictor=FastRCNNOutputLayers(
            ShapeSpec(channels=1024),
            test_score_thresh=0.05,
            box2box_transform=Box2BoxTransform((10, 10, 5, 5)),
            num_classes=80,
        ),
        mask_in_features=["p2", "p3", "p4", "p5"],
        mask_pooler=ROIPooler(14, (1.0 / 4, 1.0 / 8, 1.0 / 16, 1.0 / 32), 0, "ROIAlignV2"),
        mask_head=MaskRCNNConvUpsampleHead(
            ShapeSpec(channels=256, width=14, height=14),
            num_classes=80,
            conv_dims=[256, 256, 256, 256, 256],
        ),
    ),

1. proposal_matcher = Matcher(),会根据ROI_HEADS.IOU_THRESHOLDS来筛选正负样本,并重新指定GT bbox,Fast RCNN从每张图片种选择512个proposals用于训练,其中0.25是正样本,其余为负样本。

2. 在训练时,Fast RCNN不会使用NMS,只有在测试时,会先通过score筛选掉部分结果后,再用NMS输出结果。

对于任意大小的图像,缩放至固定大小后送入网络

对VGG16,所有的conv层都是kernel_size=3, pad=1, stride=1;所有的pooling层都是kernel_size=2, pad=0, stride=2。conv层保持矩阵长宽,pooling层使长宽变为输入的1/2。

# N = Floor((width - kernel_size + 2 * pad) / stride) + 1:可以理解为(边长 + 2倍pad - 一个卷积核)/ 步长,减去的卷积核是最后一个,拿出去了,最后再加一。

RPN:3x3卷积接两个1x1的分支卷积,其目的是将256维的特征图转换为2 * k scores用于判断k个anchor的positive和negative(二分类问题);以及 4 * k coordinates代表k个anchor的变换(用于修正anchor的位置,回归问题)。训练:选取128个正/负anchor用于训练。正样本:(1)和GT有最大重叠区域;(2)IOU > 0.7;负样本:IOU < 0.3

回归涉及到的四个参数:先做平移,即对原始中心点x, y做位移,作者认为位移是和宽/高相关的一个参数;再做缩放:Gw = Aw * exp(dw(A))。训练时:输入正样本和GT之间变换:

 Proposal layer: (1)生成anchors,利用变换对bbox做回归;(2)根据分数从大到小排序anchors,提取前pre_nms_topN个anchors;(3)限定图像边界;(4)剔除尺寸非常小的;(5)做NMS;(6)生成Proposals(对应MxN尺度的)。

# NMS:大致算法流程为:1.对所有预测框的置信度降序排序;2.选出置信度最高的预测框,确认其为正确预测,并计算他与其他预测框的IOU; 3.根据2中计算的IOU去除重叠度高的,IOU>threshold阈值就删除; 4.剩下的预测框返回第1步,直到没有剩下的为止。

(需要注意的是:Non-Maximum Suppression一次处理一个类别,如果有N个类别,Non-Maximum Suppression就需要执行N次。)

# Soft-NMS: soft-nms的核心就是降低置信度。比如一张人脸上有3个重叠的bounding box, 置信度分别为0.9, 0.7, 0.85 。选择得分最高的建议框,经过第一次处理过后,得分变成了0.9, 065, 0.55(此时将得分最高的保存在D中)。这时候再选择第二个bounding box作为得分最高的,处理后置信度分别为0.65, 0.45(这时候3个框也都还在),最后选择第三个,处理后得分不改变。最终经过soft-nms抑制后的三个框的置信度分别为0.9, 0.65, 0.45。最后设置阈值,将得分si小于阈值的去掉。

ROI Pooling:(1)使用spatial_scale参数将proposal映射回feature map尺度;(2)切割

解决正负样本不平衡的问题:在Faster RCNN中是强制正负样本比例为1:1,如果正样本不足,就用负样本补充。后面的工作主要是修改loss weight,例如:OHEM、OHNM、Focal loss

# Focal Loss: 交叉熵是 ylogy‘ + (1-y)log(1-y’)。为了解决正负样本不平衡的问题,通常会在交叉熵损失的前面加上一个参数 α:

把高置信度(p)样本的损失再降低一些:

两者融合就是Focal Loss:

γ=2,α=0.25效果最好。后面对Focal Loss的改进,认为极端困难样本中存在离群点,强行拟合他们是无意义的,进而提出GHM (Gradient Harmonized Single-stage Detector, AAAI-19)。

总共有三个creator

(1)AnchorTargetCreator : 负责在训练RPN的时候,从上万个anchor中选择一些(比如256)进行训练,以使得正负样本比例大概是1:1. 同时给出训练的位置参数目标。 即返回gt_rpn_loc和gt_rpn_label。

(2)ProposalTargetCreator: 负责在训练RoIHead/Fast R-CNN的时候,从RoIs选择一部分(比如128个)用以训练。同时给定训练目标, 返回(sample_RoI, gt_RoI_loc, gt_RoI_label)

(3)ProposalCreator: 在RPN中,从上万个anchor中,选择一定数目(2000或者300),调整大小和位置,生成RoIs,用以Fast R-CNN训练或者测试。

其中AnchorTargetCreator和ProposalTargetCreator是为了生成训练的目标,只在训练阶段用到,ProposalCreator是RPN为Fast R-CNN生成RoIs,在训练和测试阶段都会用到。三个共同点在于他们都不需要考虑反向传播(因此不同框架间可以共享numpy实现)

Faster RCNN训练步骤:

参考:https://www.cnblogs.com/WSX1994/p/11131148.html

第一步:用 Imagenet 初始化共享cov 部分初始化RPN网络,然后训练RPN,在训练后,共享cov以及RPN的特有部分参数会被更新。

第二步:用Imagenet 初始化共享cov 部分初始化Fast-rcnn网络,这里是重新初始化。然后使用训练过的RPN来计算proposal,再将proposal给予Fast-rcnn网络。接着训练Fast-rcnn。训练完以后,共享cov 以及Fast-rcnn的特有部分都会被更新。
说明:第一和第二步,用同样的COV初始化RPN网络和Fast-rcnn网络,然后各自独立地进行训练,所以训练后,各自对cov的更新一定是不一样的(论文中的different ways),因此就意味着model是不共享的(论文中的dont share convolution layers)。

第三步:使用第二步训练完成的 共享cov 来初始化RPN网络,第二次训练RPN网络。但是这次要把 共享cov 锁定,训练过程中,model始终保持不变,而RPN的unique会被改变。
说明:因为这一次的训练过程中, 共享cov始终保持和上一步Fast-rcnn中共享cov一致,所以就称之为着共享。

第四步:仍然保持第三步的 共享cov不变,初始化Fast-rcnn,第二次训练Fast-rcnn网络。其实就是对其特有部分进行finetune,训练完毕,得到一个文中所说的unified network。

IOU代码

有两个框,设第一个框的两个关键点坐标:(x1,y1)(X1,Y1),第二个框的两个关键点坐标:(x2,y2)(X2,Y2)。以大小写来区分左上角坐标和右下角坐标。首先,要知道两个框如果有交集,一定满足下面这个公式:max(x1,x2)<=min(X1,X2) && max(y1,y2)<=min(Y1,Y2)

Batch Normalization:深层神经网络在做非线性变换前的激活输入随着网络变深,其分布逐渐发生偏移和变动(internal covariate shift),之所以训练收敛慢,通常是整体分布逐渐往非线性函数的取值区间的上下限两端靠近,这导致后向传播时,底层神经网络的梯度消失,这是训练深层神经网络收敛越来越慢的本质原因。BN通过一定的规范化手段,把变换后满足均值为0方差为1的x,又进行了scale加上shift操作(y = scale * x + shift)

这里写图片描述

测试时,均值和方差是在整个数据集上通过移动平均法求得的,也是减均值除方差,然后乘以方差,加均值。Batchnorm可以放心的使用大学习率,可以替代其他正则方法如dropout。BatchNorm降低了数据之间的绝对差异,考虑相关差异。Dropout在训练时,是让某个神经元以概率p停止工作,测试时,每一个神经元的权重参数要乘以p。使用顺序:CONV/FC -> BatchNorm -> ReLu(or other activation) -> Dropout -> CONV/FC。也有一篇论文指出可以BN-Dropout

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Detectron2】详解Detectron2中Mask RCNN的部分代码 的相关文章

  • C# 中 KeyPress 、KeyDown 和KeyPress的区别

    1 KeyPress主要用来捕获数字 注意 包括Shift 数字的符号 字母 注意 包括大小写 小键盘等除了F1 12 SHIFT Alt Ctrl Insert Home PgUp Delete End PgDn ScrollLock P
  • 将时间写入数据库时,秒带小数点问题

    1 问题原因 new Date 时间秒带小数点 2 解决思路 将new Date 格式化为年月日时分秒字符串 在将该字符串转为Date 3 示例 Constant类 public final static SimpleDateFormat
  • VScode中文注释乱码问题解决

    VScode默认是用utf 8打开工程代码 C语言里的中文注释如果是Source insight之前gbk编码的注释可能会显示乱码 如何能让代码打开gbk编码的文件也不乱码 设置VScode如下 方法一 依次打开 文件 首选项 设置 然后搜
  • 电机转角控制算法

    时间周期是1 10ms可调 橙色和绿色代表期望和真实速度 红色代表期望角度 紫色代表电机转角 蓝色是减速机输出角度 在9700时刻角度已到达期望角度 速度由 200还未到0 所以算法上需要在要到达目标前某值就需要提前减速 这个值和当前真实速

随机推荐

  • MySQL查询进阶

    多表查询 ALLSOME查询 聚集函数查询 分组查询 分组过滤查询 Student表格 Dept 院系 学院号 学院名 院长 Course表格 Teacher表格 教师号 教师姓名 部门号 工资 SC表格 学号 课程号 分数 反应学生和课程
  • 使用线程池创建线程

    使用线程池可以不用线程的时候放回线程池 用的时候再从线程池取 1 5后引入的Executor框架的最大优点是把任务的提交和执行解耦 Executor接口中定义了一个方法execute 该方法接收一个Runable实例 它用来执行一个任务 任
  • IDEA插件系列(10):Statistic插件——统计代码行数

    1 插件介绍 显示项目统计信息 此插件显示按扩展名排序的文件 以及大小 行数LOC等 2 安装方式 第一种安装方式是使用IDEA下载插件进行安装 第二种方式是使用离线插件进行安装 插件下载地址 http plugins jetbrains
  • W. Richard Stevens Unix网络编程 作品集

    W Richard Stevens 写的那三卷书以怎样的顺序看是比较好的 按我的经验来看先粗略的看一遍卷一 然后再结合卷一看卷二 卷二要看几遍 每遍都会有收获 然后卷三大概看看就行 之后就是看源码 看bsd lite的 在最后就是看linu
  • svn客户端Tortoise SVN使用方法

    svn客户端Tortoise SVN使用方法 转载自 http www cnblogs com armyfai p 3985660 html 该博主介绍比较详细 这里只转载其中svn客户端使用部分 1 首先我们需要下载 svn小乌龟 后 进
  • Webservice实践(二)Webservice 客户端开发

    现在我们首先进行客户端开发的实践 从客户端实践来了解一下webservice的应用场景 比如说现在已经有一个webservice服务 提供的翻译方面的功能服务 主要是免费的webservice接口现在很多都被封了 我们需要编写一个客户端来使
  • Caffe中计算图像均值的实现(cifar10)

    在深度学习中 在进行test时经常会减去train数据集的图像均值 这样做的好处是 属于数据预处理中的数据归一化 降低数据间相似性 可以将数值调整到一个合理的范围 以下code是用于计算cifar10中训练集的图像均值 include fu
  • 代码越写越乱?那是因为你没用责任链

    路人 Java充电社 2022 08 04 08 06 发表于上海 收录于合集 java充电社244个 大家好 我是路人 最近 我让团队内一位成员写了一个导入功能 他使用了责任链模式 代码堆的非常多 bug 也多 没有达到我预期的效果 实际
  • springboot-单点登录

    单点登录 第一节 简介 1 1 什么是单点登陆 单点登录 Single Sign On 简称为 SSO 是目前比较流行的企业业务整合的解决方案之一 SSO的定义是在多个应用系统中 用户只需要登录一次就可以访问所有相互信任的应用系统 较大的企
  • 2023年美赛C题思路复盘

    论文标题 Riddle of Wordle Mining the Secret of Number Scores Solution Words Wordle之谜 挖掘数字得分和解字词的秘密 文章目录 前言 一 题目重述 拟解决的问题 我们的
  • mybatis异常:Could not find result map XXXX

    在使用mybatis框架 报这个错误时 是mapper文件中 查询语句的返回类型写错了 即该用resultType用成了resultMap 如果你要返回基本类型 或者返回已存在的pojo对象 用resultType修饰 如果要使用resul
  • Android ImageLoader用法总结

    前言 imageloader作为一个开源的框架被广泛的使用 尤其对于新手而言 更是如此 本人在项目中每当用到imageloader的时候都是从网上百度然后复制粘贴 现在觉得那样没得意义 因此写此博客 当作以后发复习资料 同时稍微研究下ima
  • springboot依赖

  • 三层架构:界面层、业务逻辑层、数据访问层

    进行用户的插入操作 1 spring会接管三层架构中的那些对象的创建 2 非spring接管下的三层项目构建 从下往上 1 实体类 com bjpowernode pojo Users package com bjpowernode poj
  • 【web开发】扩展与全面接管springmvc

    1 扩展springmvc 方法 编写一个配置类 Configuration 实现WebMvcConfigurer接口 不能标注 EnableWebMvc 特点 既保留了springboot所有的自动配置 也能用我们扩展的配置 示例 pom
  • 数据结构和算法(压缩矩阵和队列模拟)

    具体思路和分析放在末尾 稀疏矩阵的处理方法是 1 记录矩阵一共有几行几列 有多少个不同的值 2 把具有不同值的元素的行列和值记录都在一个小规模的矩阵中 从而缩小程序的规模 原始矩阵转换稀疏矩阵的思路 1 遍历原始的二维数组 得到有效数据的个
  • vue 的表单验证

    1 使用
  • zlib库各历史版本下载网址

    https zlib net fossils
  • Element——el-table给所有的row和column数据加上索引

    问题场景 开发中发现el table在使用cell style时无法获取row column的索引信息 解决思路 在其他可以获取到行列索引的方法中对行列数据添加索引属性 解决方法 利用el table的cell class name配置 以
  • 【Detectron2】详解Detectron2中Mask RCNN的部分代码

    整体来说 Backbone RPN和Fast RCNN是三个相对独立的模块 Backbone对每张图片产生5 level的特征 并送入RPN RPN对送入的特征 首先经过3x3卷积 随后用sibling 1x1卷积产生分类和bbox信息 分