Package pyvision :: Package analysis :: Module gui_tools
[hide private]
[frames] | no frames]

Source Code for Module pyvision.analysis.gui_tools

  1  # PyVision License 
  2  # 
  3  # Copyright (c) 2006-2011 David S. Bolme 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  #  
 10  # 1. Redistributions of source code must retain the above copyright 
 11  # notice, this list of conditions and the following disclaimer. 
 12  #  
 13  # 2. Redistributions in binary form must reproduce the above copyright 
 14  # notice, this list of conditions and the following disclaimer in the 
 15  # documentation and/or other materials provided with the distribution. 
 16  #  
 17  # 3. Neither name of copyright holders nor the names of its contributors 
 18  # may be used to endorse or promote products derived from this software 
 19  # without specific prior written permission. 
 20  #  
 21  #  
 22  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 23  # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 24  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 25  # A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR 
 26  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 27  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 28  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 29  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 30  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 31  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 32  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 33   
 34  ''' 
 35  Created on Oct 31, 2011 
 36   
 37  @author: bolme 
 38  ''' 
 39   
 40  import pyvision as pv 
 41  import cv 
 42  import PIL.Image as pil 
 43   
44 -def null_callback(*args,**kwargs):
45 pass
46
47 -class CaptureClicks:
48 ''' 49 This object handles the data mangagement and display of the capture clicks window. 50 ''' 51
52 - def __init__(self,im,default_points=[],keep_window_open = False,window="PyVision Capture Points"):
53 ''' 54 Initialize the data. 55 ''' 56 self.window = window 57 self.im = im.copy() 58 self.keep_window_open = keep_window_open 59 self.reset() 60 for pt in default_points: 61 self.mouseCallback(cv.CV_EVENT_LBUTTONDOWN,pt.X(),pt.Y(),None,None)
62
63 - def display(self):
64 ''' 65 Display the window and run the main event loop. 66 ''' 67 # Setup the mouse callback to handle mause events (optional) 68 cv.NamedWindow(self.window) 69 cv.SetMouseCallback(self.window, self.mouseCallback) 70 71 while True: 72 key_press = self.im.show(self.window,delay=100) 73 74 # Handle key press events. 75 if key_press == ord(' '): 76 break 77 78 if key_press == ord('r'): 79 self.reset() 80 81 if not self.keep_window_open: 82 cv.DestroyWindow(self.window) 83 84 return self.points
85
86 - def reset(self):
87 ''' 88 Clear the points and start over. 89 ''' 90 self.im = self.im.copy() 91 self.im.annotateLabel(pv.Point(10,10), "Click anywhere in the image to select a point.",color='yellow') 92 self.im.annotateLabel(pv.Point(10,20), "Press the 'r' to reset.",color='yellow') 93 self.im.annotateLabel(pv.Point(10,30), "Press the space bar when finished.",color='yellow') 94 self.points = []
95 96
97 - def mouseCallback(self, event, x, y, flags, param):
98 ''' 99 Call back function for mouse events. 100 ''' 101 if event in [cv.CV_EVENT_LBUTTONDOWN]: 102 point = pv.Point(x,y) 103 self.im.annotateLabel(point,str(len(self.points)),mark='below') 104 self.points.append(point)
105
106 -class CaptureClicksVideo:
107 ''' 108 This object handles the data mangagement and display of the capture clicks window. 109 ''' 110
111 - def __init__(self, video, buffer_size = 60, callback = None, keep_window_open=False):
112 ''' 113 Initialize the data. 114 ''' 115 self.callback = callback 116 self.video = video 117 self.points = {} 118 self.buffer = [] 119 self.frame = -1 120 self.buffer_index = -1 121 self.buffer_size = buffer_size 122 self.keep_window_open = keep_window_open 123 self.next()
124 125
126 - def display(self):
127 ''' 128 Display the window and run the main event loop. 129 ''' 130 # Setup the mouse callback to handle mause events (optional) 131 cv.NamedWindow("PyVision Capture Points") 132 133 # This next line creates a memory leak where 'self' is never released 134 # and the window cannot be closed. 135 cv.SetMouseCallback("PyVision Capture Points", self.mouseCallback) 136 137 138 while True: 139 key_press = self.im.show("PyVision Capture Points",delay=100) 140 141 # Handle key press events. 142 if key_press == ord('r'): 143 self.reset() 144 145 if key_press == ord('p'): 146 self.prev() 147 148 if key_press == ord('P'): 149 for _ in range(10): 150 self.prev() 151 152 if key_press == ord(' ') or key_press == ord('n'): 153 self.next() 154 155 if key_press == ord('N'): 156 for _ in range(10): 157 self.next() 158 159 if key_press == ord('q'): 160 break 161 162 # Reduce but does not eliminate the memory leak. 163 del self.buffer 164 165 if not self.keep_window_open: 166 cv.DestroyWindow("PyVision Capture Points") 167 168 return self.points
169
170 - def reset(self):
171 if self.points.has_key(self.frame): 172 del self.points[self.frame] 173 self.render()
174
175 - def render(self):
176 ''' 177 Clear the points and start over. 178 ''' 179 im = self.buffer[self.buffer_index] 180 w,h = im.size 181 nim = pil.new('RGB',(w,h+100)) 182 nim.paste(im.asPIL(),(0,0)) 183 self.im = pv.Image(nim) 184 185 if self.callback != None: 186 self.callback(self.im,self.frame) 187 188 self.im.annotateLabel(pv.Point(10,h+10), "Frame: %d"%self.frame,color='yellow') 189 self.im.annotateLabel(pv.Point(10,h+20), "Click anywhere in the image to select a point.",color='yellow') 190 self.im.annotateLabel(pv.Point(10,h+30), "Press 'r' to reset.",color='yellow') 191 self.im.annotateLabel(pv.Point(10,h+40), "Press the space bar or 'n' for the next frame.",color='yellow') 192 self.im.annotateLabel(pv.Point(10,h+50), "Press 'p' for the previous frame.",color='yellow') 193 self.im.annotateLabel(pv.Point(10,h+60), "Press 'N' or 'P' to skip 10 frames.",color='yellow') 194 self.im.annotateLabel(pv.Point(10,h+70), "Press 'q' when finished.",color='yellow') 195 if self.points.has_key(self.frame): 196 points = self.points[self.frame] 197 for i in range(len(points)): 198 pt = points[i] 199 self.im.annotateLabel(pt,'%d'% i,mark='below')
200
201 - def next(self):
202 if self.buffer_index == -1: 203 try: 204 self.buffer.append(self.video.next()) 205 self.frame += 1 206 except StopIteration: 207 print "End of video." 208 self.buffer = self.buffer [-self.buffer_size:] 209 else: 210 self.buffer_index += 1 211 self.frame += 1 212 213 print self.buffer_index,self.frame,len(self.buffer),self.points 214 self.render()
215 216
217 - def prev(self):
218 if self.buffer_index == -len(self.buffer): 219 print "Buffer exceed. Cannot display previous frame" 220 else: 221 self.buffer_index -= 1 222 self.frame -= 1 223 self.render()
224 225
226 - def mouseCallback(self, event, x, y, flags, param):
227 ''' 228 Call back function for mouse events. 229 ''' 230 if event in [cv.CV_EVENT_LBUTTONDOWN]: 231 if not self.points.has_key(self.frame): 232 self.points[self.frame] = [] 233 points = self.points[self.frame] 234 point = pv.Point(x,y) 235 self.im.annotateLabel(point,str(len(points)),mark='below') 236 points.append(point)
237
238 -def capturePointsFromMouse(im,*args,**kwargs):
239 ''' 240 This function opens a high gui window that displays the image. Any 241 points that are clicked will be returned after the user presses the 242 space bar. 243 244 @param im: An image to display. 245 @param default_points: Some default points to display. 246 @type default_points: list of pv.Point 247 @type default_points: list 248 @param keep_window_open: keep the window open after point were captured 249 @type True|False 250 @param window: The name of the window 251 @type window: string 252 @returns: a list of points that were clicked by the user. 253 ''' 254 if isinstance(im, pv.Image): 255 cap = CaptureClicks(im,*args,**kwargs) 256 clicks = cap.display() 257 else: 258 cap = CaptureClicksVideo(im,*args,**kwargs) 259 clicks = cap.display() 260 return clicks
261 262 263 if __name__ == '__main__': 264 #im = pv.Image(pv.TAZ_IMAGE) 265 #pv.capturePointsFromMouse(im) 266 267 video = pv.Video(pv.TAZ_VIDEO) 268 ccv = capturePointsFromMouse(video) 269