//  [python]
def refine_stage(self, input_img_batch, gtboxes_batch_r, gt_smooth_label, box_pred_list, cls_prob_list, proposal_list,
                     angle_cls_list, feature_pyramid, gpu_id, pos_threshold, neg_threshold,
                     stage, proposal_filter=False):
        with tf.variable_scope('refine_feature_pyramid{}'.format(stage)):
            refine_feature_pyramid = {}
            refine_boxes_list = []
            refine_boxes_angle_list = []

            for box_pred, cls_prob, proposal, angle_prob, stride, level in \
                    zip(box_pred_list, cls_prob_list, proposal_list, angle_cls_list,
                        cfgs.ANCHOR_STRIDE, cfgs.LEVEL):

                if proposal_filter:
                    box_pred = tf.reshape(box_pred, [-1, self.num_anchors_per_location, 5])
                    proposal = tf.reshape(proposal, [-1, self.num_anchors_per_location, 5 if self.method == 'R' else 4])
                    cls_prob = tf.reshape(cls_prob, [-1, self.num_anchors_per_location, cfgs.CLASS_NUM])

                    cls_max_prob = tf.reduce_max(cls_prob, axis=-1)
                    box_pred_argmax = tf.to_int32(tf.reshape(tf.argmax(cls_max_prob, axis=-1), [-1, 1]))
                    indices = tf.to_int32(tf.cumsum(tf.ones_like(box_pred_argmax), axis=0)) - tf.constant(1, tf.int32)
                    indices = tf.concat([indices, box_pred_argmax], axis=-1)

                    box_pred = tf.reshape(tf.gather_nd(box_pred, indices), [-1, 5])
                    proposal = tf.reshape(tf.gather_nd(proposal, indices), [-1, 5 if self.method == 'R' else 4])

                    if cfgs.METHOD == 'H':
                        x_c = (proposal[:, 2] + proposal[:, 0]) / 2
                        y_c = (proposal[:, 3] + proposal[:, 1]) / 2
                        h = proposal[:, 2] - proposal[:, 0] + 1
                        w = proposal[:, 3] - proposal[:, 1] + 1
                        theta = -90 * tf.ones_like(x_c)
                        proposal = tf.transpose(tf.stack([x_c, y_c, w, h, theta]))
                    if cfgs.ANGLE_RANGE == 180:
                        proposal = coordinate90_2_180_tf(proposal, is_radian=False, change_range=True)
                    # bboxes = bbox_transform.rbbox_transform_inv(boxes=proposal, deltas=box_pred)
                    # if cfgs.ANGLE_RANGE == 180:
                    #     bboxes = coordinate90_2_180_tf(bboxes, is_radian=False, change_range=True)
                else:
                    box_pred = tf.reshape(box_pred, [-1, 5])
                    proposal = tf.reshape(proposal, [-1, 5])

                bboxes = bbox_transform.rbbox_transform_inv(boxes=proposal, deltas=box_pred)

                # bboxes = tf.Print(bboxes, [bboxes], 'bboxes', summarize=50)

                if angle_prob is not None:
                    angle_cls = tf.to_int32(tf.argmax(tf.sigmoid(angle_prob), axis=1))
                    angle_cls = (tf.to_float(tf.reshape(angle_cls, [-1, ])) * -1 - 0.5) * cfgs.OMEGA
                    x, y, w, h, theta = tf.unstack(bboxes, axis=1)
                    bboxes_angle = tf.transpose(tf.stack([x, y, w, h, angle_cls]))
                    refine_boxes_angle_list.append(bboxes_angle)
                    center_point = bboxes_angle[:, :2] / stride
                else:
                    center_point = bboxes[:, :2] / stride
                refine_boxes_list.append(bboxes)

                refine_feature_pyramid[level] = self.refine_feature_op(points=center_point,
                                                                       feature_map=feature_pyramid[level],
                                                                       name=level)

            refine_box_pred_list, refine_cls_score_list, refine_cls_prob_list, refine_angle_cls_list = self.refine_net(
                refine_feature_pyramid,
                'refine_net{}'.format(stage))

            refine_box_pred = tf.concat(refine_box_pred_list, axis=0)
            refine_cls_score = tf.concat(refine_cls_score_list, axis=0)
            # refine_cls_prob = tf.concat(refine_cls_prob_list, axis=0)
            refine_boxes = tf.concat(refine_boxes_list, axis=0)
            refine_angle_cls = tf.concat(refine_angle_cls_list, axis=0)

        if self.is_training:
            with tf.variable_scope('build_refine_loss{}'.format(stage)):
                refine_labels, refine_target_delta, refine_box_states, refine_target_boxes, refine_target_smooth_label = tf.py_func(
                    func=refinebox_target_layer,
                    inp=[gtboxes_batch_r, gt_smooth_label, refine_boxes, pos_threshold, neg_threshold, gpu_id],
                    Tout=[tf.float32, tf.float32, tf.float32,
                          tf.float32, tf.float32])

                if cfgs.ANGLE_RANGE == 180:
                    refine_boxes_ = tf.py_func(coordinate_present_convert,
                                               inp=[refine_boxes, 1],
                                               Tout=[tf.float32])
                    refine_boxes_ = tf.reshape(refine_boxes_, [-1, 5])

                    self.add_anchor_img_smry(input_img_batch, refine_boxes_, refine_box_states, 1)
                else:
                    self.add_anchor_img_smry(input_img_batch, refine_boxes, refine_box_states, 1)

                refine_cls_loss = losses.focal_loss(refine_labels, refine_cls_score, refine_box_states)
                if cfgs.USE_IOU_FACTOR:
                    refine_reg_loss = losses.iou_smooth_l1_loss_(refine_target_delta, refine_box_pred,
                                                                 refine_box_states, refine_target_boxes,
                                                                 refine_boxes, is_refine=True)
                    # refine_reg_loss = losses.iou_smooth_l1_loss_1(refine_box_pred,
                    #                                               refine_box_states, refine_target_boxes,
                    #                                               refine_boxes, is_refine=True)
                else:
                    refine_reg_loss = losses.smooth_l1_loss(refine_target_delta, refine_box_pred, refine_box_states)

                angle_cls_loss = losses.angle_focal_loss(refine_target_smooth_label, refine_angle_cls, refine_box_states)

                self.losses_dict['refine_cls_loss{}'.format(stage)] = refine_cls_loss * cfgs.CLS_WEIGHT
                self.losses_dict['refine_reg_loss{}'.format(stage)] = refine_reg_loss * cfgs.REG_WEIGHT
                self.losses_dict['angle_cls_loss{}'.format(stage)] = angle_cls_loss * cfgs.ANGLE_CLS_WEIGHT

        return refine_box_pred_list, refine_cls_prob_list, refine_boxes_list, refine_angle_cls_list