FasterRCNN详解

faster r-cnn 是第一个完全可微分的检测模型 。也就是从数据到模型输出的整条路径既可以 前行传播 forward ,也可以反向传播 backword 。是一个 end -to- end 模型。

faster r-cnn 发展进程

1. R-CNN :

特点

候选区域 + 卷积特征提取 + (SVM)特征分类 和 边界回归

候选区域:select serch 方法; 提取个数大约:1k~2k
特征提取:CNN 网络
分类和边框回归: 事先训练的SVM 分类器分出类别后 进行线性边框回归得到精准位置。

致命缺陷

  1. 事先大量候选区域提取:(1)无法做到端到端训练;(2)占用大量磁盘空间
  2. 输入CNN 的图像大小固定尺寸,resize 破坏原有特征
  3. 每个region proposal 都经过CNN 网络计算,导致过多重复特征提取
2. fast R-CNN

特点

候选区域 + 特征提取 + softmax分类和边框回归

改进

  1. 特征提取后最后一个卷积层后加了一个ROI pooling layer,参考ssp,不再对图像进行resize。
  2. 损失函数使用了multi-task loss(多任务损失)函数,将边框回归直接加到CNN网络中训练。分类直接用softmax替代SVM进行分类。
3 faster R-CNN

faster rcnn 的亮点是它不要事先进行select serch 获取候选框后再进行训练 ,因此提出了 RPN 网络
1. RPN
2. fast R-CNN

三者对比

在这里插入图片描述

FASTER R-CNN 结构

在这里插入图片描述

1.用anchor 解决边框个数不定的问题
2.用ROI Pooling 解决不同大小边框输出特征向量一致的问题

数据框图

在这里插入图片描述

整体结构

在这里插入图片描述
1.DataSet 作为数据输入
2. BackBone 提取特征,ResNet , VGG16 等,获取特征图
3. 在特征图上对生成的 Anchor 进行 0-1 分类(区分前景和背景)和 边框回归。输入 BBOX 标签得到RPN loss
4. 对每一个anchor 边框(剔除超边界,低sore)经过 NMS 后按分数排序续输出 ROIS
5. ROIS 进入 ROIHead 前经过 ProposalTargetCreator 层,主要是根据 ROIS 与 BBOX 的 IOU 确定 正样本 和 负样本
6. ROIHead 层根据 ROIS 在feature map 上的映射结合 label 进行 边框回归 和 分类。

数据流图

在这里插入图片描述

FASTER R-CNN 核心技术

1. bounding box 回归

bbox 回归时要转换为:中心点(x,y) 与 宽高 (w,h)
原理:
对 bbox 的预测结果 P 和 标记 gt_box Q 之间可以 通过学习一组参数并进行线性变换得到。变换参数:
在这里插入图片描述
这四个参数都是特征的函数,前两个体现为bbox的中心尺度不变性,后两个体现为体现为bbox宽高的对数空间转换。学到这四个参数(函数)后,就可以将P映射到G’, 使得G’尽量逼近G。
在这里插入图片描述
也就是先将中心点进行平移,在对宽高尺度进行缩放,为约束宽高为正,取exp变换,除以宽高使得网络具有尺度不变性,网络输出特征自动适应这种变换。变换是人为设定,一切为了让网络更好学习
在这里插入图片描述在proposal 层,可以理解原始proposal为anchor预设框。
这里的变换参数:
在这里插入图片描述
是由特征图进过一层网络学习后得到,也就是是关于候选框 P 的特征的函数。所以变换关系可以定义为:
在这里插入图片描述
真值 G 与 预测 P 之间的关系如下:
在这里插入图片描述
在这里插入图片描述
所以边框回归的目标参数就是:
在这里插入图片描述
其中P为原始框,在proposal 层为anchor初始预设框,其中P值已知, G值已知, G^ 值为经过网络学习后映射得到
由P, G 构建学习目标真值:
在这里插入图片描述
最后由学习输出特征值:
在这里插入图片描述
与P,G 构建的真值作loss,使得输出特征尽可能往真值上靠拢。

faster rcnn 的bounding box 回归如下:
在这里插入图片描述
在这里插入图片描述
测试阶段需要根据变换公式还原得到bounding box 的中心点和宽高:
在这里插入图片描述

我们的目的是使得每一个边框的变换参数 d 尽可能接近 t 。d 与 t 产生LOSS ,以此学习更新 边框特征的 W 权重。 使得测试时bbox经过W运算后可以得到一个较好的offsets与scales,利用这个offsets与scales可在原预测bbox上微调,得到更好的预测结果。还有就是这个回归数据对(P,G)不是随便选的,预测的P应该离至少一个ground truth G很近,这样学出来的参数才有意义。近的度量是P、G的IOU>0.6。

FASTER R-CRNN 训练

RPN network

在这里插入图片描述
上面分支用于分类前景和背景,需要进行softmax 操作**。loss 用二分类loss,正负样本均参与。
下面的分支用于计算anchor的回归量,获得精准的proposal。loss 用smoothL1 ,只有正样本参与计算。
最后的ProposalLayer 综合前景anchor和回归量获取Proposals。经过score 排序,边缘过滤,NMS等筛选出Proposals。

1、RPN 训练正负样本挑选:

满足以下条件的Anchor是正样本:
与Ground Truth Box的IOU(Intersection-Over-Union) 的重叠区域最大的Anchor;
与Gound Truth Box的IOU的重叠区域>0.7;

满足以下条件的Anchor是负样本:
与Gound Truth Box的IOU的重叠区域 <0.3;
既不属于正样本又不属于负样本的Anchor不参与训练
问题:如果大多数anchor与GT 的IOU 俊不大于0.7会怎么样?这样的正样本是不是纯正的正样本?

2、RPN LOSS:

在这里插入图片描述在这里插入图片描述
R是Smooth L1函数;

在这里插入图片描述
在这里插入图片描述
带超参的smoothL1:
在这里插入图片描述

Smooth L1完美地避开了 L1 和 L2 损失的缺陷,在 x 较小时,对 x 的梯度也会变小; 而在 x 很大时,对 x 的梯度的绝对值达到上限1,不会因预测值的梯度十分大导致训练不稳定。
在这里插入图片描述
表示只有在正样本时才回归Bounding Box

两个类别(前景和背景)的对数损失:
在这里插入图片描述

Anchors Generator

在这里插入图片描述
假设经过16倍下采样后,输出 feature map 大小为50 * 38 。
预设3 种 anchor scale(8, 16, 32), 预设 3种宽高比(0.5, 1, 2)两两组合为9种尺度anchor。更高效的anchor生成需要对数据集进行 N 聚类。

3、ProposalCreator: ProposalLayer

RPN 最后一层为proposal layer,用于前景anchors。
backbone feature 输出信息 :im_info=[M, N, scale_factor],
anchor对应的边框回归微调参数$[d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A)]
结合产生Proposal 的位置,此时的Proposal 位置坐标对应原图尺度坐标

Proposal Layer forward

1、生成anchors:利用 [ d x ( A ) , d y ( A ) , d w ( A ) , d h ( A ) ] [d_{x}(A),d_{y}(A),d_{w}(A),d_{h}(A)] [dx(A),dy(A),dw(A),dh(A)]对所有的anchors做bbox regression回归(这里的anchors生成和训练时完全一致)

2、按照输入的foreground softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)个anchors,即提取修正位置后的foreground anchors

3、过滤:限定超出图像边界的foreground anchors为图像边界(防止后续roi pooling时proposal超出图像边界)- 剔除非常小(width<threshold or height<threshold)的foreground anchors。

4、NMS (nonmaximum suppression)

5、再次按照nms后的foreground softmax scores由大到小排序fg anchors,提取前post_nms_topN(e.g. 300)结果作为proposal = [x1, y1, x2, y2]输出。输出的proposal=[x1, y1, x2, y2],由在第三步中将anchors映射回原图判断是否超出边界,这里输出的proposal是对应MxN输入图像尺度的

POI pooling

由于proposal是对应原图 M x N 尺度的,所以首先使用spatial_scale参数将其映射回 (M/16) x (N/16) feature map尺度。

POI pooling 希望不同大小的proposal 经过pooling 后输出大小一致。实现长度固定输出。

1、获取 proposal 在feature map 上的 roi 区域。(存在精度损失)
在这里插入图片描述2、切割roi 区域。 (存在精度损失)
此时切割并不是等间隔切割,例如:
57的特征图划分成22的时候不是等分的,行是5/2,第一行得到2,剩下的那一行是3,列是7/2,第一列得到3,剩下那一列是4
在这里插入图片描述3、对切割区域进行maxpooling。
在这里插入图片描述

更加精准要使用ROI Align。

Roi pooling 经过两次取整,一次在将proposal映射到feature map 上取整;另一次为在feature map上作等大小块区域划分取整。
例如一个 665的bbox, backbone scale 为32,那么在feature map上为 665/32 = 20.78, 取整 = 20 ,误差 = 0.8 * 32 = 25。做回归时,如果对于大物体影响较小,如果对于小物体目标,影响就很大。

roi align

第一步:将proposal 映射到feature map 上时不取整,直接用浮点数进行下一步运算。

第二步:将映射到feature map 的浮点 region proposal 等块数划分,划分间距也是浮点数。

第三步:对每一划分块,按采样间隔平分,每一份取其中心点位置。采用双线性插值计算,得到中心采样点的像素坐标。

第四步:所有份中,取中心采样点中最大像素值作为该块的值。最后输出块个数固定。

例如 :scale = 32 , pooled_h = 7
665 / 32 = 20.78。feature map 大小
20.78 / 7 = 2.97。划分间距。总分为77 = 49 块。
在这里插入图片描述
将2.97
2.97 按 22 平分。取每一份中心。对每一个中心坐标双线性插值,得到像素值(在 feature map 上得到的是特征值)。
最后得到7
7块中每一块的特征值。组成该region proposal 的feature。

ROI 分类回归

将pooling 后输出(每一个roi 大小一致)作为输入,同样经过几层卷积后分两个分支:
一个用于分类,这里是多分类。
另一个用于更加精准的边框回归,在proposal 的基础上再次bounding box regression。
在这里插入图片描述

LOSS 计算

1、 RPN层的两个损失:1.是否为前景背景的二分类交叉熵损失 2. bbox的第一次修正损失。上面已经提到。
值得注意的是rpn_cls_score的shape=(1,h,w,18),也就是(1, h,w,92),作为真值监督信号。
因此在将anchor score predict 作loss 的时候需要将其reshape 成(N,9
h, w, 2),对最后 2 的维度进行 softmax ,得到概率值,最后 reshape 回(N, H, W , 18)与 rpn_cls_score 作loss。整个过程没有改变数据的位置,reshape 的目的是为了在每一个predict 上作softmax。
在这里插入图片描述

2、最后分类回归的两个损失:1.num_classes分类损失 2.第二次bbox修正损失

二阶段网络训练样本生成

1、两次生成并挑选训练样本:

第一次生成并挑选:proposal 阶段,给anchor打标签,anchor 与 bbox 生成正负样本和回归量。主要用来do loss 用。为了正负样本平衡,不是所有的anchor都参与训练,IOU 处于过渡区域的anchor label = -1,作为忽略样本 。

proposalLayer : 需要用到 anchor, loc2bbox + clip + kick-minsize + NMS 生成Head阶段需要的ProposalROI

第二次生成并挑选:head阶段,给ProposalROI 打标签。ProposalROI 与 bbox 生成label和回归量。并将ProposalROI 与 任意 bbox 的IOU小于某阈值的类别置为0背景类为了正负样本平衡,不是所有的ProposalROI都参与训练,正样本和背景类都选一些,尽可能避免过渡样本(IOU处于中间)参与训练。

总结:

第一阶段,给anchor打标签
第二阶段,给ProposalROI 打标签
两个阶段,都必须考虑样本均衡

所以不管是哪个阶段,生成训练样本总结起来就是两个问题:

1、什么是正样本,什么是负样本或背景样本(对于多分类)
2、如何选正样本,如何选负样本或背景样本,选哪些,选多少。

搞清楚以上两个问题,对整个二阶段训练极为关键,弄懂了也就理解了。

代码流程

forword 过程:

1、特征抽取

特征抽取主要将图像经过backbone 运算得到一个feature map:
features = self.faster_rcnn.extractor(imgs)

2、RPN 网络
初始化预先构建base_anchor。

(1)、RPN CONV
就是简单的将feature map 经过几层卷积得到 loc 分支和 score fen分支。有网络参数,作为一阶段的终结点

self.conv1 = nn.Conv2d(in_channels, mid_channels, 3, 1, 1)
self.score = nn.Conv2d(mid_channels, n_anchor * 2, 1, 1, 0)
self.loc = nn.Conv2d(mid_channels, n_anchor * 4, 1, 1, 0)

由于做RPN loss 时候需要将预测和gt 维度对齐。且score 的值需要经过softmax 概率化参能计算loss。因此需要如下的维度转换。

rpn_locs = rpn_locs.permute(0, 2, 3, 1).contiguous().view(n, -1, 4) #do rpn loss
rpn_scores = rpn_scores.permute(0, 2, 3, 1).contiguous()

rpn_softmax_scores = F.softmax(rpn_scores.view(n, hh, ww, n_anchor, 2), dim=4)
rpn_fg_scores = rpn_softmax_scores[:, :, :, :, 1].contiguous() #get positive score value
rpn_fg_scores = rpn_fg_scores.view(n, -1)
rpn_scores = rpn_scores.view(n, -1, 2)  #do rpn loss

(2)、RPN Proposal
结合score 和 loc 经过过滤筛选(NMS等)输出 proposal ROIs 的网络。无网络参数。
RPN CONV 输出的 LOC 预测的是(dx, dy, dh, dw), proposal ROIs 需要还原回真实框。

if is_training:
     n_pre_nms = self.n_train_pre_nms
     n_post_nms = self.n_train_post_nms
 else:
     n_pre_nms = self.n_test_pre_nms
     n_post_nms = self.n_test_post_nms

 roi = loc2bbox(anchor, loc)
# Clip predicted boxes to image.
 roi[:, slice(0, 4, 2)] = np.clip(roi[:, slice(0, 4, 2)], 0, img_size[0])
 roi[:, slice(1, 4, 2)] = np.clip(roi[:, slice(1, 4, 2)], 0, img_size[1])
 # Remove predicted boxes with either height or width < threshold.
 min_size = self.min_size * scale
 #print "roi ize = ", roi.shape
 hs = roi[:, 2] - roi[:, 0]
 ws = roi[:, 3] - roi[:, 1]
 keep = np.where((hs >= min_size) & (ws >= min_size))[0]
 roi = roi[keep, :]
 score = score[keep]
 order = score.ravel().argsort()[::-1]
 if n_pre_nms > 0:
     order = order[:n_pre_nms]
 roi = roi[order, :]
 # Apply nms (e.g. threshold = 0.7).
 # Take after_nms_topN (e.g. 300).
 keep = non_maximum_suppression(
     cp.ascontiguousarray(cp.asarray(roi)),
     thresh=self.nms_thresh)
 if n_post_nms > 0:
     keep = keep[:n_post_nms]
 #print "keep.shape1 = " ,keep.shape
 roi = roi[keep]
 score =score[keep]
 return roi , score

(3)、RPN LOSS

给anchor 打cls标签,和计算预测真值。
由于RPN CONV 输出的 LOC 预测的是(dx, dy, dh, dw), 在做IOU 运算

gt_rpn_loc, gt_rpn_label = self.anchor_target_creator aytool.tonumpy(bbox),anchor,img_size)
rpn_loc_loss = _fast_rcnn_loc_loss(rpn_loc,gt_rpn_loc,gt_rpn_label.data,self.rpn_sigma)
rpn_cls_loss = F.cross_entropy(rpn_score, gt_rpn_label.cuda(), ignore_index=-1)

(4)、HEAD

ROI Pooling
HEAD conv + linear

pool = self.roi(x, indices_and_rois)
pool = pool.view(pool.size(0), -1)
fc7 = self.classifier(pool)
roi_cls_locs = self.cls_loc(fc7)
roi_scores = self.score(fc7)
return roi_cls_locs, roi_scores

(4)、HEAD LOSS

还是分类和回归。不过这回是多分类。

roi_loc_loss = _fast_rcnn_loc_loss(roi_loc.contiguous(),gt_roi_loc,gt_roi_label.data,self.roi_sigam)
roi_cls_loss = nn.CrossEntropyLoss()(roi_score, gt_roi_label.cuda())
Faster RCNN是一种基于深度学习的目标检测算法,它是RCNN、Fast RCNN的改进版,具有更快的检测速度和更高的准确率。本文将详细介绍Faster RCNN的PyTorch实现。 Faster RCNN的实现主要分为两个部分:特征提取和区域提取。特征提取使用预训练的卷积神经网络(如VGG16、ResNet等)对输入图像进行特征提取,得到一系列特征图。区域提取使用RPN(Region Proposal Network)对特征图进行处理,得到一系列候选区域,然后对每个候选区域进行分类和回归,得到最终的目标检测结果。 在PyTorch中实现Faster RCNN,可以使用torchvision中的models和transforms模块,以及torch.utils.data中的DataLoader和Dataset模块。具体实现步骤如下: 1. 加载数据集 使用torchvision中的transforms模块对数据进行预处理,然后使用Dataset模块加载数据集,最后使用DataLoader模块对数据进行批量处理。 2. 加载预训练模型 使用torchvision中的models模块加载预训练模型(如VGG16、ResNet等),然后修改模型最后一层的输出,使其适应目标检测任务。 3. 定义RPN 定义RPN网络,包括卷积层、分类层和回归层,使用预训练模型的特征图作为输入,输出候选区域。 4. 定义ROI Pooling层 定义ROI Pooling层,将候选区域映射到固定大小的特征图上,以便进行分类和回归。 5. 定义分类和回归网络 定义分类和回归网络,包括卷积层、全连接层和softmax层,使用ROI Pooling层的输出作为输入,输出目标检测结果。 6. 训练模型 使用反向传播算法和优化器对模型进行训练,调整模型参数,使其适应目标检测任务。 7. 测试模型 使用测试数据集对模型进行测试,计算模型的准确率和召回率,评估模型性能。 以上就是Faster RCNN的PyTorch实现步骤,具体实现细节可以参考PyTorch官方文档和相关论文。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值