Calculate average precision (for single or multiple scales). Args: recalls (np.ndarray): Recalls with shape of (num_scales, num_dets) or (num_dets, ). precisions (np.ndarray): Precisions with shape of (num_scales, num_dets) or (num_dets, ). mode (
(recalls, precisions, mode='area')
| 6 | |
| 7 | |
| 8 | def average_precision(recalls, precisions, mode='area'): |
| 9 | """Calculate average precision (for single or multiple scales). |
| 10 | |
| 11 | Args: |
| 12 | recalls (np.ndarray): Recalls with shape of (num_scales, num_dets) |
| 13 | or (num_dets, ). |
| 14 | precisions (np.ndarray): Precisions with shape of |
| 15 | (num_scales, num_dets) or (num_dets, ). |
| 16 | mode (str): 'area' or '11points', 'area' means calculating the area |
| 17 | under precision-recall curve, '11points' means calculating |
| 18 | the average precision of recalls at [0, 0.1, ..., 1] |
| 19 | |
| 20 | Returns: |
| 21 | float or np.ndarray: Calculated average precision. |
| 22 | """ |
| 23 | if recalls.ndim == 1: |
| 24 | recalls = recalls[np.newaxis, :] |
| 25 | precisions = precisions[np.newaxis, :] |
| 26 | |
| 27 | assert recalls.shape == precisions.shape |
| 28 | assert recalls.ndim == 2 |
| 29 | |
| 30 | num_scales = recalls.shape[0] |
| 31 | ap = np.zeros(num_scales, dtype=np.float32) |
| 32 | if mode == 'area': |
| 33 | zeros = np.zeros((num_scales, 1), dtype=recalls.dtype) |
| 34 | ones = np.ones((num_scales, 1), dtype=recalls.dtype) |
| 35 | mrec = np.hstack((zeros, recalls, ones)) |
| 36 | mpre = np.hstack((zeros, precisions, zeros)) |
| 37 | for i in range(mpre.shape[1] - 1, 0, -1): |
| 38 | mpre[:, i - 1] = np.maximum(mpre[:, i - 1], mpre[:, i]) |
| 39 | for i in range(num_scales): |
| 40 | ind = np.where(mrec[i, 1:] != mrec[i, :-1])[0] |
| 41 | ap[i] = np.sum( |
| 42 | (mrec[i, ind + 1] - mrec[i, ind]) * mpre[i, ind + 1]) |
| 43 | elif mode == '11points': |
| 44 | for i in range(num_scales): |
| 45 | for thr in np.arange(0, 1 + 1e-3, 0.1): |
| 46 | precs = precisions[i, recalls[i, :] >= thr] |
| 47 | prec = precs.max() if precs.size > 0 else 0 |
| 48 | ap[i] += prec |
| 49 | ap /= 11 |
| 50 | else: |
| 51 | raise ValueError( |
| 52 | 'Unrecognized mode, only "area" and "11points" are supported') |
| 53 | return ap |
| 54 | |
| 55 | |
| 56 | def eval_det_cls(pred, gt, iou_thr=None): |