Exemple #1
0
def evaluate_experiment(results_dir):
    accumulators = []
    experiment_names = []
    for exp_info, trackingsOverTime, ground_truth in read_trackings(
            results_dir):
        acc = motmetrics.MOTAccumulator(auto_id=True)
        accumulators.append(acc)
        experiment_names.append(exp_info['datasetName'])
        for tracks, gt in zip(trackingsOverTime, ground_truth):
            if tracks:
                x1, y1, x2, y2 = np.array([t['bbox'] for t in tracks]).T
            else:
                x1, y1, x2, y2 = [np.array([])] * 4
            pred_bboxes = np.array([x1, y1, x2 - x1, y2 - y1]).T
            iou = motmetrics.distances.iou_matrix(
                gt[:, 1:5] if len(gt) else np.empty((0, 0)),
                pred_bboxes,
                max_iou=1)
            acc.update(gt[:, 0] if len(gt) else np.empty((0)),
                       [t['id'] for t in tracks], iou)

    mh = motmetrics.metrics.create()
    summary = mh.compute_many(accumulators,
                              metrics=motmetrics.metrics.motchallenge_metrics,
                              names=experiment_names,
                              generate_overall=True)
    strsummary = motmetrics.io.render_summary(
        summary,
        formatters=mh.formatters,
        namemap=motmetrics.io.motchallenge_metric_names)
    strsummary = "MOTA and MOTP are wrong. See py-motmetrics README. Don't use these.\n" + strsummary
    return strsummary
Exemple #2
0
def test_assignment_metrics_with_empty_groundtruth():
    acc = mm.MOTAccumulator(auto_id=True)
    # Empty groundtruth.
    acc.update([], [1, 2, 3, 4], [])
    acc.update([], [1, 2, 3, 4], [])
    acc.update([], [1, 2, 3, 4], [])
    acc.update([], [1, 2, 3, 4], [])

    mh = mm.metrics.create()
    metr = mh.compute(acc,
                      return_dataframe=False,
                      metrics=[
                          'num_matches',
                          'num_false_positives',
                          'num_misses',
                          'idtp',
                          'idfp',
                          'idfn',
                      ])
    assert metr['num_matches'] == 0
    assert metr['num_false_positives'] == 16
    assert metr['num_misses'] == 0
    assert metr['idtp'] == 0
    assert metr['idfp'] == 16
    assert metr['idfn'] == 0
Exemple #3
0
def test_events():
    acc = mm.MOTAccumulator()

    # All FP
    acc.update([], ['a', 'b'], [], frameid=0)
    # All miss
    acc.update([1, 2], [], [], frameid=1)
    # Match
    acc.update([1, 2], ['a', 'b'], [[1, 0.5], [0.3, 1]], frameid=2)
    # Switch
    acc.update([1, 2], ['a', 'b'], [[0.2, np.nan], [np.nan, 0.1]], frameid=3)
    # Match. Better new match is available but should prefer history
    acc.update([1, 2], ['a', 'b'], [[5, 1], [1, 5]], frameid=4)
    # No data
    acc.update([], [], [], frameid=5)

    expect = mm.MOTAccumulator.new_event_dataframe()
    expect.loc[(0, 0), :] = ['FP', np.nan, 'a', np.nan]
    expect.loc[(0, 1), :] = ['FP', np.nan, 'b', np.nan]
    expect.loc[(1, 0), :] = ['MISS', 1, np.nan, np.nan]
    expect.loc[(1, 1), :] = ['MISS', 2, np.nan, np.nan]
    expect.loc[(2, 0), :] = ['MATCH', 1, 'b', 0.5]
    expect.loc[(2, 1), :] = ['MATCH', 2, 'a', 0.3]
    expect.loc[(3, 0), :] = ['SWITCH', 1, 'a', 0.2]
    expect.loc[(3, 1), :] = ['SWITCH', 2, 'b', 0.1]
    expect.loc[(4, 0), :] = ['MATCH', 1, 'a', 5.]
    expect.loc[(4, 1), :] = ['MATCH', 2, 'b', 5.]
    # frame 5 generates no events

    assert pd.DataFrame.equals(acc.events, expect)
    
    mh = mm.metrics.create()
    metr = mh.compute(acc, metrics=['motp', 'mota'], return_dataframe=False)
    assert metr['motp'] == approx(11.1 / 6)
    assert metr['mota'] == approx(1. - (2 + 2 + 2) / 8)
def test_assignment_metrics_with_both_empty():
    """Tests metrics when there are no ground-truth objects or predictions."""
    acc = mm.MOTAccumulator(auto_id=True)
    # Empty groundtruth and empty predictions.
    acc.update([], [], [])
    acc.update([], [], [])
    acc.update([], [], [])
    acc.update([], [], [])

    mh = mm.metrics.create()
    metr = mh.compute(acc,
                      return_dataframe=False,
                      metrics=[
                          'num_matches',
                          'num_false_positives',
                          'num_misses',
                          'idtp',
                          'idfp',
                          'idfn',
                          'num_frames',
                      ])
    assert metr['num_matches'] == 0
    assert metr['num_false_positives'] == 0
    assert metr['num_misses'] == 0
    assert metr['idtp'] == 0
    assert metr['idfp'] == 0
    assert metr['idfn'] == 0
    assert metr['num_frames'] == 4
Exemple #5
0
def evaluate(objects, hypothesis, verbose=True):
    obj_json = JSONTracks(objects, from_xml=(objects.suffix == ".xml"))
    hyp_json = JSONTracks(hypothesis, from_xml=(hypothesis.suffix == ".xml"))

    assert obj_json.nframes == hyp_json.nframes, \
        f"Objects (nframes={obj_json.nframes}) and Hypothesis (nframes={hyp_json.nframes}) " \
        f"must have equal number of frames."

    acc = mm.MOTAccumulator(auto_id=True)

    for i in range(obj_json.nframes):
        if verbose:
            print(f"\rAccumulatating annotations {i + 1}/{obj_json.nframes}.",
                  end="")
        gt_coords, gt_ids = obj_json.get_frame_coordinates(
            i), obj_json.get_frame_ids(i)
        hy_coords, hy_ids = hyp_json.get_frame_coordinates(
            i), hyp_json.get_frame_ids(i)
        dis = mm.distances.norm2squared_matrix(gt_coords, hy_coords, 15)
        acc.update(gt_ids, hy_ids, dis)

    if verbose:
        print("\nComputing metrics...")
    mh = mm.metrics.create()
    summary = mh.compute_many([acc],
                              metrics=mm.metrics.motchallenge_metrics,
                              names=['value'])
    str_summary = mm.io.render_summary(summary,
                                       formatters=mh.formatters,
                                       namemap=mm.io.motchallenge_metric_names)

    if verbose:
        print(50 * "#" + "\n" + str_summary + "\n" + 50 * "#")
    return summary
def test_extract_counts():
    """Tests events_to_df_map() and extract_counts_from_df_map()."""
    acc = mm.MOTAccumulator()
    # All FP
    acc.update([], [1, 2], [], frameid=0)
    # All miss
    acc.update([1, 2], [], [], frameid=1)
    # Match
    acc.update([1, 2], [1, 2], [[1, 0.5], [0.3, 1]], frameid=2)
    # Switch
    acc.update([1, 2], [1, 2], [[0.2, np.nan], [np.nan, 0.1]], frameid=3)
    # Match. Better new match is available but should prefer history
    acc.update([1, 2], [1, 2], [[5, 1], [1, 5]], frameid=4)
    # No data
    acc.update([], [], [], frameid=5)

    ocs, hcs, tps = _extract_counts(acc)

    assert ocs == {1: 4, 2: 4}
    assert hcs == {1: 4, 2: 4}
    expected_tps = {
        (1, 1): 3,
        (1, 2): 2,
        (2, 1): 2,
        (2, 2): 3,
    }
    assert tps == expected_tps
Exemple #7
0
    def __init__(
        self,
        folder,
        draw_,
        min_iou_,
        max_miss_,
        conf_v,
        eval_=False,
    ):

        self.dataset = Dataset(folder, eval_)
        self.Tracks = OrderedDict()
        self.num_frames = self.dataset.getNumberFrames()
        self.next_id = 0
        self.draw_objects, self.show_objects, self.draw_video = draw_
        self.eval = eval_
        self.min_iou = min_iou_
        self.max_miss = max_miss_
        self.conf_value = conf_v
        self._create_new_tracks(self.dataset.getDetections(1))
        if self.draw_objects:
            self.list_frames = [self._drawObjects(1)]

        if self.eval:
            self.acc = mm.MOTAccumulator(auto_id=True)
            self.mh = mm.metrics.create()
            self._eval(1)
Exemple #8
0
def print_result(gt, ht):
    interested_frame = set(gt.keys()).union(set(ht.keys()))
    acc = mm.MOTAccumulator(auto_id=True)
    for frame_id in list(interested_frame):
        gt_ids = []
        gt_bbs = []
        ht_ids = []
        ht_bbs = []
        if frame_id in gt:
            for tracker in gt[frame_id]:
                gt_ids.append(tracker[0])
                gt_bbs.append(tracker[1])

        if frame_id in ht:
            for tracker in ht[frame_id]:
                ht_ids.append(tracker[0])
                ht_bbs.append(tracker[1])
        distance_matrix = mm.distances.iou_matrix(gt_bbs, ht_bbs, max_iou=0.8)
        acc.update(gt_ids, ht_ids, distance_matrix)

    mh = mm.metrics.create()
    summary = mh.compute_many([acc],
                              metrics=mm.metrics.motchallenge_metrics,
                              names=['Value'])

    strsummary = mm.io.render_summary(summary,
                                      formatters=mh.formatters,
                                      namemap=mm.io.motchallenge_metric_names)
    print(strsummary)
def test_mota_motp():
    acc = mm.MOTAccumulator()

    # All FP
    acc.update([], ['a', 'b'], [], frameid=0)
    # All miss
    acc.update([1, 2], [], [], frameid=1)
    # Match
    acc.update([1, 2], ['a', 'b'], [[1, 0.5], [0.3, 1]], frameid=2)
    # Switch
    acc.update([1, 2], ['a', 'b'], [[0.2, np.nan], [np.nan, 0.1]], frameid=3)
    # Match. Better new match is available but should prefer history
    acc.update([1, 2], ['a', 'b'], [[5, 1], [1, 5]], frameid=4)
    # No data
    acc.update([], [], [], frameid=5)

    mh = mm.metrics.create()
    metr = mh.compute(acc,
                      metrics=['motp', 'mota', 'num_predictions'],
                      return_dataframe=False,
                      return_cached=True)

    assert metr['num_matches'] == 4
    assert metr['num_false_positives'] == 2
    assert metr['num_misses'] == 2
    assert metr['num_switches'] == 2
    assert metr['num_detections'] == 6
    assert metr['num_objects'] == 8
    assert metr['num_predictions'] == 8
    assert metr['mota'] == approx(1. - (2 + 2 + 2) / 8)
    assert metr['motp'] == approx(11.1 / 6)
    def compute_map(self, epoch):
        global GT
        if GT is None:
            self.collect_gt()
        root = self.args.res_dir
        unique_fps = set()
        for x in os.listdir(root):
            name = x.split('.')[0]
            unique_fps.add(name)

        dr = {}
        for x in unique_fps:
            if int(x.split('_')[-1]) % 10 != 0:
                continue
            if x not in dr:
                dr[x] = {'bboxes': [], 'scores': [], 'ids': []}

            with open(os.path.join(root, x + '.txt')) as f:
                tracks = f.read().split('\n')
                tracks = [list(map(float, x.split())) for x in tracks if x]

            for track in tracks:
                score, _id, *box = track
                dr[x]['scores'].append(score)
                dr[x]['bboxes'].append(self.args.down_ratio * np.array(box))
                dr[x]['ids'].append(int(_id))

        inters = set(GT.keys()).intersection(dr.keys())
        unique_fids = set()
        for x in inters:
            unique_fids.add(x.split('.')[0].split('_frame')[0])
        unique_fids = list(unique_fids)
        accs = []
        for k in unique_fids:
            acc = mm.MOTAccumulator(auto_id=True)
            fids = sorted([x.split('.')[0] for x in inters if k in x],
                          key=lambda x: int(x.split('.')[0].split('_')[-1]))
            for fid in fids:
                gt_id, dr_id, dist = load(fid,
                                          GT,
                                          dr,
                                          use_ids=True,
                                          max_iou=0.55)
                acc.update(gt_id, dr_id, dist)
            accs.append(acc)
        mh = mm.metrics.create()
        summary = mh.compute_many(
            accs,
            metrics=[
                'num_frames', 'num_objects', 'num_predictions', 'num_matches',
                'num_misses', 'num_false_positives', 'num_switches', 'mota',
                'motp', 'recall', 'idp', 'idr', 'idf1'
            ],
            generate_overall=True,
            names=unique_fids,
        )
        summary.to_csv(
            os.path.join(self.args.weights_dir,
                         "map_result_{}.csv".format(epoch)))
Exemple #11
0
 def add(self, tracks, gt_frames, name='test', frame_range=None):
     assert frame_range is not None
     if not tracks:
         return
     acc = motmetrics.MOTAccumulator()
     self.accumulators.append(acc)
     self.names.append(name.split('.')[0][-40:])
     self.update(tracks, gt_frames, frame_range)
Exemple #12
0
def test_events():
    """Tests that expected events are created by MOTAccumulator.update()."""
    acc = mm.MOTAccumulator()

    # All FP
    acc.update([], [1, 2], [], frameid=0)
    # All miss
    acc.update([1, 2], [], [], frameid=1)
    # Match
    acc.update([1, 2], [1, 2], [[1, 0.5], [0.3, 1]], frameid=2)
    # Switch
    acc.update([1, 2], [1, 2], [[0.2, np.nan], [np.nan, 0.1]], frameid=3)
    # Match. Better new match is available but should prefer history
    acc.update([1, 2], [1, 2], [[5, 1], [1, 5]], frameid=4)
    # No data
    acc.update([], [], [], frameid=5)

    expect = mm.MOTAccumulator.new_event_dataframe()
    expect.loc[(0, 0), :] = ['RAW', np.nan, np.nan, np.nan]
    expect.loc[(0, 1), :] = ['RAW', np.nan, 1, np.nan]
    expect.loc[(0, 2), :] = ['RAW', np.nan, 2, np.nan]
    expect.loc[(0, 3), :] = ['FP', np.nan, 1, np.nan]
    expect.loc[(0, 4), :] = ['FP', np.nan, 2, np.nan]

    expect.loc[(1, 0), :] = ['RAW', np.nan, np.nan, np.nan]
    expect.loc[(1, 1), :] = ['RAW', 1, np.nan, np.nan]
    expect.loc[(1, 2), :] = ['RAW', 2, np.nan, np.nan]
    expect.loc[(1, 3), :] = ['MISS', 1, np.nan, np.nan]
    expect.loc[(1, 4), :] = ['MISS', 2, np.nan, np.nan]

    expect.loc[(2, 0), :] = ['RAW', np.nan, np.nan, np.nan]
    expect.loc[(2, 1), :] = ['RAW', 1, 1, 1.0]
    expect.loc[(2, 2), :] = ['RAW', 1, 2, 0.5]
    expect.loc[(2, 3), :] = ['RAW', 2, 1, 0.3]
    expect.loc[(2, 4), :] = ['RAW', 2, 2, 1.0]
    expect.loc[(2, 5), :] = ['MATCH', 1, 2, 0.5]
    expect.loc[(2, 6), :] = ['MATCH', 2, 1, 0.3]

    expect.loc[(3, 0), :] = ['RAW', np.nan, np.nan, np.nan]
    expect.loc[(3, 1), :] = ['RAW', 1, 1, 0.2]
    expect.loc[(3, 2), :] = ['RAW', 2, 2, 0.1]
    expect.loc[(3, 3), :] = ['TRANSFER', 1, 1, 0.2]
    expect.loc[(3, 4), :] = ['SWITCH', 1, 1, 0.2]
    expect.loc[(3, 5), :] = ['TRANSFER', 2, 2, 0.1]
    expect.loc[(3, 6), :] = ['SWITCH', 2, 2, 0.1]

    expect.loc[(4, 0), :] = ['RAW', np.nan, np.nan, np.nan]
    expect.loc[(4, 1), :] = ['RAW', 1, 1, 5.]
    expect.loc[(4, 2), :] = ['RAW', 1, 2, 1.]
    expect.loc[(4, 3), :] = ['RAW', 2, 1, 1.]
    expect.loc[(4, 4), :] = ['RAW', 2, 2, 5.]
    expect.loc[(4, 5), :] = ['MATCH', 1, 1, 5.]
    expect.loc[(4, 6), :] = ['MATCH', 2, 2, 5.]

    expect.loc[(5, 0), :] = ['RAW', np.nan, np.nan, np.nan]

    pd.util.testing.assert_frame_equal(acc.events, expect)
Exemple #13
0
def test_max_switch_time():
    acc = mm.MOTAccumulator(max_switch_time=1)
    acc.update([1, 2], ['a', 'b'], [[1, 0.5], [0.3, 1]],
               frameid=1)  # 1->a, 2->b
    frameid = acc.update([1, 2], ['a', 'b'], [[0.5, np.nan], [np.nan, 0.5]],
                         frameid=2)  # 1->b, 2->a

    df = acc.events.loc[frameid]
    assert ((df.Type == 'SWITCH') | (df.Type == 'RAW')).all()

    acc = mm.MOTAccumulator(max_switch_time=1)
    acc.update([1, 2], ['a', 'b'], [[1, 0.5], [0.3, 1]],
               frameid=1)  # 1->a, 2->b
    frameid = acc.update([1, 2], ['a', 'b'], [[0.5, np.nan], [np.nan, 0.5]],
                         frameid=5)  # Later frame 1->b, 2->a

    df = acc.events.loc[frameid]
    assert ((df.Type == 'MATCH') | (df.Type == 'RAW')).all()
Exemple #14
0
def acc_single_video_mots(
    gts: List[str],
    results: List[str],
    iou_thr: float = 0.5,
    ignore_iof_thr: float = 0.5,
) -> List[mm.MOTAccumulator]:
    """Accumulate results for one video."""
    assert len(gts) == len(results)
    num_classes = len(CLASSES)

    accs = [mm.MOTAccumulator(auto_id=True) for _ in range(num_classes)]
    for gt, result in zip(gts, results):
        assert os.path.isfile(gt)
        assert os.path.isfile(result)

        gt_masks = np.asarray(Image.open(gt))
        res_masks = np.asarray(Image.open(result))
        gt_masks, gt_ids, gt_attrs, gt_cats = parse_bitmasks(gt_masks)
        pred_masks, pred_ids, pred_attrs, pred_cats = parse_bitmasks(res_masks)
        ious, iofs = mask_intersection_rate(gt_masks, pred_masks)

        gt_valids = np.logical_not((gt_attrs & 3).astype(np.bool8))
        pred_valids = np.logical_not((pred_attrs & 3).astype(np.bool8))
        for i in range(num_classes):
            # cats starts from 1 and i starts from 0
            gt_inds = (gt_cats == i + 1) * gt_valids
            pred_inds = (pred_cats == i + 1) * pred_valids
            gt_ids_c, pred_ids_c = gt_ids[gt_inds], pred_ids[pred_inds]

            if gt_ids_c.shape[0] == 0 and pred_ids_c.shape[0] != 0:
                distances = np.full((0, pred_ids_c.shape[0]), np.nan)
            elif gt_ids_c.shape[0] != 0 and pred_ids_c.shape[0] == 0:
                distances = np.full((gt_ids_c.shape[0], 0), np.nan)
            else:
                ious_c = ious[gt_inds, :][:, pred_inds]
                distances = 1 - ious_c
                distances = np.where(distances > 1 - iou_thr, np.nan,
                                     distances)

            gt_invalid = np.logical_not(gt_valids)
            if (gt_invalid).any():
                # 1. assign gt and preds
                fps = np.ones(pred_ids_c.shape[0]).astype(np.bool8)
                le, ri = mm.lap.linear_sum_assignment(distances)
                for m, n in zip(le, ri):
                    if np.isfinite(distances[m, n]):
                        fps[n] = False
                # 2. ignore by iof
                iofs_c = iofs[gt_invalid, :][:, pred_inds]
                ignores = (iofs_c > ignore_iof_thr).any(axis=0)
                # 3. filter preds
                valid_inds = ~(fps & ignores)
                pred_ids_c = pred_ids_c[valid_inds]
                distances = distances[:, valid_inds]
            if distances.shape != (0, 0):
                accs[i].update(gt_ids_c, pred_ids_c, distances)
    return accs
Exemple #15
0
def acc_single_video_mot(
    gts: List[Frame],
    results: List[Frame],
    classes: List[str],
    iou_thr: float = 0.5,
    ignore_iof_thr: float = 0.5,
) -> List[mm.MOTAccumulator]:
    """Accumulate results for one video."""
    assert len(gts) == len(results)
    get_frame_index = (
        lambda x: x.frame_index if x.frame_index is not None else 0
    )
    num_classes = len(classes)
    gts = sorted(gts, key=get_frame_index)
    results = sorted(results, key=get_frame_index)
    accs = [mm.MOTAccumulator(auto_id=True) for _ in range(num_classes)]
    for gt, result in zip(gts, results):
        assert gt.frame_index == result.frame_index
        gt_bboxes, gt_labels, gt_ids, gt_ignores = parse_objects(
            gt.labels if gt.labels is not None else [], classes
        )
        pred_bboxes, pred_labels, pred_ids, _ = parse_objects(
            result.labels if result.labels is not None else [], classes
        )
        for i in range(num_classes):
            gt_inds, pred_inds = gt_labels == i, pred_labels == i
            gt_bboxes_c, gt_ids_c = gt_bboxes[gt_inds], gt_ids[gt_inds]
            pred_bboxes_c, pred_ids_c = (
                pred_bboxes[pred_inds],
                pred_ids[pred_inds],
            )
            if gt_bboxes_c.shape[0] == 0 and pred_bboxes_c.shape[0] != 0:
                distances = np.full((0, pred_bboxes_c.shape[0]), np.nan)
            elif gt_bboxes_c.shape[0] != 0 and pred_bboxes_c.shape[0] == 0:
                distances = np.full((gt_bboxes_c.shape[0], 0), np.nan)
            else:
                distances = mm.distances.iou_matrix(
                    gt_bboxes_c, pred_bboxes_c, max_iou=1 - iou_thr
                )
            if gt_ignores.shape[0] > 0:
                # 1. assign gt and preds
                fps = np.ones(pred_bboxes_c.shape[0]).astype(np.bool8)
                le, ri = mm.lap.linear_sum_assignment(distances)
                for m, n in zip(le, ri):
                    if np.isfinite(distances[m, n]):
                        fps[n] = False
                # 2. ignore by iof
                iofs = intersection_over_area(pred_bboxes_c, gt_ignores)
                ignores = (iofs > ignore_iof_thr).any(axis=1)
                # 3. filter preds
                valid_inds = ~(fps & ignores)
                pred_ids_c = pred_ids_c[valid_inds]
                distances = distances[:, valid_inds]
            if distances.shape != (0, 0):
                accs[i].update(gt_ids_c, pred_ids_c, distances)
    return accs
Exemple #16
0
def getMetrics(tracks, params, gt_file):
    num_frames = params["frames"]

    ground_truth, list_of_trajectories = parseXML(gt_file, num_frames)
    list_of_tracks, hypothesis = build_tracks_at_frame(tracks, num_frames)

    acc = mm.MOTAccumulator(auto_id=True)
    acc = update_accumulator(acc, ground_truth, hypothesis, list_of_trajectories, list_of_tracks, num_frames)
    results = generate_results(acc)
    return getResultsAsString(results)
Exemple #17
0
def calculate_ap(det_bb, gt_bb, ini_frame, last_frame, mode):
    lst_gt = [item[0] for item in gt_bb]
    lst_det = [item[0] for item in det_bb]
    acc = mm.MOTAccumulator(auto_id=True)

    AP = 0
    for f_val in range(ini_frame, last_frame):
        frame_gt_bb = [
            gt_bb[i] for i, num in enumerate(lst_gt) if num == f_val
        ]
        n_gt = len(frame_gt_bb)
        frame_det_bb = [
            det_bb[i] for i, num in enumerate(lst_det) if num == f_val
        ]

        if mode == 'sort':
            frame_det_bb = sorted(frame_det_bb,
                                  key=lambda x: x[-1],
                                  reverse=True)
            f_det_bb = [item[:-1] for item in frame_det_bb]
            AP = AP + frame_AP(n_gt, f_det_bb, copy.deepcopy(frame_gt_bb))
        elif mode == 'random':

            #Random shuffle
            f_ap = 0
            for i in range(0, 10):
                shuffle(frame_det_bb)
                a = frame_AP(n_gt, copy.deepcopy(frame_det_bb),
                             copy.deepcopy(frame_gt_bb))
                f_ap = f_ap + a
            AP = AP + f_ap / 10

        else:
            #Sorted by area
            frame_det_bb = sorted(frame_det_bb,
                                  key=lambda x: (x[5] - x[3]) * (x[5] - x[3]),
                                  reverse=True)
            AP = AP + frame_AP(n_gt, copy.deepcopy(frame_det_bb),
                               copy.deepcopy(frame_gt_bb))

        y_pred = {det[2]: det[3:7] for det in frame_det_bb}
        y_true = {gt[2]: gt[3:] for gt in frame_gt_bb}
        distances = [[
            np.sqrt(np.sum((np.array(i) - np.array(j))**2))
            for j in y_pred.values()
        ] for i in y_true.values()]

        acc.update([*y_true.keys()], [*y_pred.keys()], distances)

    summary = mm.metrics.create().compute(acc,
                                          metrics=['idf1'],
                                          name='idf1_score')
    print(summary)
    AP = AP / last_frame
    return AP
def _accum_random_uniform(rand, seq_len, num_objs, num_hyps, objs_per_frame,
                          hyps_per_frame):
    acc = mm.MOTAccumulator(auto_id=True)
    for _ in range(seq_len):
        # Choose subset of objects present in this frame.
        objs = rand.choice(num_objs, objs_per_frame, replace=False)
        # Choose subset of hypotheses present in this frame.
        hyps = rand.choice(num_hyps, hyps_per_frame, replace=False)
        dist = rand.uniform(size=(objs_per_frame, hyps_per_frame))
        acc.update(objs, hyps, dist)
    return acc
Exemple #19
0
def test_events():
    acc = mm.MOTAccumulator()

    # All FP
    acc.update([], ['a', 'b'], [], frameid=0)
    # All miss
    acc.update([1, 2], [], [], frameid=1)
    # Match
    acc.update([1, 2], ['a', 'b'], [[1, 0.5], [0.3, 1]], frameid=2)
    # Switch
    acc.update([1, 2], ['a', 'b'], [[0.2, np.nan], [np.nan, 0.1]], frameid=3)
    # Match. Better new match is available but should prefer history
    acc.update([1, 2], ['a', 'b'], [[5, 1], [1, 5]], frameid=4)
    # No data
    acc.update([], [], [], frameid=5)

    expect = mm.MOTAccumulator.new_event_dataframe()
    expect.loc[(0, 0), :] = ['RAW', np.nan, 'a', np.nan]
    expect.loc[(0, 1), :] = ['RAW', np.nan, 'b', np.nan]
    expect.loc[(0, 2), :] = ['FP', np.nan, 'a', np.nan]
    expect.loc[(0, 3), :] = ['FP', np.nan, 'b', np.nan]

    expect.loc[(1, 0), :] = ['RAW', 1, np.nan, np.nan]
    expect.loc[(1, 1), :] = ['RAW', 2, np.nan, np.nan]
    expect.loc[(1, 2), :] = ['MISS', 1, np.nan, np.nan]
    expect.loc[(1, 3), :] = ['MISS', 2, np.nan, np.nan]

    expect.loc[(2, 0), :] = ['RAW', 1, 'a', 1.0]
    expect.loc[(2, 1), :] = ['RAW', 1, 'b', 0.5]
    expect.loc[(2, 2), :] = ['RAW', 2, 'a', 0.3]
    expect.loc[(2, 3), :] = ['RAW', 2, 'b', 1.0]
    expect.loc[(2, 4), :] = ['MATCH', 1, 'b', 0.5]
    expect.loc[(2, 5), :] = ['MATCH', 2, 'a', 0.3]

    expect.loc[(3, 0), :] = ['RAW', 1, 'a', 0.2]
    expect.loc[(3, 1), :] = ['RAW', 1, 'b', np.nan]
    expect.loc[(3, 2), :] = ['RAW', 2, 'a', np.nan]
    expect.loc[(3, 3), :] = ['RAW', 2, 'b', 0.1]
    expect.loc[(3, 4), :] = ['TRANSFER', 1, 'a', 0.2]
    expect.loc[(3, 5), :] = ['SWITCH', 1, 'a', 0.2]
    expect.loc[(3, 6), :] = ['TRANSFER', 2, 'b', 0.1]
    expect.loc[(3, 7), :] = ['SWITCH', 2, 'b', 0.1]

    expect.loc[(4, 0), :] = ['RAW', 1, 'a', 5.]
    expect.loc[(4, 1), :] = ['RAW', 1, 'b', 1.]
    expect.loc[(4, 2), :] = ['RAW', 2, 'a', 1.]
    expect.loc[(4, 3), :] = ['RAW', 2, 'b', 5.]
    expect.loc[(4, 4), :] = ['MATCH', 1, 'a', 5.]
    expect.loc[(4, 5), :] = ['MATCH', 2, 'b', 5.]
    # frame 5 generates no events

    from pandas.util.testing import assert_frame_equal
    assert_frame_equal(acc.events, expect)
Exemple #20
0
def accumulate_events(gt_dict, pred_dict, args):
    acc = mm.MOTAccumulator()
    count = 0
    for i in tqdm(range(len(gt_dict))):
        for t in range(args.start_step, args.stop_step):
            gt_dict_frame = gt_dict[i][t]
            pred_dict_frame = pred_dict[i][t]
            dist, gt_ids, pred_ids = compute_dists_per_frame(
                gt_dict_frame, pred_dict_frame, args)
            acc.update(gt_ids, pred_ids, dist, frameid=count)
            count += 1
    return acc
Exemple #21
0
def get_mot_accum(results, seq):
    mot_accum = mm.MOTAccumulator(auto_id=True)
    for i, data in enumerate(seq):
        gt = data["gt"]
        gt_ids = []
        if gt:
            gt_boxes = []
            for gt_id, box in gt.items():
                gt_ids.append(gt_id)
                gt_boxes.append(box)

            gt_boxes = np.stack(gt_boxes, axis=0)
            # x1, y1, x2, y2 --> x1, y1, width, height
            gt_boxes = np.stack(
                (
                    gt_boxes[:, 0],
                    gt_boxes[:, 1],
                    gt_boxes[:, 2] - gt_boxes[:, 0],
                    gt_boxes[:, 3] - gt_boxes[:, 1],
                ),
                axis=1,
            )
        else:
            gt_boxes = np.array([])

        track_ids = []
        track_boxes = []
        for track_id, frames in results.items():
            if i in frames:
                track_ids.append(track_id)
                # frames = x1, y1, x2, y2, score
                track_boxes.append(frames[i][:4])

        if track_ids:
            track_boxes = np.stack(track_boxes, axis=0)
            # x1, y1, x2, y2 --> x1, y1, width, height
            track_boxes = np.stack(
                (
                    track_boxes[:, 0],
                    track_boxes[:, 1],
                    track_boxes[:, 2] - track_boxes[:, 0],
                    track_boxes[:, 3] - track_boxes[:, 1],
                ),
                axis=1,
            )
        else:
            track_boxes = np.array([])

        distance = mm.distances.iou_matrix(gt_boxes, track_boxes, max_iou=0.5)

        mot_accum.update(gt_ids, track_ids, distance)

    return mot_accum
Exemple #22
0
def build_mot_accumulator(truth_framedata: {},
                          model_framedata: {}) -> mm.MOTAccumulator:
    """ Parses the provided frame data and builds the motmetrics accumulator with
        it.

        Params
        ------
        truth_framedata: The data for the ground-truth output, parsed as a dictionary
              where the keys are frame numbers mapping to lists of detections for that
              frame. (as given by parse_XML_by_frame)

        model_framedata: The data for the model's output, in the same format as the
              truth_framedata.

        Returns 
        -------
        A motmetrics.MOTAccumulator that stores the matches and MOTEvents for all the
        frames in the input framedata.
    """

    # Get the maximum number of frames.
    max_frame = -1
    if truth_framedata:
        truth_frames = list(map(lambda x: int(x), truth_framedata.keys()))
        max_frame = max(truth_frames)
    if model_framedata:
        model_frames = list(map(lambda x: int(x), model_framedata.keys()))
        max_model_frame = max(model_frames)
        max_frame = max(max_frame, max_model_frame)

    #print("max_frame is {}".format(max_frame))

    acc = mm.MOTAccumulator()
    # Loop through each frame and build the distance matrix.
    for i in range(max_frame + 1):
        # Get the array of detections for the current frame
        truth_curr_frame = truth_framedata.get(str(i), [])
        model_curr_frame = model_framedata.get(str(i), [])

        # Build the distance/cost matrix.
        dist_matrix = build_cost_matrix(truth_curr_frame,
                                        model_curr_frame,
                                        iou=True)

        # Get the object indices of detections for the truth and model as arrays.
        truth_indices = list(map(lambda det: int(det['id']), truth_curr_frame))
        model_indices = list(map(lambda det: int(det['id']), model_curr_frame))

        # Pass into the motmetrics accumulator, which will automatically match
        # the indices.
        acc.update(truth_indices, model_indices, dist_matrix, frameid=i)
    return acc
    def initialize_base(self, ground_truth, working_dir_path):
        # Create an accumulator that will be updated during each frame
        self.acc = mm.MOTAccumulator(auto_id=True)
        self.ground_truth = ground_truth

        if isinstance(ground_truth, str):
            self.ground_truth = pandas_loader.load_csv(working_dir_path,
                                                       ground_truth)

        self.gt_frame_numbers_cam = set(
            self.ground_truth["frame_no_cam"].tolist())

        self.gt_frame_numbers_cam = list(map(int, self.gt_frame_numbers_cam))
Exemple #24
0
def test_metrics_with_no_events():
    acc = mm.MOTAccumulator()

    mh = mm.metrics.create()
    metr = mh.compute(acc,
                      metrics=['motp', 'mota', 'num_predictions'],
                      return_dataframe=False,
                      return_cached=True)
    assert np.isnan(metr['mota'])
    assert np.isnan(metr['motp'])
    assert metr['num_predictions'] == 0
    assert metr['num_objects'] == 0
    assert metr['num_detections'] == 0
def test_ids():
    """Test metrics with frame IDs specified manually."""
    acc = mm.MOTAccumulator()

    # No data
    acc.update([], [], [], frameid=0)
    # Match
    acc.update([1, 2], [1, 2], [[1, 0], [0, 1]], frameid=1)
    # Switch also Transfer
    acc.update([1, 2], [1, 2], [[0.4, np.nan], [np.nan, 0.4]], frameid=2)
    # Match
    acc.update([1, 2], [1, 2], [[0, 1], [1, 0]], frameid=3)
    # Ascend (switch)
    acc.update([1, 2], [2, 3], [[1, 0], [0.4, 0.7]], frameid=4)
    # Migrate (transfer)
    acc.update([1, 3], [2, 3], [[1, 0], [0.4, 0.7]], frameid=5)
    # No data
    acc.update([], [], [], frameid=6)

    mh = mm.metrics.create()
    metr = mh.compute(acc,
                      return_dataframe=False,
                      return_cached=True,
                      metrics=[
                          'num_matches',
                          'num_false_positives',
                          'num_misses',
                          'num_switches',
                          'num_transfer',
                          'num_ascend',
                          'num_migrate',
                          'num_detections',
                          'num_objects',
                          'num_predictions',
                          'mota',
                          'motp',
                          'num_frames',
                      ])
    assert metr['num_matches'] == 7
    assert metr['num_false_positives'] == 0
    assert metr['num_misses'] == 0
    assert metr['num_switches'] == 3
    assert metr['num_transfer'] == 3
    assert metr['num_ascend'] == 1
    assert metr['num_migrate'] == 1
    assert metr['num_detections'] == 10
    assert metr['num_objects'] == 10
    assert metr['num_predictions'] == 10
    assert metr['mota'] == approx(1. - (0 + 0 + 3) / 10)
    assert metr['motp'] == approx(1.6 / 10)
    assert metr['num_frames'] == 7
Exemple #26
0
def idf1_score(list_gt_bboxes, tracked_detections):
    """The lists passed are of the form [label, tly, tlx, width, height, confidence, id]"""

    for frames in list_gt_bboxes:
        for element in frames:
            frame = getattr(element, 'frame')
            xtl = int(float(getattr(element, 'xtl')))
            ytl = int(float(getattr(element, 'ytl')))
            xbr = int(float(getattr(element, 'xbr')))
            ybr = int(float(getattr(element, 'ybr')))
            height = ybr - ytl
            width = xbr - xtl
            id_det = int(getattr(element, 'id'))
            if getattr(element, 'score') is None:
                confidence = np.random
            else: confidence = getattr(element, 'score')
            '''if frame == getattr(element, 'frame'):
                element.append(['car', xtl, ytl, height, width, random(), id_det])
            else:'''
            element[frame] = ['car', xtl, ytl, height, width, confidence, id_det]

    acc = mm.MOTAccumulator(auto_id=True)
    for gt_elements_frame, det_elements_frame in zip(bboxes, tracked_detections):
        det_ids = []
        gt_ids = []
        mm_det_bboxes = []
        mm_gt_bboxes = []

        for gt_bbox in gt_elements_frame:
            # mm_gt_bboxes.append([(gt_bbox[1]+gt_bbox[3])/2, (gt_bbox[2]+gt_bbox[4])/2, gt_bbox[3]-gt_bbox[1],
            #                      gt_bbox[4]-gt_bbox[2]])
            mm_gt_bboxes.append([gt_bbox[2], gt_bbox[1], gt_bbox[3], gt_bbox[4]])

            gt_ids.append(gt_bbox[-1])

        for det_bbox in det_elements_frame:
            # mm_det_bboxes.append([(det_bbox[1]+det_bbox[3])/2, (det_bbox[2]+det_bbox[4])/2, det_bbox[3]-det_bbox[1],
            #                      det_bbox[4]-det_bbox[2]])
            mm_det_bboxes.append([det_bbox[2], det_bbox[1], det_bbox[3], det_bbox[4]])

            det_ids.append(det_bbox[-1])

        distances_gt_det = mm.distances.iou_matrix(mm_gt_bboxes, mm_det_bboxes, max_iou=1.)
        acc.update(gt_ids, det_ids, distances_gt_det)

    mh = mm.metrics.create()
    summary = mh.compute(acc, metrics=['idf1'], name='acc')

    print(summary)
    return summary
Exemple #27
0
def get_MOTA_accumulator(seq_id, size_limit, tolerance, tracker_dir):

    data = get_data(seq_id, size_limit, tolerance, tracker_dir)
    # Create an accumulator that will be updated during each frame
    acc = mm.MOTAccumulator(auto_id=True)

    for frame in data:
        acc.update(
            frame[0],   # Ground truth objects in this frame
            frame[1],   # Detector hypotheses in this frame
            frame[2]    # Distances from objects to hypotheses
        )

    return acc
    def __init__(self):
        self.position_errors = []
        self.velocity_errors = []
        self.position_gt = []
        self.velocity_gt = []
        self.position_det = []
        self.velocity_det = []
        self.velocity_success = []

        self.tf_buffer = tf2_ros.Buffer()
        self.tf_listener = tf2_ros.TransformListener(self.tf_buffer)

        self.acc = mot.MOTAccumulator(auto_id=True)
        self.rc_car = OptiTrackData('rc_car', self.tf_buffer)
        self.oncoming_car = OptiTrackData('oncoming_car', self.tf_buffer)
    def initialize_base(self):
        self.load_evaluation_files()
        # Create an accumulator that will be updated during each frame
        self.acc = mm.MOTAccumulator(auto_id=True)
        self.overall_frame_count = 0

        self.gt_cams_df_frame_numbers = []
        for gt_cam_dataframe in self.ground_truth_dataframes:
            gt_cam_df_grouped = gt_cam_dataframe.groupby("frame_no_cam", as_index=False).mean()
            gt_cam_frame_numbers = gt_cam_df_grouped["frame_no_cam"].tolist()
            gt_cam_frame_numbers = list(map(int, gt_cam_frame_numbers))
            self.overall_frame_count += len(gt_cam_frame_numbers)
            self.gt_cams_df_frame_numbers.extend(gt_cam_frame_numbers)

        self.max_all_frame_numbers = max(self.gt_cams_df_frame_numbers)
        self.min_all_frame_numbers = min(self.gt_cams_df_frame_numbers)
Exemple #30
0
def test_issue19():
    acc = mm.MOTAccumulator()

    g0 = [0, 1]
    p0 = [0, 1]
    d0 = [[0.2, np.nan], [np.nan, 0.2]]

    g1 = [2, 3]
    p1 = [2, 3, 4, 5]
    d1 = [[0.28571429, 0.5, 0.0, np.nan], [ np.nan, 0.44444444, np.nan, 0.0 ]]

    acc.update(g0, p0, d0, 0)
    acc.update(g1, p1, d1, 1)

    mh = mm.metrics.create()
    result = mh.compute(acc)