RPNHead
RPNHead的主要功能是
- 给定图片的各个特征预测层,通过conv3x3滑动窗口,预测每个锚框的前景概率和回归参数
__init__
通过滑动窗口预测目标概率和bbox regression参数
forward
在多个特征层预测,把3x3conv作为滑动窗口生成预测结果.
AnchorsGenerator
AnchorsGenerator类的主要功能是
- 给定图片的各个特征层,在每个特征层上都生成特定大小和尺寸的锚框
__init__
处理anchor的sizes和ratios
forward
首先生成anchor模板,再获取每个特征图上的anchor在原图上的坐标信息.随后遍历每张图像,将所有anchor存入anchors中,anchors是list of list,第一个维度是不同图片,第二个维度是不同特征层.最后通过cat操作消除第二个维度,即把一个图片的不同特征图的anchor全部汇总起来.至此AnchorGenerator生成anchor的工作结束.
generate_anchors
生成anchors模板,首先拓展ratios和scales的维度并相乘(广播机制),获得不同尺度不同比例的anchor对应的宽和高,再将坐标摞起来,得到anchor模板的左上角(右下角)坐标.
cache_grid_anchors
对于anchor在原图上的位置信息做了一个cache缓存操作
grid_anchors
得到anchor模板在原图上的坐标信息,这里主要用到了meshgrid函数生成网格坐标,先生成特征图的每个像素中心点在原图上的坐标信息,再和anchor模板坐标相加即可(因为anchor模板默认中心点是(0,0))
BoxCoder
BoxCoder类主要工作是
- 已知两个Box计算regression回归参数
- 已知一个Box和regression计算回归后的Box
encode
根据anchor和对应的GTBox计算regression参数。这里先把所有图片的reference_boxes和proposals拼接在一起,最后返回的时候再根据每张图片的anchor个数分离,加快运算效率。
encode_single/encode_boxes
根据proposal坐标得到其宽高(ex_widths/ex_heights)和中心点坐标(ex_ctr_x/ex_ctr_y).同理计算GTBox的宽高和中心点.
最后计算四个回归参数dx/dy/dw/dh.参照以下公式.
decode
思路和encode
相反,参数为proposal和回归参数regresssion,计算最终的proposal坐标.
decode_single
思路与encode_single
相反.
计算公式如下.
Matcher
Matcher的主要功能是
- 将真实框分配给锚框,并划分正负样本
_call_
根据IoU矩阵为每个proposal分配真实框,并根据IoU大小划分正负样本.
BalancedPositiveNegativeSample
BalancedPositiveNegativeSample的主要功能:
- 随机采样正负样本,挑选指定比例的样本参与损失计算
__call__
call函数的参数是matched_idxs,数据类型是List of Tensor,List代表不同图像,Tensor代表每幅图像中每个Proposals的正负样本类型,为-1时代表样本被忽略;为0时代表负样本;>0时代表正样本
首先通过条件过滤出正负样本的下标,再根据正样本的比例(positive_fraction)选取正负样本的数量.注意如果正/负样本不足时,需要采样所有正/负样本.
正负样本的随机采样使用randperm
函数,
最后根据选出的正负样本下标制作掩码并返回.
RegionProposalNetwork
RegionProposalNetwork类是RPN网络的主体,调用了Matcher/BoxCoder等类来完成RPN的功能
__init__
- 传入上文提到的两个类(anchor_generator和rpn_head).
- fg_iou_thresh和bg_iou_thresh是划分正负样本的阈值.
- positive_fraction是计算损失时正负样本比例
- pre_nms_top_n是每个特征层最后NMS留下的候选框个数,post_nms_top_n是所有特征层汇总后留下的候选框个数
- BoxCoder /Matcher/BalancedPositiveNegativeSample见前文
forward
首先将特征图丢入head中获得预测类别和边界框偏移的结果,再通过anchor_generator生成anchors.
接下来计算每个特征层上的anchors的数量,用于之后的过滤操作.
利用Box_coder的decode操作将pred_bbox_deltas应用在生成的anchors上,获得propoals的坐标信息,在这里做NMS操作.
最后为预测的proposal分配GTBox,并计算损失.
concat_box_prediction_layers
对box_cls和box_regression两个list中的每个预测特征层的预测信息的tensor排列顺序以及shape进行调整 -> [N, -1, C]
C是num_classes or 4(bbox regression)
permute_and_flatten
主要工作是交换维度,把C维度换到最后.利于之后计算损失.
filter_proposals
此方法调用topk方法过滤每个特征层的proposals.
首先用level变量存储不同特征层上的anchors索引信息(因为这个时候不同特征层的anchor在之前的处理中存储在一起了,这里需要用level来区分不同的特征层anchor)
随后调用_get_top_n_idx
获取每层特征图中预测概率排前pre_nms_top_n的anchor的索引值,存入top_n_idx.利用双重索引获得这些anchor的objectness和proposal.
最后过滤得到的proposal对应的objectness记得做一次sigmod~
最后对于过滤的proposals进行边缘的裁剪,并去除小概率的proposal.最后再按照不同次执行一次batch_nms.
batch_nms是按照某个类别/预测层分别执行nms,当然底层实现更加高效.具体见下文
clip_boxes_to_image
利用clamp函数将边界框限制在图片范围内
remove_small_boxes
过滤宽高不满足条件的proposal
batch_nms
为了高效实现不同类别分别做NMS,首先为不同的类别生成一个足够大的offset,保证不同类别之间的boxes不会重叠,从而保证了在各自类别内做NMS的效果.
assign_targets_to_anchors
将真实框分配给锚框,并划分正负样本.主要使用proposal_matcher来实现匹配.具体方法见Matcher类实现.
compute_loss
首先通过BalancedPositiveNegativeSampler类选择正负样本,并将正负样本的索引拼接在一起,用来计算目标预测损失.
随后计算正样本的边界框回归损失(smooth_L1_Loss)和所有样本的物体预测损失(BCE_Loss)