faster rcnn接口_源码解析faster rcnn (mask rcnn)全过程

1. 总领过程--官方faster cnnn 调用过程

import torchvision, torch

# 导入官方faster rcnn 模型

model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False)

# For training

# 生成随机训练数据,用于测试模型跑通

boxes = torch.randint(0, 300, (4, 11, 4))

# right bottom 的值一定比left top 大

boxes[:, :, 2:4:1] = torch.randint(400, 600, (4, 11, 2))

images = torch.rand(4, 3, 600, 1200)

# 生成随机标签

# 此处是数据格式的处理,官方fast rcnn 输入数据只支持images-->list与 targets --> dict

# 后面会细讲

# 关于labele 标签,任何用户定义的标签都不能出现0,官方代码都已经设定label=0为background

labels = torch.randint(1, 91, (4, 11))

images = list(image for image in images)

targets = []

for i in range(len(images)):

d = {}

d['boxes'] = boxes[i]

d['labels'] = labels[i]

targets.append(d)

# 相当于batch_size = 4 的训练

output = model(images, targets)

# For inference

model.eval()

x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)]

predictions = model(x)

# 模型 onnx 保存 可用于前向网络 tensort

# optionally, if you want to export the model to ONNX:

torch.onnx.export(model, x, "faster_rcnn.onnx", opset_version=11)

2. 先谈一下faster rcnn 的原理白裳:一文读懂Faster RCNN​zhuanlan.zhihu.com4642edea042e9e971da8e9a678395cc2.png

总结而言faster rcnn 的原理概括为如下几个重点:1. faster rcnn 原理图backbone 网络整个图像特征提取,如上图所示 conv layers,pytorch 官方 backbone 采用FPN + reset50网络构建,前端将提取5层特征,代码部分细讲

将整张图片的特征做输入rpn网络,做框的分类(二分类实物或者background)和box回归,rpn:在faster rcnn 整个理论中用于产生候选框,官网代码中rpn网络主要由 rpn_head(用于分类和回归) anchor_generator(用于训练时基础框产生) 代码部分细讲

关键是rpn在训练过程中的 ground truth 如何产生,不同目标检测此处处理方式不同, faster rcnn 采用的是动态生成anchors,将anchors 与 实际框和labels做IOU、nms,动态生成训练的label 和boxes

rpn网络将产生proposals框,根据proposals框的大小,选取不同FPN输出层的特征作为特征层

roi pooling 操作后得到的特征将是固定尺度的特征

再接全连接层做实物分类和进一步框回归,同样训练过程中的ground truth也是由 proposals 和 anchor generator作用产生的

3. 结合faster rcnn 原理看faster rcnn 代码

定义一个模型:

model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False)

官方faster rcnn 默认采用的是resnet50网络作为backbone图像特征提取, ctrl + 双击 fasterrcnn_resnet50_fpn 查看fasterrcnn_resnet50_fpn源码

def fasterrcnn_resnet50_fpn(pretrained=False, progress=True,

num_classes=91, pretrained_backbone=True, trainable_backbone_layers=3, **kwargs):

assert trainable_backbone_layers <= 5 and trainable_backbone_layers >= 0

# dont freeze any layers if pretrained model or backbone is not used

if not (pretrained or pretrained_backbone):

# 没有pretrained model 或者是没有pretrained backbone时前端网络前5层均需要训练

trainable_backbone_layers = 5

if pretrained:

# no need to download the backbone if pretrained is set

pretrained_backbone = False

# 定义前端网络 (1)

backbone = resnet_fpn_backbone('resnet50', pretrained_backbone, trainable_layers=trainable_backbone_layers)

# 定义fast rcnn

model = FasterRCNN(backbone, num_classes, **kwargs)

if pretrained:

state_dict = load_state_dict_from_url(model_urls['fasterrcnn_resnet50_fpn_coco'],

progress=progress)

model.load_state_dict(state_dict)

return model

结合原理看下backbone的生成代码

1)首先简易说明FPN原理:2. FPN网络结构图3. FPN全过程

FPN:分层特征提取器

包括:下采样、横向连接、上采样

下采样过程与一般特征提取器无差异,以conv2 ~ conv5为例作为FPN的输入层:

conv5 -> 1X1卷积->M5->P5

conv4 -> 1X1卷积 + M5 上采样(此处默认stride=2) -> M4 -> P4

以次类推,最好FPN输出P5~P2的分层特征,P5~P2特征维度相同,特征尺寸不同

FPN的意义:FPN不是第一个不同层特征融合的网络,但是第一个在目标检测使用多尺度特征融合的方法。CNN的设计中,网络的深度和down sample是一对矛盾体。网络较为浅,特征提取不充分。网络较深,可以提取较大感受野,随之down sample过大,小目标的检测性能显著降低,同时由于CNN的平移不变形,丢失位置信息。而对于卷积神经网络而言,不同深度对应着不同层次的语义特征,浅层网络分辨率高,学的更多是细节特征,深层网络分辨率低,学的更多是语义特征。对于faster rcnn网络而言,深层网络更适宜于做目标的分类,检测网络更适宜于做小目标的检测

FPN接入resnet网络

backbone需要进行特征金字塔的层包含 {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'}

in_channels_list 接入FPN层的 in_channels_list

out_channels FPN 输出层的 channel,不对特征的宽高变化

def resnet_fpn_backbone(backbone_name, pretrained, norm_layer=misc_nn_ops.FrozenBatchNorm2d, trainable_layers=3):

# resnet 网络结构

backbone = resnet.__dict__[backbone_name](

pretrained=pretrained,

norm_layer=norm_layer)

# select layers that wont be frozen

assert trainable_layers <= 5 and trainable_layers >= 0

# 全部可训练层,从后向前选择需要训练的层

layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]

# freeze layers only if pretrained backbone is used

for name, parameter in backbone.named_parameters():

if all([not name.startswith(layer) for layer in layers_to_train]):

parameter.requires_grad_(False)

return_layers = {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'}

in_channels_stage2 = backbone.inplanes // 8

in_channels_list = [

in_channels_stage2,

in_channels_stage2 * 2,

in_channels_stage2 * 4,

in_channels_stage2 * 8,

]

out_channels = 256

# 利用FPN将resnet网络接入,此处也可采用vgg,或者其他自定义网络形式

return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels)

看BackboneWithFPN的源码,注: return_layers, in_channels_list, out_channels 三者的维度关系对应做好

class BackboneWithFPN(nn.Module):

def __init__(self, backbone, return_layers, in_channels_list, out_channels):

super(BackboneWithFPN, self).__init__()

# 根据需返回层的名字return_layers返回特征

self.body = Interme

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值