def anchor_target_layer(rpn_cls_score, gt_boxes, gt_ishard, dontcare_areas,
                            im_info, _feat_stride, anchor_scales):
        """
        rpn_cls_score: for pytorch (1, Ax2, H, W) bg/fg scores of previous conv layer
        gt_boxes: (G, 5) vstack of [x1, y1, x2, y2, class]
        gt_ishard: (G, 1), 1 or 0 indicates difficult or not
        dontcare_areas: (D, 4), some areas may contains small objs but no labelling. D may be 0
        im_info: a list of [image_height, image_width, scale_ratios]
        _feat_stride: the downsampling ratio of feature map to the original input image
        anchor_scales: the scales to the basic_anchor (basic anchor is [16, 16])
        ----------
        Returns
        ----------
        rpn_labels : (1, 1, HxA, W), for each anchor, 0 denotes bg, 1 fg, -1 dontcare
        rpn_bbox_targets: (1, 4xA, H, W), distances of the anchors to the gt_boxes(may contains some transform)
                        that are the regression objectives
        rpn_bbox_inside_weights: (1, 4xA, H, W) weights of each boxes, mainly accepts hyper param in cfg
        rpn_bbox_outside_weights: (1, 4xA, H, W) used to balance the fg/bg,
        beacuse the numbers of bgs and fgs mays significiantly different
        """
        rpn_cls_score = rpn_cls_score.data.cpu().numpy()
        rpn_labels, rpn_bbox_targets, rpn_bbox_inside_weights, rpn_bbox_outside_weights = \
            anchor_target_layer_py(rpn_cls_score, gt_boxes, gt_ishard, dontcare_areas, im_info, _feat_stride, anchor_scales)

        rpn_labels = network.np_to_variable(rpn_labels,
                                            is_cuda=True,
                                            dtype=torch.LongTensor)
        rpn_bbox_targets = network.np_to_variable(rpn_bbox_targets,
                                                  is_cuda=True)
        rpn_bbox_inside_weights = network.np_to_variable(
            rpn_bbox_inside_weights, is_cuda=True)
        rpn_bbox_outside_weights = network.np_to_variable(
            rpn_bbox_outside_weights, is_cuda=True)

        return rpn_labels, rpn_bbox_targets, rpn_bbox_inside_weights, rpn_bbox_outside_weights
    def __init__(self, debug=False):
        super(RPN, self).__init__()

        self.anchor_scales = cfg.ANCHOR_SCALES
        self.anchor_ratios = cfg.ANCHOR_RATIOS
        self.feat_stride = cfg.FEAT_STRIDE[0]
        self._vgg16 = VGG16()
        self.conv1 = Conv2d(512, 512, 3, same_padding=True)
        self.score_conv = Conv2d(512,
                                 len(self.anchor_scales) *
                                 len(self.anchor_ratios) * 2,
                                 1,
                                 relu=False,
                                 same_padding=False)
        self.bbox_conv = Conv2d(512,
                                len(self.anchor_scales) *
                                len(self.anchor_ratios) * 4,
                                1,
                                relu=False,
                                same_padding=False)

        # define proposal layer
        self.proposal_layer = proposal_layer_py(self.feat_stride,
                                                self.anchor_scales,
                                                self.anchor_ratios)

        # define anchor target layer
        self.anchor_target_layer = anchor_target_layer_py(
            self.feat_stride, self.anchor_scales, self.anchor_ratios)

        # loss
        self.cross_entropy = 0
        self.loss_box = 0

        # for log
        self.debug = debug