def eval_prop_cls()

in wypr/utils/eval_prop.py [0:0]


def eval_prop_cls(pred, gt, ovthresh=0.25, get_iou_func=get_iou):
    """ Generic functions to compute precision/recall for object detection
        for a single class.
        Input:
            pred: map of {img_id: [(bbox, score)]} where bbox is numpy array
            gt: map of {img_id: [bbox]}
            ovthresh: scalar, iou threshold
        Output:
            rec: numpy array of length nd
            ABO: Average Best Overlap (ABO)
    """

    # construct gt objects
    class_recs = {} # {img_id: {'bbox': bbox list, 'det': matched list, 'max_overlap': for MABO}}
    npos = 0
    for img_id in gt.keys():
        bbox = np.array(gt[img_id])
        det = [False] * len(bbox)
        max_overlap = [0] * len(bbox)
        npos += len(bbox)
        class_recs[img_id] = {'bbox': bbox, 'det': det, 'max_overlap': max_overlap}
    # pad empty list to all other imgids
    for img_id in pred.keys():
        if img_id not in gt:
            class_recs[img_id] = {'bbox': np.array([]), 'det': [], 'max_overlap': []}
    
    # construct dets
    image_ids = []
    BB = []
    for img_id in pred.keys():
        for box in pred[img_id]:
            image_ids.append(img_id)
            BB.append(box)
    BB = np.array(BB) # (nd,4 or 8,3 or 6)

    # go down dets and mark TPs and FPs
    nd = len(image_ids)
    tp = np.zeros(nd)
    fp = np.zeros(nd)
    for d in range(nd):
        #if d%100==0: print(d)
        R = class_recs[image_ids[d]]
        bb = BB[d,...].astype(float)
        ovmax = -np.inf
        BBGT = R['bbox'].astype(float)

        if BBGT.size > 0:
            # compute overlaps
            for j in range(BBGT.shape[0]):
                iou = get_iou_main(get_iou_func, (bb, BBGT[j,...]))
                if iou > ovmax:
                    ovmax = iou
                    jmax = j

        #print d, ovmax
        if ovmax > ovthresh:
            if not R['det'][jmax]:
                tp[d] = 1.
                R['det'][jmax] = 1
                if ovmax > R['max_overlap'][jmax]:
                    if ovmax > 1:
                        print('wrong ovmax: %f'%ovmax)
                    R['max_overlap'][jmax] = ovmax
            else:
                fp[d] = 1.
        else:
            fp[d] = 1.

    # compute precision recall
    fp = np.cumsum(fp)
    tp = np.cumsum(tp)
    rec = tp / float(npos)
    # # avoid divide by zero in case the first detection matches a difficult ground truth
    # prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)

    max_overlaps = []
    for i in range(len(class_recs)):
        if class_recs[i]['bbox'].size != 0:
            max_overlaps += class_recs[i]['max_overlap']

    assert len(max_overlaps) == npos
    ABO = np.mean(max_overlaps)

    return rec, ABO