File size: 4,852 Bytes
96d549d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import cv2


class Timeline(object):
    """
    The Timeline represents a logical sequence of frames, where the
    rendering of frames from the video stream will be done through
    lazy evaluation.
    """
    reader_head = 0

    def __init__(self, stream):
        """
        Default Initializer
        :param stream: the video stream from OpenCV
        """
        self.stream = stream
        self.len = stream.get(cv2.CAP_PROP_FRAME_COUNT)
        self.fps = stream.get(cv2.CAP_PROP_FPS)

    def next_frame(self):
        """
        This method reads the next frame from the video stream and
        append it to the rendered_frames list. It also increments the
        reader_head by 1.
        :return: Usually the recently evaluated frame.
        If the video stream has been completely read, it will return
        None
        """
        ret, frame = self.stream.read()
        self.reader_head += 1

        if not ret:
            return None

        return frame

    def get_frame(self, pos):
        """
        Returns the frame at the given position of the frame sequence
        :param pos: the position of the frame in the sequence
        :return: the frame at the specified position
        """
        assert pos >= 0
        self.stream.set(cv2.CAP_PROP_POS_FRAMES, self.len - 1)
        _, frame = self.stream.read()
        self.reader_head = pos + 1
        return frame

    def get_frames(self, start, end):
        """
        Returns the list of frames at between the specified start and
        end position in the frame sequence.
        :param start: Where the frame sequence should start
        :param end: Where the frame sequence should end
        :return: the frame sequence from start to end
        """
        assert end >= start
        assert start >= 0

        result = []
        for i in xrange(start, end, 1):
            result.append(self.get_frame(i))
        return result

    def release_stream(self):
        self.stream.release()


class SlidingWindow(object):
    """
    This class represents an adaptive sliding window. Meaning
    that it has a pointer to the start position of the window
    and its size. The size of the window can be changed at any
    time. Move operations and shrink and expand operations are
    included.
    """

    def __init__(self, timeline, pos=0, size=2):
        """
        Default Initializer for the sliding window
        :param timeline: the timeline where the sliding window
        should be applied
        :param pos: the position where the beginning of the
        window points to
        :param size: the size of the window
        """
        self.timeline = timeline
        self.pos = pos
        self.size = size

    def move_right(self):
        """
        This method does this:
        β–‘|β–‘|β–ˆ|β–ˆ|β–‘|β–‘ => β–‘|β–‘|β–‘|β–ˆ|β–ˆ|β–‘
        1 2 3 4 5 6    1 2 3 4 5 6
        :return: the changed list of frame
        """
        self.pos += 1

    def move_left(self):
        """
        This method does this:
        β–‘|β–‘|β–ˆ|β–ˆ|β–‘|β–‘ => β–‘|β–ˆ|β–ˆ|β–‘|β–‘|β–‘
        1 2 3 4 5 6    1 2 3 4 5 6
        :return: the changed list of frame
        """
        self.pos -= 1

    def shrink_from_left(self):
        """
        This method does this:
        β–‘|β–‘|β–ˆ|β–ˆ|β–‘|β–‘ => β–‘|β–‘|β–‘|β–ˆ|β–‘|β–‘
        1 2 3 4 5 6    1 2 3 4 5 6
        :return: the changed list of frame
        """
        self.pos += 1
        self.size -= 1

    def shrink_from_right(self):
        """
        This method does this:
        β–‘|β–‘|β–ˆ|β–ˆ|β–‘|β–‘ => β–‘|β–‘|β–ˆ|β–‘|β–‘|β–‘
        1 2 3 4 5 6    1 2 3 4 5 6
        :return: the changed list of frame
        """
        self.size -= 1

    def expand_to_left(self):
        """
        This method does this:
        β–‘|β–‘|β–ˆ|β–ˆ|β–‘|β–‘ => β–‘|β–ˆ|β–ˆ|β–ˆ|β–‘|β–‘
        1 2 3 4 5 6    1 2 3 4 5 6
        :return: the changed list of frame
        """
        self.pos -= 1
        self.size += 1

    def expand_to_right(self):
        """
        This method does$$ this:
        β–‘|β–‘|β–ˆ|β–ˆ|β–‘|β–‘ => β–‘|β–‘|β–ˆ|β–ˆ|β–ˆ|β–‘
        1 2 3 4 5 6    1 2 3 4 5 6
        :return: the changed list of frame
        """
        self.size += 1

    def get_frames(self):
        """
        Retrieves all the frames that are currently in this adaptive
        sliding window.
        :return: the frames in the sliding window
        """
        return self.timeline.get_frames(self.pos, self.pos + self.size)

    def get_frame(self, pos):
        return self.timeline.get_frame(self.pos)

    def get_start_frame(self):
        return self.timeline.get_frame(self.pos)

    def get_end_frame(self):
        return self.timeline.get_frame(self.pos + self.size - 1)

    def at_end(self):
        return self.pos + self.size == self.timeline.len