def ga_loc_targets(self, gt_bboxes_list, featmap_sizes):
        """Compute location targets for guided anchoring.

        Each feature map is divided into positive, negative and ignore regions.
        - positive regions: target 1, weight 1
        - ignore regions: target 0, weight 0
        - negative regions: target 0, weight 0.1

        Args:
            gt_bboxes_list (list[Tensor]): Gt bboxes of each image.
            featmap_sizes (list[tuple]): Multi level sizes of each feature
                maps.

        Returns:
            tuple
        """
        anchor_scale = self.approx_anchor_generator.octave_base_scale
        anchor_strides = self.approx_anchor_generator.strides
        # Currently only supports same stride in x and y direction.
        for stride in anchor_strides:
            assert (stride[0] == stride[1])
        anchor_strides = [stride[0] for stride in anchor_strides]

        center_ratio = self.train_cfg.center_ratio
        ignore_ratio = self.train_cfg.ignore_ratio
        img_per_gpu = len(gt_bboxes_list)
        num_lvls = len(featmap_sizes)
        r1 = (1 - center_ratio) / 2
        r2 = (1 - ignore_ratio) / 2
        all_loc_targets = []
        all_loc_weights = []
        all_ignore_map = []
        for lvl_id in range(num_lvls):
            h, w = featmap_sizes[lvl_id]
            loc_targets = torch.zeros(
                img_per_gpu,
                1,
                h,
                w,
                device=gt_bboxes_list[0].device,
                dtype=torch.float32)
            loc_weights = torch.full_like(loc_targets, -1)
            ignore_map = torch.zeros_like(loc_targets)
            all_loc_targets.append(loc_targets)
            all_loc_weights.append(loc_weights)
            all_ignore_map.append(ignore_map)
        for img_id in range(img_per_gpu):
            gt_bboxes = gt_bboxes_list[img_id]
            scale = torch.sqrt((gt_bboxes[:, 2] - gt_bboxes[:, 0]) *
                               (gt_bboxes[:, 3] - gt_bboxes[:, 1]))
            min_anchor_size = scale.new_full(
                (1, ), float(anchor_scale * anchor_strides[0]))
            # assign gt bboxes to different feature levels w.r.t. their scales
            target_lvls = torch.floor(
                torch.log2(scale) - torch.log2(min_anchor_size) + 0.5)
            target_lvls = target_lvls.clamp(min=0, max=num_lvls - 1).long()
            for gt_id in range(gt_bboxes.size(0)):
                lvl = target_lvls[gt_id].item()
                # rescaled to corresponding feature map
                gt_ = gt_bboxes[gt_id, :4] / anchor_strides[lvl]
                # calculate ignore regions
                ignore_x1, ignore_y1, ignore_x2, ignore_y2 = calc_region(
                    gt_, r2, featmap_sizes[lvl])
                # calculate positive (center) regions
                ctr_x1, ctr_y1, ctr_x2, ctr_y2 = calc_region(
                    gt_, r1, featmap_sizes[lvl])
                all_loc_targets[lvl][img_id, 0, ctr_y1:ctr_y2 + 1,
                                     ctr_x1:ctr_x2 + 1] = 1
                all_loc_weights[lvl][img_id, 0, ignore_y1:ignore_y2 + 1,
                                     ignore_x1:ignore_x2 + 1] = 0
                all_loc_weights[lvl][img_id, 0, ctr_y1:ctr_y2 + 1,
                                     ctr_x1:ctr_x2 + 1] = 1
                # calculate ignore map on nearby low level feature
                if lvl > 0:
                    d_lvl = lvl - 1
                    # rescaled to corresponding feature map
                    gt_ = gt_bboxes[gt_id, :4] / anchor_strides[d_lvl]
                    ignore_x1, ignore_y1, ignore_x2, ignore_y2 = calc_region(
                        gt_, r2, featmap_sizes[d_lvl])
                    all_ignore_map[d_lvl][img_id, 0, ignore_y1:ignore_y2 + 1,
                                          ignore_x1:ignore_x2 + 1] = 1
                # calculate ignore map on nearby high level feature
                if lvl < num_lvls - 1:
                    u_lvl = lvl + 1
                    # rescaled to corresponding feature map
                    gt_ = gt_bboxes[gt_id, :4] / anchor_strides[u_lvl]
                    ignore_x1, ignore_y1, ignore_x2, ignore_y2 = calc_region(
                        gt_, r2, featmap_sizes[u_lvl])
                    all_ignore_map[u_lvl][img_id, 0, ignore_y1:ignore_y2 + 1,
                                          ignore_x1:ignore_x2 + 1] = 1
        for lvl_id in range(num_lvls):
            # ignore negative regions w.r.t. ignore map
            all_loc_weights[lvl_id][(all_loc_weights[lvl_id] < 0)
                                    & (all_ignore_map[lvl_id] > 0)] = 0
            # set negative regions with weight 0.1
            all_loc_weights[lvl_id][all_loc_weights[lvl_id] < 0] = 0.1
        # loc average factor to balance loss
        loc_avg_factor = sum(
            [t.size(0) * t.size(-1) * t.size(-2)
             for t in all_loc_targets]) / 200
        return all_loc_targets, all_loc_weights, loc_avg_factor
Пример #2
0
    def target_single_image(self, gt_boxes, gt_labels, feat_shape):
        """

        Args:
            gt_boxes: tensor, tensor <=> img, (num_gt, 4).
            gt_labels: tensor, tensor <=> img, (num_gt,).
            feat_shape: tuple.

        Returns:
            heatmap: tensor, tensor <=> img, (80, h, w).
            box_target: tensor, tensor <=> img, (4, h, w) or (80 * 4, h, w).
            reg_weight: tensor, same as box_target
        """
        output_h, output_w = feat_shape
        heatmap_channel = self.num_fg
        # gt_boxes,  gt_labels= self.FilerBbox(gt_boxes, gt_labels, output_h*output_w)
        # if gt_boxes:
        #     gt_boxes = torch.stack(gt_boxes, dim=0)
        #
        # if gt_labels:
        #     gt_labels = torch.stack(gt_labels, dim=0)


        heatmap = torch.zeros((heatmap_channel, output_h, output_w)).cuda()
        fake_heatmap = torch.zeros((output_h, output_w)).cuda()
        box_target = torch.ones((self.wh_planes, output_h, output_w)).cuda() * -1
        reg_weight = torch.zeros((self.wh_planes // 4, output_h, output_w)).cuda()
        try:
            if self.wh_area_process == 'log':
                boxes_areas_log = self.bbox_areas(gt_boxes).log()
            elif self.wh_area_process == 'sqrt':
                boxes_areas_log = self.bbox_areas(gt_boxes).sqrt()
            else:
                boxes_areas_log = self.bbox_areas(gt_boxes)
            boxes_area_topk_log, boxes_ind = torch.topk(boxes_areas_log, boxes_areas_log.size(0))

            if self.wh_area_process == 'norm':
                boxes_area_topk_log[:] = 1.

            gt_boxes = gt_boxes[boxes_ind]
            gt_labels = gt_labels[boxes_ind]

            feat_gt_boxes = gt_boxes / self.down_ratio
            feat_gt_boxes[:, [0, 2]] = torch.clamp(feat_gt_boxes[:, [0, 2]], min=0,
                                                   max=output_w - 1)
            feat_gt_boxes[:, [1, 3]] = torch.clamp(feat_gt_boxes[:, [1, 3]], min=0,
                                                   max=output_h - 1)
            feat_hs, feat_ws = (feat_gt_boxes[:, 3] - feat_gt_boxes[:, 1],
                                feat_gt_boxes[:, 2] - feat_gt_boxes[:, 0])

            # we calc the center and ignore area based on the gt-boxes of the origin scale
            # no peak will fall between pixels
            ct_ints = (torch.stack([(gt_boxes[:, 0] + gt_boxes[:, 2]) / 2,
                                    (gt_boxes[:, 1] + gt_boxes[:, 3]) / 2],
                                   dim=1) / self.down_ratio).to(torch.int)

            h_radiuses_alpha = (feat_hs / 2. * self.alpha).int()
            w_radiuses_alpha = (feat_ws / 2. * self.alpha).int()
            if self.wh_gaussian and self.alpha != self.beta:
                h_radiuses_beta = (feat_hs / 2. * self.beta).int()
                w_radiuses_beta = (feat_ws / 2. * self.beta).int()

            if not self.wh_gaussian:
                # calculate positive (center) regions
                r1 = (1 - self.beta) / 2
                ctr_x1s, ctr_y1s, ctr_x2s, ctr_y2s = calc_region(gt_boxes.transpose(0, 1), r1)
                ctr_x1s, ctr_y1s, ctr_x2s, ctr_y2s = [torch.round(x.float() / self.down_ratio).int()
                                                      for x in [ctr_x1s, ctr_y1s, ctr_x2s, ctr_y2s]]
                ctr_x1s, ctr_x2s = [torch.clamp(x, max=output_w - 1) for x in [ctr_x1s, ctr_x2s]]
                ctr_y1s, ctr_y2s = [torch.clamp(y, max=output_h - 1) for y in [ctr_y1s, ctr_y2s]]

            # larger boxes have lower priority than small boxes.
            for k in range(boxes_ind.shape[0]):
                cls_id = gt_labels[k] - 1

                fake_heatmap = fake_heatmap.zero_()
                self.draw_truncate_gaussian(fake_heatmap, ct_ints[k],
                                            h_radiuses_alpha[k].item(), w_radiuses_alpha[k].item())
                heatmap[cls_id] = torch.max(heatmap[cls_id], fake_heatmap)

                if self.wh_gaussian:
                    if self.alpha != self.beta:
                        fake_heatmap = fake_heatmap.zero_()
                        self.draw_truncate_gaussian(fake_heatmap, ct_ints[k],
                                                    h_radiuses_beta[k].item(),
                                                    w_radiuses_beta[k].item())
                    box_target_inds = fake_heatmap > 0
                else:
                    ctr_x1, ctr_y1, ctr_x2, ctr_y2 = ctr_x1s[k], ctr_y1s[k], ctr_x2s[k], ctr_y2s[k]
                    box_target_inds = torch.zeros_like(fake_heatmap, dtype=torch.uint8)
                    box_target_inds[ctr_y1:ctr_y2 + 1, ctr_x1:ctr_x2 + 1] = 1

                if self.wh_agnostic:
                    box_target[:, box_target_inds] = gt_boxes[k][:, None]
                    cls_id = 0
                else:
                    box_target[(cls_id * 4):((cls_id + 1) * 4), box_target_inds] = gt_boxes[k][:, None]

                if self.wh_gaussian:
                    local_heatmap = fake_heatmap[box_target_inds]
                    ct_div = local_heatmap.sum()
                    local_heatmap *= boxes_area_topk_log[k]
                    reg_weight[cls_id, box_target_inds] = local_heatmap / ct_div
                else:
                    reg_weight[cls_id, box_target_inds] = \
                        boxes_area_topk_log[k] / box_target_inds.sum().float()
        except:
            # print("There is no big target")
            pass
        return heatmap, box_target, reg_weight