예제 #1
0
    def test_bounds_inheritance(self):
        from rekall.predicates import overlaps

        class Bounds2D(Bounds):
            def __init__(self, t1, t2, x1, x2):
                self.data = {'t1': t1, 't2': t2, 'x1': x1, 'x2': x2}

            def __lt__(self, other):
                return ((self['t1'], self['t2'], self['x1'], self['x2']) <
                        (other['t1'], other['t2'], other['x1'], other['x2']))

            def primary_axis(self):
                return ('t1', 't2')

            def X(pred):
                return Bounds.cast({'t1': 'x1', 't2': 'x2'})(pred)

        bounds1 = Bounds2D(0, 1, 0.5, 0.7)
        bounds2 = Bounds2D(2, 3, 0.4, 0.6)

        # overlaps expects two objects with fields 't1' and 't2' and
        #   computes whether there is overlap in that dimension

        # This is False, since there is no time overlap
        self.assertFalse(overlaps()(bounds1, bounds2))

        # This is True, since there is overlap in the X dimension
        self.assertTrue(Bounds2D.X(overlaps())(bounds1, bounds2))

        # This is True.
        self.assertTrue(bounds1 < bounds2)

        # This returns ('t1', 't2')
        self.assertEqual(bounds1.primary_axis(), ('t1', 't2'))
예제 #2
0
def main():
    '''
    An example of a join. We filter pairs based on time overlap, and merge
    surviving pairs by taking the intersection over the time bounds and the
    span of the spatial bounds (and adding the payloads).
    '''

    is1 = IntervalSet([
        Interval(Bounds3D(0, 1, 0, 1, 0, 1), 1),
        Interval(Bounds3D(0, 0.5, 0.5, 1, 0, 0.5), 2),
    ])
    is2 = IntervalSet([
        Interval(Bounds3D(0.5, 1, 0, 1, 0, 1), 4),
        Interval(Bounds3D(0, 1, 0, 1, 0, 1), 8),
    ])
    is3 = is1.join(
        is2, Bounds3D.T(overlaps()), lambda i1, i2: Interval(
            i1['bounds'].intersect_time_span_space(i2['bounds']), i1['payload']
            + i2['payload']))

    print('is1:')
    print(is1)
    print('is2:')
    print(is2)

    print('is1 joined with is2:')
    print(is3)
예제 #3
0
 def test_collect_by_interval(self):
     c = TestIntervalSetMapping.get_collection()
     d = IntervalSetMapping({1: IntervalSet([
             Interval(Bounds3D(t,t)) for t in range(1, 100)])})
     e = c.collect_by_interval(d, Bounds3D.T(overlaps()),
             filter_empty=False, window=0)
     self.assertEqual(e.keys(), c.keys())
예제 #4
0
    def fold_fn(stack, interval):
        if interval['t2'] - interval['t1'] > MAX_COMMERCIAL_TIME:
            interval = Interval(
                Bounds3D(interval['t1'], interval['t1'] + MAX_COMMERCIAL_TIME))

        if len(stack) == 0:
            stack.append(interval)
        else:
            last = stack.pop()
            if or_pred(overlaps(),
                       after(max_dist=COMMERCIAL_FOLD_EPSILON))(interval,
                                                                last):
                if last['bounds'].span(interval['bounds']).size() \
                        > MAX_COMMERCIAL_TIME:
                    stack.append(
                        Interval(
                            Bounds3D(last['t1'],
                                     last['t1'] + MAX_COMMERCIAL_TIME)))
                else:
                    stack.append(
                        Interval(last['bounds'].span(interval['bounds'])))
            else:
                stack.append(last)
                stack.append(interval)

        return stack
예제 #5
0
def tiou(box1, box2) -> float:
    # IoU in t1, t2
    if not overlaps()(box1, box2):
        return 0

    U = max(box1['t2'], box2['t2']) - min(box1['t1'], box2['t1'])
    I = (box1['t2'] - box1['t1']) + (box2['t2'] - box2['t1']) - U
    assert U >= 0 and I >= 0
    return I / U
예제 #6
0
    def intersect(self, other):
        """Returns the bound intersecting ``self`` and ``other``, or
        ``None`` if the bounds do not overlap.

        Returns:
            A single Bounds1D covering the intersection of ``self`` and
            ``other``, or ``None`` if the two bounds do not overlap.
        """
        if overlaps()(self, other):
            return Bounds1D.fromTuple(
                utils.bounds_intersect((self['t1'], self['t2']),
                                       (other['t1'], other['t2'])))
        else:
            return None
예제 #7
0
    def intersect_time_span_space(self, other):
        """Returns the bound intersecting ``other`` in time and spanning
        ``self`` and ``other`` in space. Returns ``None`` if ``self`` and
        ``other`` do not overlap in time.

        Returns:
            A single Bounds3D at the intersection of ``self`` and ``other`` in
            time but spanning them in space, or ``None`` if they do not
            overlap in time.
        """
        if overlaps()(self, other):
            return self.combine_per_axis(other, utils.bounds_intersect,
                                         utils.bounds_span, utils.bounds_span)
        else:
            return None
예제 #8
0
def main():
    '''
    Some examples of coalesce -- recursively merging overlapping or touching
    intervals.
    '''

    is1 = IntervalSet([
        Interval(Bounds3D(1, 10, 0.3, 0.4, 0.5, 0.6), 1),
        Interval(Bounds3D(2, 5, 0.2, 0.8, 0.2, 0.3), 1),
        Interval(Bounds3D(10, 11, 0.2, 0.7, 0.3, 0.5), 1),
        Interval(Bounds3D(13, 15, 0.5, 1, 0, 0.5), 1),
        Interval(Bounds3D(15, 19, 0.5, 1, 0, 0.5), 1),
        Interval(Bounds3D(20, 20), payload=1),
        Interval(Bounds3D(22, 22), payload=1),
        Interval(Bounds3D(22, 23), payload=1),
    ])
    is1_coalesced = is1.coalesce(('t1', 't2'), Bounds3D.span, payload_plus)

    # target1 is the same as is1_coalesced
    target1 = IntervalSet([
        Interval(Bounds3D(1, 11, 0.2, 0.8, 0.2, 0.6), 3),
        Interval(Bounds3D(13, 19, 0.5, 1, 0, 0.5), 2),
        Interval(Bounds3D(20, 20), payload=1),
        Interval(Bounds3D(22, 23), payload=2),
    ])

    is1_coalesced_larger_epsilon = is1.coalesce(('t1', 't2'),
                                                Bounds3D.span,
                                                payload_plus,
                                                epsilon=2)

    # target2 is the same as is1_coalesced_larger_epsilon
    target2 = IntervalSet([Interval(Bounds3D(1, 23), payload=8)])

    is2 = IntervalSet([
        Interval(Bounds3D(2, 5, 0.2, 0.8, 0.2, 0.4), 1),
        Interval(Bounds3D(1, 10, 0.3, 0.4, 0.3, 0.6), 1),
        Interval(Bounds3D(9, 11, 0.16, 0.17, 0.3, 0.5), 1),
        Interval(Bounds3D(13, 15, 0.5, 1, 0, 0.5), 1),
        Interval(Bounds3D(14, 19, 0.5, 1, 0, 0.5), 1),
    ])
    is2_coalesced_overlapping_bboxes = is2.coalesce(
        ('t1', 't2'),
        Bounds3D.span,
        payload_plus,
        predicate=and_pred(Bounds3D.X(overlaps()), Bounds3D.Y(overlaps())))

    # target3 is the same as is2_coalesced_overlapping_bboxes
    target3 = IntervalSet([
        Interval(Bounds3D(1, 10, 0.2, 0.8, 0.2, 0.6), 2),
        Interval(Bounds3D(9, 11, 0.16, 0.17, 0.3, 0.5), 1),
        Interval(Bounds3D(13, 19, 0.5, 1, 0, 0.5), 2),
    ])

    print('is1:')
    print(is1)
    print()

    print('is1 coalesced:')
    print(is1_coalesced)
    print()

    print('is1_coalesced_larger_epsilon:')
    print(is1_coalesced_larger_epsilon)
    print()

    print('is2:')
    print(is2)
    print()

    print('is2 coalesced with overlapping bounding boxes:')
    print(is2_coalesced_overlapping_bboxes)
예제 #9
0
def detect_commercials(black_frames, captions, whole_video, params=None):
    """
    ---

    Arguments:
        captions (IntervalSet):
        black_frames (IntervalSet):
        whole_video (IntervalSet):
        params (dict):

    Returns:
        IntervalSet of commercials (in seconds).
    """

    black_windows = black_frames.coalesce(('t1', 't2'),
                                          Bounds3D.span,
                                          epsilon=BLACK_FRAME_COALESCE_EPSILON)

    caption_intervals = captions.filter(lambda x: '{' not in x['payload'])

    arrow_intervals = caption_intervals.filter(lambda x: '>>' in x['payload'])
    arrow_announcer_intervals = caption_intervals.filter(
        lambda x: '>> Announcer:' in x['payload'])
    arrow_having_intervals = caption_intervals.filter(
        lambda x: '>> HAVING' in x['payload'])

    caption_intervals = caption_intervals.coalesce(
        ('t1', 't2'), Bounds3D.span, epsilon=CAPTIONS_COALESCE_EPSILON)

    reliable_captions = caption_intervals.filter_size(
        min_size=RELIABLE_TEXT_DURATION)

    arrow_intervals = arrow_intervals.minus(arrow_announcer_intervals).minus(
        arrow_having_intervals).filter_against(reliable_captions,
                                               predicate=overlaps())

    # Find commercial blocks
    all_blocks = whole_video.minus(black_windows)
    non_commercial_blocks = all_blocks.filter_against(arrow_intervals,
                                                      predicate=overlaps())
    commercial_blocks = whole_video.minus(
        non_commercial_blocks.union(black_windows))

    def fold_fn(stack, interval):
        if interval['t2'] - interval['t1'] > MAX_COMMERCIAL_TIME:
            interval = Interval(
                Bounds3D(interval['t1'], interval['t1'] + MAX_COMMERCIAL_TIME))

        if len(stack) == 0:
            stack.append(interval)
        else:
            last = stack.pop()
            if or_pred(overlaps(),
                       after(max_dist=COMMERCIAL_FOLD_EPSILON))(interval,
                                                                last):
                if last['bounds'].span(interval['bounds']).size() \
                        > MAX_COMMERCIAL_TIME:
                    stack.append(
                        Interval(
                            Bounds3D(last['t1'],
                                     last['t1'] + MAX_COMMERCIAL_TIME)))
                else:
                    stack.append(
                        Interval(last['bounds'].span(interval['bounds'])))
            else:
                stack.append(last)
                stack.append(interval)

        return stack

    commercials = commercial_blocks.fold_to_set(
        fold_fn, init=[]).filter_size(min_size=MIN_COMMERCIAL_TIME)
    commercials_orig = commercials

    def is_lower_text(obj):
        alpha = [c for c in obj['payload'] if c.isalpha()]
        if not alpha:
            return False

        lower = [c for c in alpha if c.islower()]
        return len(lower) / len(alpha) > MIN_LOWERTEXT

    lowercase_intervals = captions.filter(is_lower_text).coalesce(
        ('t1', 't2'),
        Bounds3D.span,
        payload_merge_op=lambda a, b: a + ' ' + b,
        epsilon=LOWERCASE_COALESCE_EPSILON).filter_size(
            min_size=MIN_LOWERWINDOW)

    commercials = commercials.union(lowercase_intervals)

    blank_intervals = whole_video.minus(caption_intervals).filter_size(
        min_size=MIN_BLANKWINDOW, max_size=MAX_BLANKWINDOW).minus(
            whole_video.map(lambda x: Interval(Bounds3D(x['t2'] - 60, x['t2']))
                            )).filter_size(min_size=MIN_BLANKWINDOW)

    commercials = commercials.union(blank_intervals)

    commercials = commercials.coalesce(
        ('t1', 't2'), Bounds3D.span, epsilon=MAX_MERGE_GAP).filter_size(
            max_size=MAX_COMMERCIAL_TIME).union(commercials_orig).union(
                lowercase_intervals).union(blank_intervals).coalesce(
                    ('t1', 't2'), Bounds3D.span)

    return commercials