예제 #1
0
def load_predictions_csv(fp):
    '''Loads output of tracker from CSV file.

    Args:
        fp: File-like object with read() and seek().

    Returns:
        List of (time, prediction-dict) pairs.
    '''
    # has_header = csv.Sniffer().has_header(fp.read(4<<10)) # 4 kB
    # fp.seek(0)
    reader = _dict_reader_optional_fieldnames(fp, PREDICTION_FIELD_NAMES)

    predictions = util.SparseTimeSeries()
    for row in reader:
        present = util.str2bool(row['present'])
        t = int(row['frame_num'])
        predictions[t] = make_prediction(
            present=present,
            score=float(row['score']),
            xmin=float(row['xmin']) if present else None,
            xmax=float(row['xmax']) if present else None,
            ymin=float(row['ymin']) if present else None,
            ymax=float(row['ymax']) if present else None)
    return predictions
예제 #2
0
def load_dataset_annotations_csv(fp):
    '''Loads the annotations for an entire dataset from one CSV file.'''
    reader = csv.DictReader(fp, fieldnames=TRACK_FIELDS)
    rows = [row for row in reader]

    # Group rows by object.
    rows_by_track = {}
    for row in rows:
        vid_id = row['video_id']
        obj_id = row['object_id']
        rows_by_track.setdefault((vid_id, obj_id), []).append(row)

    tracks = VideoObjectDict()
    for vid_obj in rows_by_track.keys():
        # vid_id, obj_id = vid_obj
        frames = util.SparseTimeSeries()
        for row in rows_by_track[vid_obj]:
            present = _parse_is_present(row['object_presence'])
            # TODO: Support 'exemplar' field in CSV format?
            t = int(row['frame_num'])
            frames[t] = make_frame_label(
                present=present,
                xmin=float(row['xmin']) if present else None,
                xmax=float(row['xmax']) if present else None,
                ymin=float(row['ymin']) if present else None,
                ymax=float(row['ymax']) if present else None)
        assert len(frames) >= 2
        first_row = rows_by_track[vid_obj][0]
        tracks[vid_obj] = make_track_label(
            category=first_row['class_name'],
            frames=frames,
            contains_cuts=first_row['contains_cuts'],
            always_visible=first_row['always_visible'])

    return tracks
예제 #3
0
def make_task_from_track(track):
    '''Creates a tracking task from a track annotation dict (oxuva.annot.make_track_label).

    The first frame is adopted as initialization.
    The remaining frames become the ground-truth rectangles.
    '''
    frames = list(track['frames'].sorted_items())
    init_time, init_annot = frames[0]
    labels = util.SparseTimeSeries(frames[1:])
    # TODO: Check that init_annot['exemplar'] is True.
    init_rect = {k: init_annot[k] for k in ['xmin', 'xmax', 'ymin', 'ymax']}
    attributes = {k: v for k, v in track.items() if k not in {'frames'}}
    return Task(init_time, init_rect, labels=labels, attributes=attributes)
예제 #4
0
def assess_sequence(gt, pred, iou_threshold):
    '''Evaluate predicted track against ground-truth annotations.

    Args:
        gt: SparseTimeSeries of annotation dicts.
        pred: SparseTimeSeries of prediction dicts.
        iou_threshold: Threshold for determining true positive.

    Returns:
        An assessment of each frame with ground-truth.
        This is a TimeSeries of frame assessment dicts.
    '''
    times = gt.sorted_keys()
    # if pred.sorted_keys() != times:
    pred = subset_using_previous_if_missing(pred, times)
    return util.SparseTimeSeries({t: assess_frame(gt[t], pred[t], iou_threshold) for t in times})
예제 #5
0
def subset_using_previous_if_missing(series, times):
    '''Extracts a subset of values at the given times.
    If there is no data for a particular time, then the last value is used.

    Args:
        series: SparseTimeSeries of data.
        times: List of times.

    Returns:
        Time series sampled at specified times.

    Examples:
        >> subset_using_previous_if_missing([(2, 'hi'), (4, 'bye')], [2, 3, 4, 5])
        ['hi', 'hi', 'bye', 'bye']

    Raises an exception if asked for a time before the first element in series.
    '''
    assert isinstance(series, util.SparseTimeSeries)
    series = list(series.sorted_items())
    subset = [None for _ in times]
    t_curr, x_curr = None, None
    for i, t in enumerate(times):
        # Read from series until we have read all elements <= t.
        read_all = False
        while not read_all:
            if len(series) == 0:
                read_all = True
            else:
                # Peek at next element.
                t_next, x_next = series[0]
                if t_next > t:
                    # We have gone past t.
                    read_all = True
                else:
                    # Keep going.
                    t_curr, x_curr = t_next, x_next
                    series = series[1:]
        if t_curr is None:
            raise ValueError('no value for time: {}'.format(t))
        if t_curr != t:
            logger.warning(
                'no prediction for time %d: use prediction for time %s', t,
                t_curr)
        subset[i] = x_curr
    return util.SparseTimeSeries(zip(times, subset))
예제 #6
0
 def test_idempotent(self):
     source = util.SparseTimeSeries({1: 'one', 3: 'three'})
     times = [1, 2, 3, 4]
     once = subset_using_previous_if_missing(source, times)
     twice = subset_using_previous_if_missing(once, times)
     self.assertEqual(list(once.sorted_items()), list(twice.sorted_items()))
예제 #7
0
 def test_before_start(self):
     source = util.SparseTimeSeries({3: 'three'})
     times = [1, 2, 3]
     self.assertRaises(
         Exception, lambda: subset_using_previous_if_missing(source, times))
예제 #8
0
 def test_beyond_end(self):
     source = util.SparseTimeSeries({1: 'one', 3: 'three'})
     times = [2, 4, 6]
     got = subset_using_previous_if_missing(source, times)
     want = [(2, 'one'), (4, 'three'), (6, 'three')]
     self.assertEqual(list(got.sorted_items()), want)
예제 #9
0
 def test_missing(self):
     source = util.SparseTimeSeries({1: 'one', 3: 'three'})
     times = [1, 2, 3]
     got = subset_using_previous_if_missing(source, times)
     want = [(1, 'one'), (2, 'one'), (3, 'three')]
     self.assertEqual(list(got.sorted_items()), want)