1 '''
2 Created on Oct 22, 2010
3 @author: Stephen O'Hara
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 import scipy as sp
38 import pyvision as pv
39
41 '''
42 Stores a limited number of images from a video (or any other source)
43 Makes it easy to do N-frame-differencing, for example, by easily being
44 able to get the current (middle) frame, plus the first and last frames of the
45 buffer. With an ImageBuffer of size N, as images are added, eventually the
46 buffer fills, and older items are dropped off the end. This is convenient
47 for streaming input sources, as the user can simply keep adding images
48 to this buffer, and internally, the most recent N will be kept available.
49 '''
50
52 '''
53 @param N: how many image frames to buffer
54 '''
55 self._data = [None for _ in xrange(N)]
56 self._count = 0
57 self._max = N
58
60 return self._data[key]
61
63 '''
64 This is a fixed-sized ring buffer, so length is always the number
65 of images that can be stored in the buffer (as initialized with Nframes)
66 '''
67 return self._max
68
70 if self._count == self._max:
71 return True
72 else:
73 return False
74
76 self._data = [None for _ in xrange(self._max)]
77 self._count = 0
78
80 '''
81 Note that getCount() differs from __len__() in that this method returns the number of
82 image actually stored in the ImageBuffer, while __len__() returns the size of the buffer,
83 defined as the number of images the buffer is allowed to store.
84 '''
85 return self._count
86
89
92
95
97 mid = int(self._count/2)
98 return self._data[mid]
99
100 - def add(self, image):
101 '''
102 add an image to the buffer, will kick out the oldest of the buffer is full
103 @param image: image to add to buffer
104 '''
105 self._data.pop(0)
106 self._data.append(image)
107 self._count += 1
108 if(self._count > self._max):
109 self._count = self._max
110
112 '''
113 If buffer is empty, you can use this function to spool off the first
114 N frames of a video or list of images to initialize/fill the buffer.
115 @param v: Either a list of pv.Images, an instance of pv.Video or its
116 subclass, or any other iterable that yields a pv.Image() when
117 next() is called.
118 @note: Will cause an assertion exception if buffer is already full.
119 '''
120 assert not self.isFull()
121
122 if type(v) == list:
123
124 idxs = range(len(v))
125 V = ( v[i] for i in idxs)
126 else:
127 V = v
128
129 while not self.isFull():
130 im = V.next()
131 self.add(im)
132
133 return
134
136 '''
137 Outputs an image buffer as a 3D numpy array ("stack") of grayscale images.
138 @param size: A tuple (w,h) indicating the output size of each frame.
139 If None, then the size of the first image in the buffer will be used.
140 @return: a 3D array (stack) of the gray scale version of the images
141 in the buffer. The dimensions of the stack are (N,w,h), where N is
142 the number of images (buffer size), w and h are the width and height
143 of each image.
144 '''
145 if size==None:
146 img0 = self[0]
147 (w,h) = img0.size
148 else:
149 (w,h) = size
150
151 f = self.getCount()
152 stack = sp.zeros((f,w,h))
153 for i,img in enumerate(self._data):
154
155 sz = img.size
156 if (w,h) != sz:
157 img2 = img.resize((w,h))
158 mat = img2.asMatrix2D()
159 else:
160 mat = img.asMatrix2D()
161 stack[i,:,:] = mat
162
163 return stack
164
165 - def asMontage(self, layout, tile_size=None, **kwargs):
166 (w,h) = self[0].size
167 if tile_size == None:
168 tw = w/5
169 th = h/5
170 if tw < 32: tw=32
171 if th < 24: th=24
172 tile_size = (tw,th)
173
174 im = pv.ImageMontage(self._data, layout=layout, tile_size=tile_size, **kwargs)
175 return im
176
177 - def show(self, N=10, window="Image Buffer", pos=None, delay=0):
178 '''
179 @param N: The number of images in the buffer to display at once
180 @param window: The window name
181 @param pos: The window position
182 @param delay: The window display duration
183 '''
184 if self[0] == None: return
185
186 if N <= self._count:
187 im = self.asMontage(layout=(1,N))
188 else:
189 im = self.asMontage(layout=(1,self._count))
190 im.show(window, pos, delay)
191
192
193