Faster RCNN系列——RPN的真值详解

  RPN的真值分为类别真值偏移量真值,即每一个Anchor是否对应着真实物体,以及每一个Anchor对应物体的真实偏移值,这两种真值的具体求解过程如下图所示:

Faster RCNN系列——RPN的真值详解_第1张图片

  1. Anchor生成

  Anchor生成的具体过程可参考Faster RCNN系列——Anchor生成过程,可生成 37 × 50 × 9 = 16650 37×50×9=16650 37×50×9=16650个Anchors,这种方法对于靠近图像边缘的点来说,可能生成超出图像范围的Anchor,需要把这部分超过图像范围的Anchor过滤掉。

def forward(self, input):
	# 利用NumPy首先得到原图上的中心点坐标,并利用contiguous保证内存连续
	shifts = torch. from_numpy(np.vstack((shift_x.ravel(), shift__y.ravel(),
										  shift_x.rave1(), shift_y.rave1())).transpose())
	shifts = shifts.contiguous().type_as(rpn_cls_score) .float ()
	# 调用基础Anchor生成所有Anchors
	self.anchors = self.anchors.type_as(gt_boxes)
	all_ anchors = self. anchors.view(1, A, 4) + shifts.view(K, 1, 4)
	# 保留边框内的Anchors
	inds_inside = torch.nonzero(keep).view(-1)
	anchors = all_ anchors[inds_inside, :]
  1. 类别真值求解

  类别真值求解的详细过程可参考Faster RCNN系列——RPN的真值与预测值概述中类别真值的部分,需要注意的是,求解过程中的三个步骤的顺序不能变动,原因:

  • 保证一个Anchor既符合正样本,也符合负样本时,才会被赋予正样本。

  • 为了保证召回率,允许一个标签对应多个Anchor,不允许一个Anchor对应多个标签。

def forward(self, input):
	# 生成标签向量,对应每一个Anchor的状态,1为正,0为负,初始化为-1
	labels = gt_boxes.new(batch_size, inds_inside.size(0)).fill_(-1)
	# 生成IoU矩阵,每一行代表一个Anchor, 每一列代表一个标签
	overlaps = bbox_overlaps_batch(anchors, gt_boxes)
	# 对每一行求最大值,返回的第一个为最大值,第二个为最大值的位置
	max_overlaps, argmax_overlaps = torch.max(overlaps, 2)
	# 对每一列取最大值,返回的是每一个标签对应的IoU最大值
	gt_max_overlaps, _ = torch.max(overlaps, 1)
	# 如果一个Anchor最大的IoU小于0.3, 视为负样本
	labels[max_overlaps < 0.3] = 0
	#与所有Anchors的最大IoU为0的标签要过滤掉
	gt_ max_overlaps[gt_max_overlaps==0] = 1e-5
	# 将与标签有最大IoU的Anchor赋予正样本
	keep = torch.sum(overlaps.eq(gt_max_overlaps.view(batch_size, 1, -1).expand_as(overlaps)), 2)
	if torch.sum(keep)>0:
		labels[keep>0] = 1
	#  如果一个 Anchor最大的IoU大于0.7,视为正样本
	labels[max_overlaps >= 0.7] = 1
  1. Anchor的筛选

  由于Anchor的总数量接近于2万,并且大部分Anchor的标签都是背景,如果都计算损失的话则正、负样本失去了均衡,不利于网络的收敛。因此,RPN默认选择256个Anchors进行损失的计算,其中最多不超过128个的正样本。如果数量超过了限定值,则进行随机选取。当然,这里的256与128都可以根据实际情况进行调整,而不是固定死的。

def forward(self, input):
	......
	for i in range(batch_size):
	#如果正样本数量太多,则进行下采样随机选取
		if sum_fg[i] > 128 :
			fg_inds = torch.nonzero(labels[i] == 1).view(-1)
			rand_num = torch.from_numpy(np.random.permutation
			(fg_ inds.size(0))).type_as(gt_boxes).long()
			disable_inds = fg_inds[rand_num[:fg_inds.size(0)-num_fg]]
			labels[i][disable_inds] = -1
			# 负样本同上
			......
  1. 偏移量真值求解

  偏移量真值的求解过程可参考Faster RCNN系列——RPN的真值与预测值概述中偏移量真值的部分。

  得到偏移量的真值后,将其保存在bbox_ targets 中。与此同时,还需要求解两个权值矩阵bbox_inside_weights 和bbox_outside_weights,前者是用来设置正样本回归的权重,正样本设置为1,负样本设置为0,因为负样本对应的是背景,不需要进行回归;后者的作用则是平衡RPN分类损失与回归损失的权重,在此设置为1/256。

def forward(self, input):
	......
	# 选择每一个Anchor对应最大Iou的标签进行偏移计算
	bbox_targets = _compute_targets_batch(anchors, gt_ boxes.view(-1, 5)[argmax_overlaps.view(-1), :].view(batch_size, -1, 5))
	#设置两个权重向量
	bbox_inside_weights[labels==1] = 1
	num_examples = torch.sum(labels[i] >=0)
	bbox_outside_weights[labels == 1] = 1.0 / examples.item()
	bbox_outside_weights[labels == 0]=1.0 / examples.item()

你可能感兴趣的:(目标检测,深度学习,python,人工智能)