FasterRCNN目标检测

本文详细介绍了R-CNN、FastRCNN和FasterRCNN的原理,包括候选区域提取、特征提取、共享卷积、ROIPooling、多任务损失函数和RPN网络等关键组件。讲述了如何从原始图像通过深度学习模型进行目标检测和定位的过程。

R-CNN

在这里插入图片描述

四个步骤:

  1. 对输入图片提取候选区(region proposal),每张大约2000个。论文中采用selective search的方法。
  2. 对每个候选区采用CNN网络提取特征。此处需要将proposal的尺寸缩放成统一的227x227,以匹配CNN网络。最终提取到的特征展平处理,长度为4096。
  3. 类别判断。将所提特征送入每一类的SVM分类器,判断是否属于该类。
  4. 候选框位置回归。

Fast RCNN

在这里插入图片描述

Fast RCNN相比于RCNN改进了3点:

  1. 共享卷积:将整幅图输出卷积神经网络,得到特征图,而不是像RCNN那样一个一个的候选区域输入卷积神经网络。
  2. ROI Pooling:将最后一个卷积层的SSP Layer改为RoI Pooling Layer,利用特征池化的方法,进行特征尺度变换,这样可以有任意大小的图片输入。
  3. 多任务损失函数:将边框回归直接加入到CNN网络中训练,同时包含了候选区域分类损失和位置回归损失。

Faster RCNN

在这里插入图片描述

  1. Conv layers。作为一种CNN网络目标检测方法,Faster RCNN首先使用一组基础的conv+relu+pooling层提取image的feature maps。该feature maps被共享用于后续RPN层和全连接层。
  2. Region Proposal Networks。RPN网络用于生成region proposals。该层通过softmax判断anchors属于positive或者negative,再利用bounding box regression修正anchors获得精确的proposals。
  3. Roi Pooling。该层收集输入的feature maps和proposals,综合这些信息后提取proposal feature maps,送入后续全连接层判定目标类别。
  4. Classification。利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置。
    在这里插入图片描述

在这里插入图片描述

作为 torchvision 中目标检测基类,GeneralizedRCNN 继承了 torch.nn.Module,后续 FasterRCNN 、MaskRCNN 都继承 GeneralizedRCNN。

4个步骤:

  1. 将 transform 后的图像输入到 backbone 模块提取特征图

    #GeneralizedRCNN.forward(…)
    features = self.backbone(images.tensors)
    backbone 一般为 VGG、ResNet、MobileNet 等网络。

  2. 然后经过 rpn 模块生成 proposals 和 proposal_losses

    #GeneralizedRCNN.forward(…)
    proposals, proposal_losses = self.rpn(images, features, targets)

  3. 接着进入 roi_heads 模块(即 roi_pooling + 分类)

    #GeneralizedRCNN.forward(…)
    detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets)

  4. 最后经 postprocess 模块(进行 NMS,同时将 box 通过 original_images_size映射回原图)
    #GeneralizedRCNN.forward(…)
    detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes)

在这里插入图片描述

对于普通的 FasterRCNN 只需要将 feature_map 输入到 rpn 网络生成 proposals 即可。但是由于加入 FPN,需要将多个 feature_map 逐个输入到 rpn 网络。

在这里插入图片描述

class AnchorGenerator(nn.Module):
    def generate_anchors(self, scales, aspect_ratios, dtype=torch.float32, device="cpu"):
    def set_cell_anchors(self, dtype, device):

首先,每个位置有 5 种 anchor_size 和 3 种 aspect_ratios,所以每个位置生成 15 个 base_anchors:

[ -23., -11., 23., 11.] # w = h = 32, ratio = 2
[ -16., -16., 16., 16.] # w = h = 32, ratio = 1
[ -11., -23., 11., 23.] # w = h = 32, ratio = 0.5
[ -45., -23., 45., 23.] # w = h = 64, ratio = 2
[ -32., -32., 32., 32.] # w = h = 64, ratio = 1
[ -23., -45., 23., 45.] # w = h = 64, ratio = 0.5
[ -91., -45., 91., 45.] # w = h = 128, ratio = 2
[ -64., -64., 64., 64.] # w = h = 128, ratio = 1
[ -45., -91., 45., 91.] # w = h = 128, ratio = 0.5
[-181., -91., 181., 91.] # w = h = 256, ratio = 2
[-128., -128., 128., 128.] # w = h = 256, ratio = 1
[ -91., -181., 91., 181.] # w = h = 256, ratio = 0.5
[-362., -181., 362., 181.] # w = h = 512, ratio = 2
[-256., -256., 256., 256.] # w = h = 512, ratio = 1
[-181., -362., 181., 362.] # w = h = 512, ratio = 0.5

由于有 FPN 网络,所以输入 rpn 的是多个特征。为了方便介绍,以下都是以某一个特征进行描述,其他特征类似。

假设有h * w的特征,首先会计算这个特征相对于输入图像的下采样倍数 stride:
比如原图800*800大小的图片,输出特征图50*50,stride则为800/50=16
在这里插入图片描述
然后生成一个h*w大小的网格,每个格子长度为 stride,如下图:
在这里插入图片描述

#AnchorGenerator.grid_anchors(...)
shifts_x = torch.arange(0, grid_width, dtype=torch.float32, device=device) * stride_width
shifts_y = torch.arange(0, grid_height, dtype=torch.float32, device=device) * stride_height
shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x)

然后将 base_anchors 的中心从(0,0)移动到网格的点,且在网格的每个点都放置一组 base_anchors。这样就在当前 feature_map 上有了很多的 anchors。
stride 代表网络的感受野,网络不可能检测到比 feature_map 更密集的框了!所以才只会在网格中每个点设置 anchors(反过来说,如果在网格的两个点之间设置 anchors,那么就对应 feature_map 中半个点,显然不合理)。
在这里插入图片描述

#AnchorGenerator.grid_anchors(...)
anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4))

#RPN

  1. 如果输入3*600*800的图像,经过Backbone网络,降采样率为16,输出512*37*50(600/16=37.5,800/16=50)的特征图feature map.

  2. 经过RPNhead的3*3卷积神经网络维度还是512*37*50,对于分类网络分支,1x1卷积输出18*37*50的特征,对于回归网络分支,1x1卷积输出36*37*50的数据。
    18是因为在RPN中的分类网络部分只是判断有无物体,即正负样本,不进行物体类别分类,所以分类结果只有两种(0和1),若每个特征点生成9个锚框Anchor,2*9=18.
    回归网络中每个anchor对应四个数据,tx、ty、tw、th,因此9x4=36。

  3. RPN中的AnchorGenerator 生成37*50*9=16650个锚框Anchors,有一些锚框超出了边界,因此保留边框内部部分。

  4. RPN中分类网络部分:通过计算Anchor与标签的IOU来判断是正样本还是负样本,具体实现时,需要计算每一个Anchor与每一个标签的IOU,因此会得到一个IOU矩阵。判断标准如下:

     (1) 对于任何一个Anchor,与所有标签的最大IOU小于0.3,则视为负样本。
     (2) 对于任何一个标签,与其有最大IOU的Anchor视为正样本。
     (3) 对于任何一个Anchor,与所有标签的最大IOU大于0.7,则视为正样本。
    

    由于Anchor的数量接近2万,并且大部分时背景,因此需要筛选一部分,默认选择256个Anchor。

  5. RPN的回归偏移真值:得到anchor相对于target框的偏移量后,保存在bbox_tarets中,损失函数通常使用smooth函数,smooth函数结合了1阶与2阶损失函数,原因在于,当预测偏移量与真值差距较大时,使用2阶函数时导数太大,模型容易发散而不容易收敛,因此大于1时采用导数较小的1阶段损失函数。

  6. RPN的非极大值抑制(NMS)将重叠的框去掉,最后再次根据RPN的预测得分选择前2000个,作为最终的Proposal,输出到下一阶段。这里得到2000个候选框还是太多,继续Select Sample,筛选出的正负样本总数为256,筛选标准如下:

     (1)对于任何一个proposal,其与所有标签的最大IOU如果大于等于0.5,则视为正样本。
     (2)对于任何一个proposal,其与所有标签的最大IOU如果大于等于0且小于0.5,则视为负样本。
    

    为了控制正负样本比例基本满足1:3,在此正样本数量不超过64,超过了则随机选取64个。

ROI Pooling

  1. 从RPN得到了256个ROI,以及每一个ROI对应的类别与偏移量真值,为了计算损失,还需要计算每一个ROI的预测量。由于ROI是由各种大小高宽不同的Anchor经过偏移修正、筛选得到的,但后续的RCNN全连接网络部分要求输入特征大小维度固定。Pooling的过程就是获得7*7大小区域的特征。
  2. 如输入原图像600*800,ROI为332*332,对应原图的一块子区域,经过下采样率为16的Backbone,特征图上ROI对应区域为20*20大小(332/16=20.75),然后为了获得7x7的特征,20/7=2.857,对ROI对应的20*20区域进行步长为2的最大池化。

全连接RCNN模块

  1. 在经过ROIPooling层之后,特征被池化到了固定的维度,因此接下来可以利用全连接网络进行分类与回归预测量的计算。经过池化后的256个ROI维度为256*512*7*7,作展平处理为256*25088,两个全连接网络输出256*4096,再分别进入分类网络分支和回归网络分支,得到256*21的分类输出和256*84的回归网络输出
  2. RCNn部分的损失函数计算方法与RPN相似,只不过分类类别有2变为21,回归则是至多有64个正样本参与回归计算,负样本不参与回归计算。

代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

网络输出
2. RCNn部分的损失函数计算方法与RPN相似,只不过分类类别有2变为21,回归则是至多有64个正样本参与回归计算,负样本不参与回归计算。

代码

[外链图片转存中…(img-ujOc2x2C-1699491243408)]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值