Exemple #1
0
 def prec_recall(self, that, th=0.5):
     none = torch.zeros((0,6))
     bgt = torch.from_numpy(self.dets).float()
     bpd = torch.from_numpy(that.dets).float()
     
     overlaps = jaccard(bgt[:,2:], bpd[:,2:])
     overlaps[overlaps<th] = 0
     best_prior_overlap, best_prior_idx = overlaps.max(1)
     best_prior_idx = best_prior_idx.squeeze()
 
     tp_gt = torch.nonzero(best_prior_idx)
     if tp_gt.nelement() == 0: return 0, 0, (none, none, bgt, bpd)
     tp_gt_boxes = bgt.index_select(0,tp_gt.squeeze())
 
     tp_pd = torch.index_select(best_prior_idx, 0, tp_gt.squeeze())
     tp_pd_boxes = bpd.index_select(0,tp_pd.squeeze())
 
     fn = torch.nonzero(best_prior_idx==0)
     if fn.nelement() == 0: fn_boxes = none
     else :fn_boxes = bgt.index_select(0,fn.squeeze())
 
     fp = torch.ones((len(bpd))).cpu()
     fp = fp.index_fill_(0,tp_pd,0).nonzero()
     if fp.nelement() == 0: fp_boxes = none
     else: fp_boxes = bpd.index_select(0,fp.squeeze())
     prec = len(tp_pd)/(len(tp_pd)+len(fp))
     recall = len(tp_gt)/(len(tp_gt)+len(fn))
 
     return prec, recall, (tp_gt_boxes, tp_pd_boxes, fn_boxes, fp_boxes)
Exemple #2
0
def match_dis(othreshold, cthreshold, prevs_loc, prevs_conf, truths_loc, truths_cls, loc_match, cls_match, mask, idx):
    """
    args
        othreshold: overlap threshold
        cthreshold: conf threshold
        prevs_loc: tensor [num_prevs, 4]
        prevs_conf: tensor [num_prevs]
        truths_loc: tensor [num_objs, 4]
        truths_cls: tensor [num_objs]
        loc_match: to be filled [batch, num_pres, 4]
        cls_match: to be filled [batch, num_pres]
        mask : to be filled [batch, num_pres]
        idx : current batch index
        count: num of good prevs
    return
        none
    """
    overlaps = jaccard(truths_loc, prevs_loc)  # [num_objs, num_prevs]
    # print('overlap',overlaps)

    best_truth_overlap, best_truth_idx = overlaps.max(0, keepdim=True)
    best_truth_idx.squeeze_(0)  # [num_prevs] 每个prev最大overlap的obj序号
    best_truth_overlap.squeeze_(0)  # 每个prev的最大overlap
    # print('best',best_truth_idx)
    # print('xiaocl',cls_match[idx])

    # for i in range(cls_match.size(1)):
    #     cls_match[idx,i] = truths_cls[int(best_truth_idx[i])]  # [num_prevs] 每个prev匹配obj的cls
    cls_match[idx] = truths_cls[best_truth_idx]
    # print('houcl',cls_match[idx])
    loc_match[idx] = truths_loc[best_truth_idx, :]  # [num_prevs, 4] 每个prev匹配obj的loc

    mask[idx][best_truth_overlap < othreshold] = 0
    mask[idx][prevs_conf < cthreshold] = 0
Exemple #3
0
    def fast_nms(self,
                 boxes,
                 masks,
                 scores,
                 iou_threshold: float = 0.5,
                 top_k: int = 200,
                 second_threshold: bool = False):
        #sorted with the 1th dim
        scores, idx = scores.sort(1, descending=True)

        idx = idx[:, :top_k].contiguous()
        scores = scores[:, :top_k]
        #80
        num_classes, num_dets = idx.size()

        boxes = boxes[idx.view(-1), :].view(num_classes, num_dets, 4)
        masks = masks[idx.view(-1), :].view(num_classes, num_dets, -1)

        iou = jaccard(boxes, boxes)
        #iou 80 x top_k x top_k
        iou.triu_(diagonal=1)
        #https://blog.csdn.net/Z_lbj/article/details/79766690
        iou_max, _ = iou.max(dim=1)

        # Now just filter out the ones higher than the threshold
        keep = (iou_max <= iou_threshold)

        # We should also only keep detections over the confidence threshold, but at the cost of
        # maxing out your detection count for every image, you can just not do that. Because we
        # have such a minimal amount of computation per detection (matrix mulitplication only),
        # this increase doesn't affect us much (+0.2 mAP for 34 -> 33 fps), so we leave it out.
        # However, when you implement this in your method, you should do this second threshold.
        # TODO:: above
        if second_threshold:
            keep *= (scores > self.conf_thresh)

        # Assign each kept detection to its corresponding class
        #https://blog.csdn.net/m0_37586991/article/details/88830026
        classes_t = torch.arange(num_classes,
                                 device=boxes.device)[:, None].expand_as(keep)
        #tensor([[ 0,  0,  0,  ...,  0,  0,  0],
        #        [ 1,  1,  1,  ...,  1,  1,  1],
        #        [ 2,  2,  2,  ...,  2,  2,  2],
        classes = classes_t[keep]

        boxes = boxes[keep]
        masks = masks[keep]
        scores = scores[keep]

        # Only keep the top cfg.max_num_detections highest scores across all classes
        scores, idx = scores.sort(0, descending=True)
        idx = idx[:cfg.max_num_detections]
        scores = scores[:cfg.max_num_detections]

        classes = classes[idx]
        boxes = boxes[idx]
        masks = masks[idx]

        return boxes, masks, classes, scores
def prec_recall(gt_dets, pd_dets, th=0.5, filter_pups=False):
    if filter_pups:
        #print("gt_dets",gt_dets.shape)
        gt_dets = gt_dets[gt_dets[:, 0] != 4]
        #print("gt_dets",gt_dets.shape)
        pd_dets = pd_dets[pd_dets[:, 0] != 4]
    bgt = torch.from_numpy(gt_dets).float()
    bpd = torch.from_numpy(pd_dets).float()
    overlaps = jaccard(bgt[:, 2:], bpd[:, 2:])
    overlaps[overlaps < th] = 0
    best_prior_overlap, best_prior_idx = overlaps.max(1)
    best_prior_idx = best_prior_idx.squeeze()

    tp_gt = torch.nonzero(best_prior_idx)
    if tp_gt.nelement() == 0:
        return 0, 0, ([], [], bgt, bpd)
    tp_gt_boxes = bgt.index_select(0, tp_gt.squeeze())

    tp_pd = torch.index_select(best_prior_idx, 0, tp_gt.squeeze())
    tp_pd_boxes = bpd.index_select(0, tp_pd.squeeze())

    fn = torch.nonzero(best_prior_idx == 0)
    if fn.nelement() == 0:
        fn_boxes = []
    else:
        fn_boxes = bgt.index_select(0, fn.squeeze())

    fp = torch.ones((len(bpd))).cpu()
    fp = fp.index_fill_(0, tp_pd, 0).nonzero()
    if fp.nelement() == 0:
        fp_boxes = []
    else:
        fp_boxes = bpd.index_select(0, fp.squeeze())
    prec = len(tp_pd) / (len(tp_pd) + len(fp))
    recall = len(tp_gt) / (len(tp_gt) + len(fn))
    #print("%.2f" % prec, "%.2f" % recall, len(tp_gt_boxes), len(fn_boxes), len(fp_boxes))
    return prec, recall, (tp_gt_boxes, tp_pd_boxes, fn_boxes, fp_boxes)
Exemple #5
0
def _bbox_iou(bbox1, bbox2, iscrowd=False):
    with timer.env('BBox IoU'):
        ret = jaccard(bbox1, bbox2, iscrowd)
    return ret
Exemple #6
0
def evaluate_detections(dataset, config):
    # Load all the detections.
    with open(ALL_DETECTIONS_FILEPATH, 'rb') as file:
        all_detections = pickle.load(file)
    num_images = len(dataset)
    num_classes = config.model.num_classes  # take the model num_classes, since we are omitting background
    classes_name = dataset.classes_name
    configs_dict = config.dict()

    # For each image, calculate
    # 1) the highest jaccard index for each ground truth.
    # 2) true positives and false positives/negatives for each class.
    true_pos = np.nan * np.zeros((num_images, num_classes))
    false_pos = np.nan * np.zeros((num_images, num_classes))
    false_neg = np.nan * np.zeros((num_images, num_classes))
    truepos_jaccard_mean = np.nan * np.zeros((num_images, num_classes))
    min_jaccard_overlap = 0.5
    gts_exist = False

    for i in range(num_images):
        image_objects_gt = dataset.get_gt(i)
        if image_objects_gt.shape[0] == 0:
            continue
        gts_exist = True
        boxes_class_image = image_objects_gt[:, -1]
        for j in range(1, num_classes):
            boxes_limits_gt = image_objects_gt[boxes_class_image == (j -
                                                                     1), :4]
            image_detections = all_detections[i][j]
            N_detections = len(image_detections)
            N_gts = boxes_limits_gt.shape[0]
            if N_detections == 0 or N_gts == 0:
                true_pos[i, j] = 0
                false_neg[i, j] = N_gts
                false_pos[i, j] = N_detections
                truepos_jaccard_mean[i, j] = 0
                continue

            # Get the box limits and confidence.
            boxes_limits_detections = image_detections[:, :4]
            detections_conf = image_detections[:, 4]

            # Calculate the jaccard overlap between detections and gt.
            boxes_limits_gt_tensor = torch.Tensor(boxes_limits_gt)
            boxes_limits_detections_tensor = torch.Tensor(
                boxes_limits_detections)

            # Permute columns to satisfy the input format of jaccard.
            boxes_limits_gt_tensor = boxes_limits_gt_tensor[:, (0, 2, 1, 3)]
            boxes_limits_detections_tensor = boxes_limits_detections_tensor[:,
                                                                            (0,
                                                                             2,
                                                                             1,
                                                                             3
                                                                             )]

            # intersect(boxes_limits_gt_tensor[0,:].unsqueeze(0),boxes_limits_detections_tensor[13,:].unsqueeze(0))
            jaccard_mat = jaccard(boxes_limits_gt_tensor,
                                  boxes_limits_detections_tensor)

            # For each detection, find the best ground truth overlap.
            best_truth_jaccard, best_truth_index = jaccard_mat.max(0)

            # For each gt x, find the detection with highest confidence among all detections whose max overlap is x.
            best_detection_ind = np.zeros((N_gts, 1)) * np.nan
            best_detection_conf = np.zeros((N_gts, 1))

            for k in range(N_detections):
                best_gt_ind = best_truth_index[k]
                if best_truth_jaccard[
                        k] > min_jaccard_overlap and detections_conf[
                            k] > best_detection_conf[best_gt_ind]:
                    best_detection_ind[best_gt_ind] = k
                    best_detection_conf[best_gt_ind] = detections_conf[k]

            # Remove nans, which correspond to unmatched gt boxes.
            best_detection_ind = best_detection_ind[
                ~np.isnan(best_detection_ind)].astype(np.int16)

            # Calculate the true positives, false positives and false negatives.
            true_pos[i, j] = best_detection_ind.shape[0]
            false_neg[i, j] = N_gts - true_pos[i][j]
            false_pos[i, j] = len([
                x for x in range(N_detections) if x not in best_detection_ind
            ])
            truepos_jaccard_mean[i, j] = np.mean(
                best_truth_jaccard.cpu().numpy()[best_detection_ind])

    if gts_exist:
        statistics_dict = {'dataset_name': config.dataset.name}
        statistics_dict.update(
            dict(zip(classes_name, [{}] * len(classes_name))))
        for j in range(1, num_classes):
            class_dict = {}
            class_dict['N_groundtruths'] = int(
                np.sum(true_pos[:, j] + false_neg[:, j]))
            class_dict['N_detections'] = int(
                np.sum(true_pos[:, j] + false_pos[:, j]))
            class_dict['True Positives'] = int(np.sum(true_pos[:, j]))
            class_dict['False Positives'] = int(np.sum(false_pos[:, j]))
            class_dict['False Negatives'] = int(np.sum(false_neg[:, j]))
            class_dict['Precision'] = class_dict['True Positives'] / (
                class_dict['True Positives'] + class_dict['False Positives'])
            class_dict['Recall'] = class_dict['True Positives'] / (
                class_dict['True Positives'] + class_dict['False Negatives'])
            class_dict['Jaccard_TruePos_Average'] = np.mean(
                truepos_jaccard_mean[:, j])

            total_false = false_pos[:, j] + false_neg[:, j]
            worst_image_id = np.argmax(total_false)

            class_dict['Highest False Pos + Neg Image'] = dataset.filenames[
                worst_image_id]
            class_dict['Highest Error Image: False positives'] = int(
                false_pos[worst_image_id, j])
            class_dict['Highest Error Image: False negatives'] = int(
                false_neg[worst_image_id, j])

            statistics_dict[classes_name[j - 1]] = class_dict

        # Add useful info to statistics_dict.
        statistics_dict['model'] = configs_dict['model']
        statistics_dict['eval'] = configs_dict['eval']

        with open(DETECTION_STATISTICS_FILEPATH, 'w') as file:
            file.write(
                reformat_json(
                    json.dumps(statistics_dict, sort_keys=False, indent=4)))
    else:
        print("No ground truths were found.")
def test_net(save_folder, net, cuda, testset, transform, thresh):
    # dump predictions and assoc. ground truth to text file for now
    filename = save_folder+'test1.txt'
    num_images = len(testset)
    mAP=0;
    for i in range(num_images):
        img = testset.pull_image(i)
        img_id, annotation = testset.pull_anno(i)
        x = torch.from_numpy(transform(img)[0]).permute(2, 0, 1)
        x = Variable(x.unsqueeze(0))
        
        with open(filename, mode='a') as f:
            f.write('\nGROUND TRUTH FOR: '+img_id+'\n')
           
        if cuda:
            x = x.cuda()

        y = net(x)      # forward pass
        detections = y.data
        # scale each detection back up to the image
        scale = torch.Tensor([img.shape[1], img.shape[0],
                             img.shape[1], img.shape[0]])
        pred_num = 0
        
        detections2=detections[0,:,:,0].view(-1)
        detectionr, rind =detections2.sort(descending=True)
        ntop=40
        jj=rind[:ntop]%200
        ii=rind[:ntop]/200
        
        gt_label=[box[-1]  for box in annotation]
        possible=len(gt_label) 
        if gt_label==0:
            continue
        gt_box=torch.tensor([box[:-1]  for box in annotation])
        dt_box=detections[0,ii,jj,1:]*scale
        iou=jaccard(dt_box,gt_box)
        k=0; correct=0;  
        precisions=[];
        while correct<possible and k<ntop:
            flag=False
            for j, gtl in enumerate(gt_label):
                if ii[k]-1==gtl and iou[k,j]>0.5:
                    correct+=1
                    flag=True
                    gt_label[j]=0 #turn the ground truth off
                    break
            if flag:
                name = labelmap[ii[k]-1]
                conf = detectionr[k].item()*100
                precision=correct/(k+1);recall=correct/possible
                precisions.append(precision)                    
                gtb=gt_box[j,:];dtb=dt_box[k,:]; iou1=iou[k,j].item()
                with open(filename, mode='a') as f:
                    f.write('rank %d: %s(%d), score %1.2f%%, precision:%1.2f, recall:%1.2f\n'%
                      (k,name,ii[k]-1,conf,precision,recall))
                    f.write('detection:'+' ||'.join('%d'%c.item() for c in dtb)+
                      ', ground truth: '+' ||'.join('%d'%c.item() for c in gtb)+', iou:%1.2f\n'%iou1)
                
            k+=1
        AP=1;
        for j,p in enumerate(precisions):
            prec=np.max(np.array(precisions[j:]))
            AP+=prec*(np.floor(np.float(j+1)/possible/0.1)-np.floor(np.float(j)/possible/0.1))
        AP=AP/11*100
        mAP=(mAP*i+AP)/(i+1)
        with open(filename, mode='a') as f:
            f.write('---AP: %.1f%%, total AP: %.1f%%---'%(AP,mAP))
        print('Image {:d}/{:d} AP: {:.1f}, total AP: {:.1f}'.format(i+1, num_images,AP,mAP))
Exemple #8
0
 def max_th(self):
     boxes = torch.from_numpy(self.dets[:,2:]).float()
     th = jaccard(boxes, boxes).numpy()
     for i in range(th.shape[0]): th[i][i] = 0
     return np.max(th, axis=1)