Faster-RCNN理解

本文所看的GitHub地址为:simple-faster-rcnn-pytorch

参考了些博客,主要为:逐字理解faster-rcnn

以及:Faster_RCNN

https://zhuanlan.zhihu.com/p/84465138 这个人最后画的图蛮好的

大的总结:

Region Proposal Network

以下提到的 offset, scale 其实都代表位置偏差,只是x,y是上下左右移动,框高就是缩放了。

一. Region Proposal Network 作用

这个RPN网络主要作用就两个:

作用一: 提供 proposal rois 给 Fast-rcnn,这里的rois是(x_left_top,y_left_top,width,height)。

作用二:训练自身的 bounding box regression 和分类。

1.RPN输入是 backbone提取的特征,然后经过3x3卷积,后面是两个并行的1x1的卷积,见下图:

这里一定要明白,上图左边36=9x4,这里的4是(x,y,w,h)四个值,且其是 offset 和 scale,不是与ground truth一样,也就是说,RPN预测值是预测的偏移量(不是预测的框的坐标),有了偏移量,把偏移量带入公式(公式如下,且预测值是d.(p)(这里用d.代表dx,dy,dw,dh))就得到真实的坐标,这里的坐标就是下面这个:

RPN训练自身的 box regression 是想达到预测的 p_offset, p_scale 非常准确,这样通过上面公式1-1就可以达到跟实际 Ground Truth 很接近的位置坐标。那么,其是怎么训练自身的?它是通过smooth L1 来求的,首先,求出 anchor 与 ground truth 之间的 (a_gt_offset, a_gt_scale),把(a_gt_offset, a_gt_scale)作为基准,然后把(p_offset, p_scale)和(a_gt_offset, a_gt_scale)带入smooth L1求loss。不断训练,让RPN网络预测的(p_offset, p_scale)值和(a_gt_offset, a_gt_scale)值无限接近,当loss最小的时候,就代表无限接近。那么,当(p_offset, p_scale)值和(a_gt_offset, a_gt_scale)值无限接近的时候,把(p_offset, p_scale)带入上面公式1-1,就可以直接得出一个G‘ = Ground Truth了。

那么,anchor与ground truth之间offset和scale怎么求呢?是通过下面公式1-2来求:

对于公式1-2大家不要让其Px,Py,Pw,Ph迷惑,当我们在计算 anchor 与 ground truth 的时候,P就是anchor的值,只不过anchor的坐标要转换为(x中心点,y中心点,宽度,高度)对应的格式。

对于label的值,其是根据 对于的 loc 与 bbox 的 iou值来决定的。

RPN 网络训练的时候,batch size =1,即每次都是一张图片训练。

二. Region Proposal Network 里的两个主要方法

1. AnchorTargetCreator 其作用是用于训练RPN,提高RPN的Proposal更准确。

(1). 首先这个方法输入feature_map_width * feature_map_widht * 9 个anchor,以及对应这张图片的 ground truth。

(2). 然后根据图片的框高过滤掉不在图片内部的anchor,接下来参与计算的只有图片内部的anchor。

(3). 接着计算anchor与ground truth bbox的iou。找到每个anchor与哪个bbox的iou最大,且其最大值大于一定阈值则为正样本,接着找到每个bbox与哪些anchor的iou最大(假如有bbox1, bbox2, 15000个anchor,那么找到与bbox1的iou最大的anchorX, 以及与bbox2的iou最大的anchorY,这里的anchorX, anchorY 可能有多个,因为iou相同大)的作为正样本,接着把iou小于一定阈值的作为负样本。

(4). 然后根据预先设定的正负样本比例1:1,正样本选取128个,负样本选取128个,共计256个。如果正样本只有26个,那么负样本就选取230个,反之类似;如果正样本,负样本都不足128,那就按其各自有多少算多少。

(5). 接着把 anchor 和 ground truth bbox 的位置坐标转换为(x_中心点,y_z中心点,宽度,高度),按照公式1-2计算 anchor 与 ground truth之间的offset, scale。

(6). 把除了正负样本的label给标记为-1,loc全部赋为0。

(7). 接着把正负样本的 a_gt_offset 与 RPN 网络预测的 p_loc 进行 smooth L1计算 loss, 和 a_gt_label 与 p_label 进行 cross_entropy 计算 loss。

2. ProposalCreator 其作用是把RPN网络生成的 9 * feature_map_width * feature_map_height 个筛选出2000个给ProposalTargetCreator

(1). 通过anchor 和 预测值 带入公式1-1计算每个预测值带入公式后的坐标,下面就是公式1-1代码形式,且src_xxxx就是anchor,dxxx 就是预测值。

ctr_y = dy * src_height[:, xp.newaxis] + src_ctr_y[:, xp.newaxis]
ctr_x = dx * src_width[:, xp.newaxis] + src_ctr_x[:, xp.newaxis]
h = xp.exp(dh) * src_height[:, xp.newaxis]
w = xp.exp(dw) * src_width[:, xp.newaxis]

(2). 把 ctr_y, ctr_x, h, w 转换为 左上右下坐标(x_left_top, y_left_top, x_right_down, y_right_down),记为 P_Box

(3). 过滤掉 P_Box 中在图片外部的坐标,得到 P_Box_B。

(3). 通过原始图片与resize到固定图片后,这两者的宽高比:scale,再乘以self.min_size(代码中设定为16)得到一个min_val,然后过滤掉 P_Box_B 中宽高不大于min_val的框,得到 P_Box_C。

(4). 接着对预测的值按照其概率从大到小排序,找到前12000个。( 在这里有一点不明白,就是一个框预测为前景概率和背景概率之和为1,但是它有两个值,作者统一用的第二列的值,难道作者这里默认第二列都为前景概率?不过作者这么选,也行,就是始终认为第二列为前景概率,然后不断训练)

(5). 对12000个进行NMS过滤,阈值为 0.7, 选出 前 2000个,不足2000就按实际有多少算多少。

3. ProposalTargetCreator 其作用是对 ProposalCreator 推荐的 2000个进行进一步筛选,筛选出 128个(32个正样本,128个正样本)给 ROI head,即 fast-rcnn网络

(1). 利用 ProposalCreator 推荐的 2000 个 与 真实的 ground truth 进行 iou 计算。

(2). 选出2000个与哪个 ground truth的iou最大的索引,与哪个最大就代表属于这个ground truth对应的label,然后对每个label加1,得到的gt_roi_label就是属于具体哪个label了,如下。

iou = bbox_iou(roi, bbox)
gt_assignment = iou.argmax(axis=1)
max_iou = iou.max(axis=1)
# Offset range of classes from [0, n_fg_class - 1] to [1, n_fg_class].
# The label with value 0 is the background.
gt_roi_label = label[gt_assignment] + 1

(3). 接着判断 iou 的值大于一定阈值为正样本,随机选出32个,不足就以实际为准;阈值大于零,小于一定阈值为负样本,随机选出96个,不足以实际为准。

(4). 对拷贝刚刚选出的128个样本一份,用拷贝版本与ground truth 进行 计算 offset,且对这个offset进行了归一化处理。这个offset 就作为一个基准了,就是 gt_offset了,也就是说,其给 ROI Head 输入有 proposal, 还有 ground truth(一般都是给proposal 和 ground truth,这里也不列外),只不过这个 ground truth就是 gt_offset,还有backbone提取的feature。

       冬夜读书示子聿
                     陆游
古人学问无遗力,少壮工夫老始成。
纸上得来终觉浅,绝知此事要躬行。

小细节:

不知道大家看代码有没有注意到这里,下图所示:

for layer in features[:10]:   
	for p in layer.parameters():
    	p.requires_grad = False

能进入for p in layer.parameters():循环下的只有 Conv2d,而且会进入两次,刚开始不理解为啥两次,是因为有两个卷积,一个输入,一个输出,这两个卷积都不更新

RegionProposalNetwork

  1. 实现了生成所有anchor

  2. ProposalCreator在其内部

  3. RPN网络后面 3x3 卷积,两个 1x1 卷积

Normal_init

VGG16RoIHead:输入:分类+1(背景),roi pooling size,spatial_scale(这个主要用于rois的坐标映射到 feature map 上的缩放比例),分类(decom_vgg16),这个就是fast-rcnn网络了。

RoIPool:这个用的pytorch.ops自带的

FasterRCNN:这个好像是基类

FasterRCNNVGG16 -> 提取到 extractor,classier -> RegionProposalNetwork

                                                                                 -> VGG16RoIHead

FasterRCNNVGG16 类只实现了init函数,其继承自FasterRCNN类,这个中实现了 forward,所以,提取feature 就是在这个FasterRCNN中做的。

所以,总的入口是FasterRCNNVGG16,然后其初始化了基类FasterRCNN,接着FasterRCNNVGG16定义一个其对象,这个对象传入FasterRCNNTrainer类中,然后在这个类中调用了AnchorTargetCreator()和ProposalTargetCreator()类,实现了训练自身和推荐rois给ROIHead。

1.当基类调用FasterRCNNVGG16对象时,对于传入图片,会调用extractor,提取到特征,然后调用rpn,产生 anchor,rois(2000个),接着调用self.proposal_target_creator,对传入的rois进行过滤,接着调用ROIHead,再调用anchor_target_creator,接着就是算loss。


不理解 gt_roi_label = label[gt_assignment] + 1 这个地方虽然说把gt的label从0-19转为1-20,但是label有时有两个值,gt_assignment是每行的最大索引,那分配分出来就是每行最大索引对应的label中的值,但是label不是背景和前景,但是gt_assignment是计算的box与iou最大的,我认为有些是背景,但是label中没有背景,label中是两个类别,这就没有把对应的 gt_assignment算的是与两个bbox(真实box)的概率,、

理解了理解了,到ProposalTargetCreator这一步输入的2000个其实已经全是前景了,所以上面就是看前景分别属于哪个gt对应的label,因为label里面包含两个bbox,这样gt_assignment就是说的与label中哪个bbox的iou最大,最大就属于对应的label

而且还会对选出的2000个选出128个,再选出32个为正样本,96个为负样本

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值