コード例 #1
0
    def match_targets_to_proposals(self, proposal, target):
        match_quality_matrix = boxlist_iou_3d(target,
                                              proposal,
                                              aug_thickness=self.aug_thickness,
                                              criterion=-1,
                                              flag='roi_label_generation')
        matched_idxs = self.proposal_matcher(match_quality_matrix,
                                             yaw_diff=None,
                                             flag='ROI')
        # Fast RCNN only need "labels" field for selecting the targets
        target = target.copy_with_fields("labels")
        # get the targets corresponding GT for each proposal
        # NB: need to clamp the indices because we can have a single
        # GT in the image, and matched_idxs can be -2, which goes
        # out of bounds
        matched_targets = target[matched_idxs.clamp(min=0)]
        matched_targets.add_field("matched_idxs", matched_idxs)

        if CHECK_IOU:
            num_gt = len(target)
            if not torch.all(
                    matched_idxs[-num_gt:].cpu() == torch.arange(num_gt)):
                ious = match_quality_matrix[:, -num_gt:].diag()
                err_inds = torch.nonzero(
                    torch.abs(ious - 1) > 1e-5).view(-1) - len(ious)
                print(f"IOU error: \n{ious}")
                err_targets = target[err_inds]
                ious__ = boxlist_iou_3d(err_targets, err_targets, 0)
                print(err_targets.bbox3d)
                import pdb
                pdb.set_trace()  # XXX BREAKPOINT
                assert False
                pass
        return matched_targets
コード例 #2
0
 def match_targets_to_proposals(self, proposal, target):
     match_quality_matrix = boxlist_iou_3d(target, proposal)
     matched_idxs = self.proposal_matcher(match_quality_matrix)
     # Mask RCNN needs "labels" and "masks "fields for creating the targets
     target = target.copy_with_fields(["labels", "masks"])
     # get the targets corresponding GT for each proposal
     # NB: need to clamp the indices because we can have a single
     # GT in the image, and matched_idxs can be -2, which goes
     # out of bounds
     matched_targets = target[matched_idxs.clamp(min=0)]
     matched_targets.add_field("matched_idxs", matched_idxs)
     return matched_targets
コード例 #3
0
ファイル: loss_3d.py プロジェクト: picwoon/Detection_3D
    def match_targets_to_anchors(self, anchor, target):
        from utils3d.geometric_torch import angle_dif
        if target.bbox3d.shape[0] == 0:
            matched_idxs = torch.ones([anchor.bbox3d.shape[0]],
                                      dtype=torch.int64,
                                      device=anchor.bbox3d.device) * (-1)
            matched_targets = anchor
        else:
            match_quality_matrix = boxlist_iou_3d(
                target,
                anchor,
                aug_thickness=self.aug_thickness,
                criterion=2,
                flag='rpn_label_generation')
            yaw_diff = angle_dif(anchor.bbox3d[:, -1].view(1, -1),
                                 target.bbox3d[:, -1].view(-1, 1), 0)
            yaw_diff = torch.abs(yaw_diff)
            cendis = anchor.bbox3d[:, 0:3].view(
                1, -1, 3) - target.bbox3d[:, 0:3].view(-1, 1, 3)
            cendis = cendis.norm(dim=2)
            matched_idxs = self.proposal_matcher(match_quality_matrix,
                                                 yaw_diff=yaw_diff,
                                                 flag='RPN',
                                                 cendis=cendis)
            #anchor.show__together(target, 200)
            # RPN doesn't need any fields from target
            # for creating the labels, so clear them all
            target = target.copy()
            # get the targets corresponding GT for each anchor
            # NB: need to clamp the indices because we can have a single
            # GT in the image, and matched_idxs can be -2, which goes
            # out of bounds
            matched_targets = target[matched_idxs.clamp(min=0)]
        matched_targets.add_field("matched_idxs", matched_idxs)

        if SHOW_POS_NEG_ANCHORS:
            self.matched_idxs = matched_idxs
            self.matched_iou = match_quality_matrix.max(0)[0]

        if SHOW_IGNORED_ANCHOR:
            sampled_ign_inds = torch.nonzero(matched_idxs == -2).squeeze(1)
            anchors_ign = anchor[sampled_ign_inds]
            ignored_iou = match_quality_matrix.max(0)[0][sampled_ign_inds]
            print(f'\n ignore {len(anchors_ign)} anchors')
            print(f'\n ignore ious:\n{ignored_iou}')
            anchors_ign.show__together(target)
            #for i in range(0, len(anchors_ign), 3):
            #  ids_ign = [j for j in range(i, i+3)]
            #  print(f'iou: {ignored_iou[ids_ign]}')
            #  anchors_ign[ids_ign].show__together(target)
            pass

        if CHECK_MATCHER and target.bbox3d.shape[0] > 0:
            check_matcher(target, anchor, match_quality_matrix, matched_idxs,
                          self.dset_metas)

        if SHOW_POS_ANCHOR_IOU_SAME_LOC:
            num_gt = target.bbox3d.shape[0]
            for j in range(num_gt):
                sampled_pos_inds = torch.nonzero(matched_idxs == j).squeeze(1)
                inds_same_loc = anchor.same_loc_anchors(sampled_pos_inds)
                matched_idxs_same_loc = matched_idxs[inds_same_loc]

                # all the ious for gt box j
                iou_j = match_quality_matrix[j][sampled_pos_inds]
                anchors_pos_j = anchor[sampled_pos_inds]
                print(
                    f'\n{iou_j.shape[0]} anchor matched as positive. All anchor centroids are shown.'
                )
                print(f'ious:{iou_j}\n')
                anchors_pos_j.show__together(target[j],
                                             points=anchor.bbox3d[:, 0:3])

                for i in range(iou_j.shape[0]):

                    print(f'\n{i}th pos anchor for gt box j\n iou: {iou_j[i]}')
                    #anchors_pos_j[i].show__together(target[j])

                    ious_same_loc = match_quality_matrix[j][inds_same_loc[i]]
                    yaw_diff_same_loc = yaw_diff[j, inds_same_loc[i]]
                    print(
                        f'\nall same loc anchors \nious:{ious_same_loc}\nmatched_idxs:{matched_idxs_same_loc[i]}\nyaw_diff:{yaw_diff_same_loc}'
                    )
                    print(f'-1:low, -2:between')
                    anchors_same_loc_i = anchor[inds_same_loc[i]]
                    anchors_same_loc_i.show__together(target[j])
                    import pdb
                    pdb.set_trace()  # XXX BREAKPOINT
                    pass
                pass

        return matched_targets
コード例 #4
0
ファイル: suncg_eval.py プロジェクト: picwoon/Detection_3D
def calc_detection_suncg_prec_rec(gt_boxlists, pred_boxlists, iou_thresh,
                                  dset_metas, eval_aug_thickness):
    """Calculate precision and recall based on evaluation code of PASCAL VOC.
    This function calculates precision and recall of
    predicted bounding boxes obtained from a dataset which has :math:`N`
    images.
    The code is based on the evaluation code used in PASCAL VOC Challenge.
   """
    n_pos = defaultdict(int)
    score = defaultdict(list)
    # The pred having maximum iou with a gt is matched with the gt.
    # If multiple preds share same maximum iou gt, the one with highest score is
    # selected. NOTICE HERE, not the one with highest iou! Because, in test,
    # only score is available.
    match = defaultdict(list)  # 1:true, 0:false, -1:ignore
    predious = defaultdict(list)

    pred_for_each_gt = defaultdict(list)
    batch_size = len(gt_boxlists)

    bi = -1
    for gt_boxlist, pred_boxlist in zip(gt_boxlists, pred_boxlists):
        bi += 1
        pred_bbox = pred_boxlist.bbox3d.numpy()
        pred_label = pred_boxlist.get_field("labels").numpy()
        pred_score = pred_boxlist.get_field("scores").numpy()
        gt_bbox = gt_boxlist.bbox3d.numpy()
        gt_label = gt_boxlist.get_field("labels").numpy()

        for l in np.unique(np.concatenate((pred_label, gt_label)).astype(int)):
            obj_name = dset_metas.label_2_class[l]
            pred_mask_l = pred_label == l
            pred_ids_l = np.where(pred_mask_l)[0]
            pred_bbox_l = pred_bbox[pred_mask_l]
            pred_score_l = pred_score[pred_mask_l]
            # sort by score
            order = pred_score_l.argsort()[::-1]
            pred_bbox_l = pred_bbox_l[order]
            pred_score_l = pred_score_l[order]

            gt_mask_l = gt_label == l
            # Extract gt only of current class, thus gt_index is the index
            # inside of one signle class gts, not of all gts
            # TAG: GT_MASK
            gt_bbox_l = gt_bbox[gt_mask_l]

            n_pos[l] += gt_bbox_l.shape[0]
            score[l].extend(pred_score_l)

            if len(pred_bbox_l) == 0:
                continue
            if len(gt_bbox_l) == 0:
                match[l].extend((0, ) * pred_bbox_l.shape[0])
                predious[l].extend((0, ) * pred_bbox_l.shape[0])
                continue

            pred_bbox_l = pred_bbox_l.copy()
            gt_bbox_l = gt_bbox_l.copy()
            iou = boxlist_iou_3d(BoxList3D(gt_bbox_l, gt_boxlist.size3d,
                                           gt_boxlist.mode, None,
                                           gt_boxlist.constants),
                                 BoxList3D(pred_bbox_l, pred_boxlist.size3d,
                                           pred_boxlist.mode, None,
                                           pred_boxlist.constants),
                                 aug_thickness=eval_aug_thickness,
                                 criterion=-1,
                                 flag='eval').numpy()  # [gt_nm,pred_num]

            gt_index = iou.argmax(axis=0)  # the gt index for each predicion
            # set -1 if there is no matching ground truth
            gt_index[iou.max(axis=0) < iou_thresh] = -1
            pred_for_each_gt_l = defaultdict(list)
            neg_count = 0
            for pi in range(gt_index.shape[0]):
                pis = {
                    'pred_idx': pred_ids_l[pi],
                    'iou': iou[gt_index[pi], pi],
                    'score': score[l][pi]
                }
                gt_idx = gt_index[pi]
                if gt_idx < 0:
                    neg_count += 1
                    gt_idx -= (gt_idx == -1) * neg_count
                pred_for_each_gt_l[gt_idx].append(pis)

            if obj_name not in pred_for_each_gt:
                for iii in range(batch_size):
                    pred_for_each_gt[obj_name].append(defaultdict(list))
            pred_for_each_gt[obj_name][bi] = pred_for_each_gt_l

            predious[l].extend(iou.max(0))

            selec = np.zeros(gt_bbox_l.shape[0], dtype=bool)
            for gt_idx in gt_index:
                if gt_idx >= 0:
                    if not selec[gt_idx]:
                        # gt_index is already sorted by scores,
                        # thus the first pred match a gt box is set 1
                        match[l].append(1)
                    else:
                        match[l].append(0)
                    selec[gt_idx] = True
                else:
                    match[l].append(0)

            del iou
            pass

    n_fg_class = max(n_pos.keys()) + 1
    prec = [None] * n_fg_class
    rec = [None] * n_fg_class
    scores = [None] * n_fg_class
    pred_ious = [None] * n_fg_class

    for l in n_pos.keys():
        score_l = np.array(score[l])
        if score_l.shape[0] == 0:
            continue
        match_l = np.array(match[l], dtype=np.int8)

        order = score_l.argsort()[::-1]
        scores[l] = score_l[order]
        match_l = match_l[order]
        predious[l] = np.array(predious[l], dtype=np.float)
        if not predious[l].shape[0] == order.shape[0]:
            import pdb
            pdb.set_trace()  # XXX BREAKPOINT
            pass
        pred_ious[l] = predious[l][order]

        tp = np.cumsum(match_l == 1)
        fp = np.cumsum(match_l == 0)

        # If an element of fp + tp is 0,
        # the corresponding element of prec[l] is nan.
        prec[l] = tp / (fp + tp)
        # If n_pos[l] is 0, rec[l] is None.
        #if n_pos[l] > 0:
        rec[l] = tp / n_pos[l]

    #plt.plot(rec[1], label='rec')
    #plt.plot(prec[1], label='prec')
    #plt.plot(scores[1], label='score')
    #plt.legend()
    #plt.show()
    return prec, rec, pred_for_each_gt, scores, pred_ious
コード例 #5
0
def calc_detection_suncg_prec_rec(gt_boxlists, pred_boxlists, iou_thresh=0.5):
    """Calculate precision and recall based on evaluation code of PASCAL VOC.
    This function calculates precision and recall of
    predicted bounding boxes obtained from a dataset which has :math:`N`
    images.
    The code is based on the evaluation code used in PASCAL VOC Challenge.
   """
    n_pos = defaultdict(int)
    score = defaultdict(list)
    match = defaultdict(list)
    for gt_boxlist, pred_boxlist in zip(gt_boxlists, pred_boxlists):
        pred_bbox = pred_boxlist.bbox.numpy()
        pred_label = pred_boxlist.get_field("labels").numpy()
        pred_score = pred_boxlist.get_field("scores").numpy()
        gt_bbox = gt_boxlist.bbox.numpy()
        gt_label = gt_boxlist.get_field("labels").numpy()
        gt_difficult = gt_boxlist.get_field("difficult").numpy()

        for l in np.unique(np.concatenate((pred_label, gt_label)).astype(int)):
            pred_mask_l = pred_label == l
            pred_bbox_l = pred_bbox[pred_mask_l]
            pred_score_l = pred_score[pred_mask_l]
            # sort by score
            order = pred_score_l.argsort()[::-1]
            pred_bbox_l = pred_bbox_l[order]
            pred_score_l = pred_score_l[order]

            gt_mask_l = gt_label == l
            gt_bbox_l = gt_bbox[gt_mask_l]
            gt_difficult_l = gt_difficult[gt_mask_l]

            n_pos[l] += np.logical_not(gt_difficult_l).sum()
            score[l].extend(pred_score_l)

            if len(pred_bbox_l) == 0:
                continue
            if len(gt_bbox_l) == 0:
                match[l].extend((0, ) * pred_bbox_l.shape[0])
                continue

            # VOC evaluation follows integer typed bounding boxes.
            pred_bbox_l = pred_bbox_l.copy()
            pred_bbox_l[:, 2:] += 1
            gt_bbox_l = gt_bbox_l.copy()
            gt_bbox_l[:, 2:] += 1
            iou = boxlist_iou_3d(
                BoxList3D(pred_bbox_l, gt_boxlist.size),
                BoxList3D(gt_bbox_l, gt_boxlist.size),
            ).numpy()
            gt_index = iou.argmax(axis=1)
            # set -1 if there is no matching ground truth
            gt_index[iou.max(axis=1) < iou_thresh] = -1
            del iou

            selec = np.zeros(gt_bbox_l.shape[0], dtype=bool)
            for gt_idx in gt_index:
                if gt_idx >= 0:
                    if gt_difficult_l[gt_idx]:
                        match[l].append(-1)
                    else:
                        if not selec[gt_idx]:
                            match[l].append(1)
                        else:
                            match[l].append(0)
                    selec[gt_idx] = True
                else:
                    match[l].append(0)

    n_fg_class = max(n_pos.keys()) + 1
    prec = [None] * n_fg_class
    rec = [None] * n_fg_class

    for l in n_pos.keys():
        score_l = np.array(score[l])
        match_l = np.array(match[l], dtype=np.int8)

        order = score_l.argsort()[::-1]
        match_l = match_l[order]

        tp = np.cumsum(match_l == 1)
        fp = np.cumsum(match_l == 0)

        # If an element of fp + tp is 0,
        # the corresponding element of prec[l] is nan.
        prec[l] = tp / (fp + tp)
        # If n_pos[l] is 0, rec[l] is None.
        if n_pos[l] > 0:
            rec[l] = tp / n_pos[l]

    return prec, rec