Tensorflow版Faster RCNN源码解析(TFFRCNN) (03) bbox_transform.py
本blog为github上CharlesShang/TFFRCNN版源码解析系列代码笔记
---------------个人学习笔记---------------
----------------本文作者疆--------------
------点击此处链接至博客园原文------
1.Faster RCNN中RPN中预测的bbox_pred坐标补偿量说明(RCNN subnet中预测的补偿量是同样的形式,这种预测形式最初由RCNN中提出)
回归预测直接预测坐标很难,而预测一种转换则比较容易,回归预测的补偿量为(tx,ty,tw,th),对应gt标签为(tx*,ty*,tw*,th*),由式(2)第一行、第二行在(测试阶段)有如下关系:
(x,y,w,h)分别为回归后box的中心点横坐标、纵坐标、宽和高,(xa,ya,wa,ha)为未回归前的box的中心点横坐标、纵坐标、宽和高。
2.bbox_transform_inv(boxes,deltas))返回pred_boxes的回归过程
boxes的shape为(R2,4),deltas的shape为(R2,n_classes*4),返回的pred_boxes的shape与deltas相同,即(R2,n_classes*4),表明每一个box均向各类回归。
被train.py和test.py等调用
def bbox_transform_inv(boxes, deltas): if boxes.shape[0] == 0: return np.zeros((0, deltas.shape[1]), dtype=deltas.dtype) boxes = boxes.astype(deltas.dtype, copy=False) widths = boxes[:, 2] - boxes[:, 0] + 1.0 # wa heights = boxes[:, 3] - boxes[:, 1] + 1.0 # ha ctr_x = boxes[:, 0] + 0.5 * widths # xa ctr_y = boxes[:, 1] + 0.5 * heights # ya dx = deltas[:, 0::4] # tx 以4为步长 dy = deltas[:, 1::4] # ty dw = deltas[:, 2::4] # tw dh = deltas[:, 3::4] # th pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis] pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis] pred_w = np.exp(dw) * widths[:, np.newaxis] # 以e为底的指数函数 pred_h = np.exp(dh) * heights[:, np.newaxis] pred_boxes = np.zeros(deltas.shape, dtype=deltas.dtype) # pred_boxes与deltas的shape相同 # x1 pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w # y1 pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h # x2 pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w # y2 pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h return pred_boxes
# -*- coding:utf-8 -*- # Author: WUJiang # 测试功能 import numpy as np deltas = np.array([ [0, 1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 4, 5, 6, 7, 8, 9] ]) """ [[0 4] [1 5] [2 6]] """ dx = deltas[:, 0::4] # 第二维以4为步长 print(dx)
2.其他函数
clip_boxes(boxes, im_shape) 将越界的box限制为图像边界,test.py中也定义了该函数,被rpn/msr proposal_layer_tf.py中proposal_layer(...)调用
def clip_boxes(boxes, im_shape): """ Clip boxes to image boundaries. """
bbox_transform(ex_rois, gt_rois)由RCNN subnet中(训练时)未回归前的ex_rois和真实的gt_rois计算回归补偿量的gt值tx*、ty*、tw*、th*(见式子(2)第三行、第四行) (暂未见调用,猜测在训练中被调用)
def bbox_transform(ex_rois, gt_rois): # 由RCNN subnet中(训练时)未回归前的ex_rois和真实的gt_rois计算回归补偿量的gt值tx*、ty*、tw*、th* """ computes the distance from ground-truth boxes to the given boxes, normed by their size :param ex_rois: n * 4 numpy array, given boxes :param gt_rois: n * 4 numpy array, ground-truth boxes :return: deltas: n * 4 numpy array, ground-truth boxes """ ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + 1.0 # wa ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + 1.0 # ha ex_ctr_x = ex_rois[:, 0] + 0.5 * ex_widths # xa ex_ctr_y = ex_rois[:, 1] + 0.5 * ex_heights # ya assert np.min(ex_widths) > 0.1 and np.min(ex_heights) > 0.1, \ 'Invalid boxes found: {} {}'. \ format(ex_rois[np.argmin(ex_widths), :], ex_rois[np.argmin(ex_heights), :]) gt_widths = gt_rois[:, 2] - gt_rois[:, 0] + 1.0 # w* gt_heights = gt_rois[:, 3] - gt_rois[:, 1] + 1.0 # h* gt_ctr_x = gt_rois[:, 0] + 0.5 * gt_widths # x* gt_ctr_y = gt_rois[:, 1] + 0.5 * gt_heights # y* # warnings.catch_warnings() # warnings.filterwarnings('error') targets_dx = (gt_ctr_x - ex_ctr_x) / ex_widths # tx* targets_dy = (gt_ctr_y - ex_ctr_y) / ex_heights # ty* targets_dw = np.log(gt_widths / ex_widths) # tw* targets_dh = np.log(gt_heights / ex_heights) # th* targets = np.vstack( (targets_dx, targets_dy, targets_dw, targets_dh)).transpose() return targets
# -*- coding:utf-8 -*- # Author: WUJiang # 测试功能 import numpy as np a = np.array([ [0, 1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 4, 5, 6, 7, 8, 9] ]) """ [[0 1 2] [1 2 3] [2 3 4] [3 4 5] [4 5 6] [5 6 7] [6 7 8] [7 8 9]] """ print(a.transpose()) # 转置