Package pyvision :: Package types :: Module Video
[hide private]
[frames] | no frames]

Source Code for Module pyvision.types.Video

  1  # PyVision License 
  2  # 
  3  # Copyright (c) 2006-2008 David S. Bolme, Stephen O'Hara 
  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  import time 
 35  import os 
 36  import pyvision as pv 
 37  import cv 
 38  import random 
 39  #from scipy import weave 
 40   
 41   
 42   
43 -class VideoInterface(object):
44 ''' 45 VideoInterface is an abstract class meant only to define a common interface 46 for all Video subtypes. The VideoInterface defines the methods that every 47 video data source should provide. 48 '''
49 - def query(self):
50 ''' 51 Must be overridden to implement the specific frame-grabbing required 52 by different video sources. 53 ''' 54 raise NotImplemented
55
56 - def grab(self):
57 ''' 58 This is a placeholder for the open cv webcam interface that sometimes 59 requires this call. 60 ''' 61 pass
62
63 - def next(self):
64 ''' 65 The next method calls self.query(), so it is common to most video sources 66 and may not need to be overridden. 67 @return: The next frame in the sequence, or raise StopIteration if done. 68 ''' 69 frame = self.query() 70 if frame == None: 71 raise StopIteration("End of video sequence") 72 return frame
73
74 - def resize(self,frame):
75 ''' 76 Used to resize the source frame to the desired output size. This 77 method is common to most sources and may not need to be overridden. 78 The query() method will typically call this resize() method prior 79 to returning the captured image. 80 @param frame: An openCV image (note: not a pyvision image) 81 @return: An openCV image with the new dimensions 82 ''' 83 if self.size == None: 84 return frame 85 else: 86 depth = frame.depth 87 channels = frame.channels 88 w,h = self.size 89 resized = cv.CreateImage( (w,h), depth, channels ) 90 cv.Resize( frame, resized, cv.CV_INTER_LINEAR ) 91 return resized
92
93 - def __iter__(self):
94 ''' 95 Override to provide an appropriate iterator for your video source 96 so that it can be used in a for loop as "for im in videoX: ..." 97 ''' 98 raise NotImplemented
99
100 - def play(self, window="Input", pos=None, delay=20, 101 annotate=True, imageBuffer=None, startframe=0, endframe=None, 102 onNewFrame=None, **kwargs ):
103 ''' 104 Plays the video, calling the onNewFrame function after loading each 105 frame from the video. The user may interrupt video playback by 106 hitting (sometimes repeatedly) the spacebar, upon which they are 107 given a text menu in the console to abort program, quit playback, 108 continue playback, or step to the next frame. 109 @param window: The window name used to display the video. If None, 110 then the video won't be shown, but onNewFrame will be called at 111 each frame. 112 @param pos: A tuple (x,y) where the output window should be located 113 on the users screen. None indicates default openCV positioning algorithm 114 will be used. 115 @param delay: The delay in ms between window updates. This allows the user 116 to control the playback frame rate. A value of 0 indicates that the video 117 will wait for keyboard input prior to advancing to the next frame. This 118 delay is used by the pauseAndPlay interface, so it will affect the rate 119 at which onNewFrame is called as well. 120 @param annotate: If True, the image will be annotated with the frame number 121 in the upper left corner. Set false for no frame number annotation. 122 @param imageBuffer: An optional pyvision ImageBuffer object to contain the 123 most recent frames. This is useful if a buffer is required for background 124 subtraction, for example. The buffer contents is directly modified each 125 time a new image is captured from the video, and a reference to the buffer 126 is passed to the onNewFrame function (defined below). 127 @param startframe: If > 0, then the video will cue itself by quickly fast-forwarding 128 to the desired start frame before any images are shown. During the cueing process, 129 any _onNewFrame function callbacks (or VideoStreamProcessor objects) will NOT be 130 activated. 131 @param endframe: If not None, then the playback will end after this frame has 132 been processed. 133 @param onNewFrame: A python callable object (function) with a 134 signature of 'foo( pvImage, frameNum, key=None, buffer=None )', where key is 135 the key pressed by the user (if any) during the pauseAndPlay interface, and 136 buffer is a reference to the optional image buffer provided to the play method. 137 @param kwargs: Optional keyword arguments that should be passed 138 onto the onNewFrame function. 139 @return: The final frame number of the video, or the frame number at which 140 the user terminated playback using the 'q'uit option. 141 ''' 142 fn = -1 143 vid = self 144 if delay==0: 145 delayObj = {'wait_time':20, 'current_state':'PAUSED'} 146 else: 147 delayObj = {'wait_time':delay, 'current_state':'PLAYING'} 148 key='' 149 for fn, img in enumerate(vid): 150 if fn == 0 and startframe > 0: print "Cueing video to start at %d"%startframe 151 if fn < startframe: continue 152 if not endframe is None and fn > endframe: break 153 154 if imageBuffer != None: 155 imageBuffer.add(img) 156 157 if annotate: 158 pt = pv.Point(10, 10) 159 img.annotateLabel(label="Frame: %d"%(fn+1), point=pt, color="white", background="black") 160 161 if window != None: 162 img.show(window=window,pos=pos,delay=1) 163 164 if onNewFrame != None: 165 onNewFrame( img, fn, key=key, imageBuffer=imageBuffer, **kwargs ) 166 167 key = self._pauseAndPlay(delayObj) 168 if key == 'q': break #user selected quit playback 169 170 if window != None: cv.DestroyWindow(window) 171 return(fn)
172
173 - def _pauseAndPlay(self,delayObj={'wait_time':20, 'current_state':'PLAYING'}):
174 ''' 175 This function is intended to be used in the playback loop of a video. 176 It allows the user to interrupt the playback to pause the video, to 177 step through it one frame at a time, and to register other keys/commands 178 that the user may select. 179 @param delayObj: The "delay object", which is just a dictionary that 180 specifies the wait_time (the delay in ms between frames), and 181 the current_state of either 'PLAYING' or 'PAUSED' 182 ''' 183 state = delayObj['current_state'] 184 wait = delayObj['wait_time'] 185 #print state, wait 186 187 if state=="PAUSED": 188 print "PAUSED: Select <a>bort program, <q>uit playback, <c>ontinue playback, or <s>tep to next frame." 189 wait = 0 190 191 c = cv.WaitKey(wait) 192 c = c & 127 #bit mask to get only lower 8 bits 193 194 #sometimes a person has to hold down the spacebar to get the input 195 # recognized by the cv.WaitKey() within the short time limit. So 196 # we need to 'soak up' these extra inputs when the user is still 197 # holding the spacebar, but we've gotten into the pause state. 198 while c==ord(' '): 199 print "PAUSED: Select <a>bort program, <q>uit playback, <c>ontinue playback, or <s>tep to next frame." 200 c = cv.WaitKey(0) 201 c = c & 127 #bit mask to get only lower 8 bits 202 203 #At this point, we have a non-spacebar input, so process it. 204 if c == ord('a'): #abort 205 print "User Aborted Program." 206 raise SystemExit 207 elif c == ord('q'): #quit video playback 208 return 'q' 209 elif c == ord('c'): #continue video playback 210 delayObj['current_state'] = "PLAYING" 211 return 'c' 212 elif c == ord('s'): #step to next frame, keep in paused state 213 delayObj['current_state'] = "PAUSED" 214 return 's' 215 else: #any other keyboard input is just returned 216 #delayObj['current_state'] = "PAUSED" 217 return chr(c)
218 219 # TODO: The default camera on linux appears to be zero and 1 on MacOS 220 # svohara note on above...I'm not sure this is true. As of OpenCV 2.2 on my iMac, 221 # the built-in webcam is index 0. 222 223 # Video capture is an alterative for windows http://videocapture.sourceforge.net/ 224 # An option for linux http://code.google.com/p/python-video4linux2/ 225 # On linux it may be possible to use something like v4lctl to capture in a separate process.
226 -class Webcam(VideoInterface):
227 - def __init__(self,camera_num=0,size=(640,480),flipped=False):
228 ''' 229 Web camera interface for cameras attached to your computer via USB or built-in. 230 For IP/network cameras, use the Video object instead. 231 @param camera_num: The camera index. Usually 0 if you only have a single webcam 232 on your computer. See the OpenCV highgui documentation for details. 233 @param flipped: Set to true if camera is installed upside-down. 234 ''' 235 self.cv_capture = cv.CreateCameraCapture( camera_num ) 236 self.flipped = flipped 237 #cv.SetCaptureProperty(self.cv_capture,cv.CV_CAP_PROP_FRAME_WIDTH,1600.0) 238 #cv.SetCaptureProperty(self.cv_capture,cv.CV_CAP_PROP_FRAME_HEIGHT,1200.0) 239 #print cv.GetCaptureProperty(self.cv_capture,cv.CV_CAP_PROP_FRAME_WIDTH) 240 # print cv.GetCaptureProperty(self.cv_capture,cv.CV_CAP_PROP_FRAME_HEIGHT) 241 self.size = size
242
243 - def __iter__(self):
244 ''' Return an iterator for this video ''' 245 return self
246
247 - def query(self):
248 ''' 249 The returned image also include a field named orig_frame which returns 250 the original image returned before rescaling. 251 252 @returns: the frame rescaled to a given size. 253 ''' 254 # TODO: Video capture is unreliable under linux. This may just be a timing issue when running under parallels. 255 frame = cv.QueryFrame( self.cv_capture ) 256 if self.flipped: 257 cv.Flip(frame,frame,-1) 258 im = pv.Image(self.resize(frame)) 259 im.orig_frame = pv.Image(frame) 260 im.capture_time = time.time() 261 return im
262
263 - def grab(self):
264 return cv.GrabFrame( self.cv_capture );
265
266 - def retrieve(self):
267 ''' 268 The returned image also include a field named orig_frame which returns 269 the original image returned before rescaling. 270 271 @returns: the frame rescaled to a given size. 272 ''' 273 frame = cv.RetrieveFrame( self.cv_capture ); 274 im = pv.Image(self.resize(frame)) 275 im.orig_frame = pv.Image(frame) 276 return im
277 278
279 -class Video(VideoInterface):
280 - def __init__(self,filename,size=None):
281 ''' 282 The basic video class that is used to play back a movie file. 283 @param filename: The full path name of the video file including extension. Also, with 284 current versions of OpenCV, this can be a url to a network IP camera, but you will need 285 to consult your IP camera manufacturer's documentation as url formats vary. 286 @note: The following is an example of using the Video class with an IP camera. 287 The rtsp url is for a linksys WVC54GCA IP camera. The ip address will need to be changed 288 as appropriate for your local network. Other model cameras use different urls. It can take 289 a few seconds for the feed to be established. 290 cam_url = "rtsp://192.168.2.55/img/video.sav" 291 vid = Video(cam_url) 292 vid.play() 293 ''' 294 self.filename = filename 295 self.cv_capture = cv.CaptureFromFile( filename ); 296 self._numframes = cv.GetCaptureProperty(self.cv_capture,cv.CV_CAP_PROP_FRAME_COUNT) 297 self.size = size 298 self.current_frame = 0
299
300 - def query(self):
301 if self.current_frame > 0 and cv.GetCaptureProperty(self.cv_capture,cv.CV_CAP_PROP_POS_AVI_RATIO) == 1.0: 302 return None 303 frame = cv.QueryFrame( self.cv_capture ) 304 if frame == None: 305 raise StopIteration("End of video sequence") 306 self.current_frame += 1 307 frame = cv.CloneImage(frame); 308 return pv.Image(self.resize(frame))
309
310 - def setFrame(self,n):
311 assert n >= 0 and n <= 1 312 cv.SetCaptureProperty(self.cv_capture, cv.CV_CAP_PROP_POS_AVI_RATIO, float(n))
313 314
315 - def __iter__(self):
316 ''' Return an iterator for this video ''' 317 return Video(self.filename,self.size)
318
319 - def __len__(self):
320 return self._numframes
321 322 323
324 -class VideoFromFileList(VideoInterface):
325 ''' 326 Given a sorted list of filenames (including full path), this will 327 treat the list as a video sequence. 328 '''
329 - def __init__(self, filelist, size=None):
330 ''' 331 @param filelist: a list of full file paths to the images that comprise the video. 332 They must be files capable of being loaded into a pv.Image() object, and should 333 be in sorted order for playback. 334 @param size: Optional tuple to indicate the desired playback window size. 335 ''' 336 self.filelist = filelist 337 self.idx = 0 338 self.size = size
339
340 - def grab(self):
341 pass
342
343 - def query(self):
344 if self.idx >= len(self.filelist): return None 345 f = self.filelist[self.idx] 346 frame = pv.Image(f).asOpenCV() 347 self.idx += 1 348 return pv.Image(self.resize(frame))
349
350 - def __iter__(self):
351 ''' Return an iterator for this video ''' 352 return VideoFromFileList(self.filelist)
353 354
355 -class VideoFromDirectory(VideoInterface):
356 ''' 357 This class allows the user to treat a directory of images as a video. 358 359 This class will recursively search the directories and will load 360 and return any image with an image extension: JPG,JPEG,PNG,TIF,TIFF,GIF,BMP,PPM,PGM 361 ''' 362
363 - def __init__(self,dirname,order='ascending',limit=None,size=None,followlinks=True):
364 ''' 365 Recursively scans a directory for images and returns all images that 366 could be loaded. 367 368 Example: 369 images = pv.VideoFromDirectory(dirname) 370 for im in images: 371 do something 372 373 374 @param dirname: directory where the images comprising the video exist 375 @type dirname: str 376 @param order: return the images in a random order using the randam.shuffle function. 377 @type order: 'random' | 'ascending' 378 @param limit: limit the number of images returned. 379 @type limit: int 380 @param size: resize all images to this size. 381 @type: (int,int) 382 ''' 383 self._dirname = dirname 384 self._order = order 385 self._limit = limit 386 self._size = size 387 self._counter = 0 388 389 self._followlinks = followlinks 390 391 self._image_paths = [] 392 393 self._scanImageDir() 394 395 if self._order == 'ascending': 396 self._image_paths.sort() 397 elif self._order == 'random': 398 random.shuffle(self._image_paths) 399 else: 400 raise ValueError("unknown ordering type: %s"%(self._order,))
401
402 - def _checkExtension(self,filename):
403 ''' 404 Check the extension on a filename to see if it is in the list. 405 ''' 406 parts = filename.split('.') 407 if len(parts) > 0: 408 ext = parts[-1].upper() 409 return ext in ("JPG",'JPEG',"PNG","TIF","TIFF","GIF","BMP","PPM","PGM")
410 411
412 - def _scanImageDir(self):
413 ''' 414 Scan the directory and populate image_paths. 415 ''' 416 for dirpath,_,filenames in os.walk(self._dirname,followlinks=self._followlinks): 417 for filename in filenames: 418 if self._checkExtension(filename): 419 path = os.path.join(dirpath,filename) 420 self._image_paths.append(path)
421 422
423 - def query(self):
424 while True: 425 im_path = None 426 try: 427 if self._counter >= len(self._image_paths) or (self._limit != None and self._counter >= self._limit): 428 return None 429 im_path = self._image_paths[self._counter] 430 self._counter += 1 431 im = pv.Image(im_path) 432 if self._size != None: 433 im = im.resize(self.size) 434 return im 435 except: 436 print "Warning: could not process image:",im_path
437
438 - def __iter__(self):
439 ''' Return an iterator for this video ''' 440 return VideoFromDirectory(self._dirname, self._order, self._limit, self._size)
441
442 - def __len__(self):
443 return len(self._image_paths)
444
445 -class VideoFromImages(VideoInterface):
446 ''' 447 This class allows the user to treat a directory of images as a video. It is assumed that 448 the files in the directory are named as follows: 449 {prefix}{num}.{ext} 450 where 451 prefix is any string that is constant for all the files, 452 ext is the file extension/type like jpg, png, etc. 453 num is a zero-padded number like 0001, 0002, ... 454 455 note: the amount of padded zeros is the minimum required based on the length 456 (num frames) in the video, unless a specific padding is specified. So if you only had 457 120 frames, then it would be 001, 002,...120. 458 459 We assume the frames are sequential with no gaps, and start at number startnum (with 460 appropriate padding). 461 '''
462 - def __init__(self,dirname,numframes,prefix="frame",ext="jpg", pad=None, startnum=1, size=None):
463 ''' 464 The file names are of the format {prefix}{zero-padded num}.{ext}, the amount of 465 zero-padding is determined automatically based on numframes. If there is additional 466 zero-padding required, put it in the prefix. 467 Example: a directory with images: vid_t1_s1_f001.jpg, ..., vid_t1_s1_f999.jpg 468 would have prefix="vid_t1_s1_f", startnum=1, numframes=999, ext="jpg" 469 470 @param dirname: directory where the images comprising the video exist 471 @param numframes: the number of frames in the video...0 to numframes will be read. 472 specify None to read all images in directory, in which case you must specify 473 a value for the pad parameter. 474 @param prefix: a string which remains as a constant prefix to all frames in video 475 @param ext: the extension of the images, like jpg, png, etc. Do not include the dot. 476 @param pad: the padding (like string.zfill(x)) used on the sequential numbering of 477 the input files. Specify None, and the padding will be determined based on length 478 of numframes. (So if numframes = 1234, then pad=4, 0001,0002,...1234) 479 @param startnum: the starting number of the first frame, defaults to 1 480 @param size: the optional width,height to resize the input frames 481 ''' 482 self.dirname = dirname 483 if numframes == None: 484 #user wants to read all frames, so padding must be specified 485 assert(pad != None and pad>0) 486 487 if pad == None: 488 pad = len(str(numframes)) 489 490 self.pad = pad 491 self.maxframes = numframes 492 self.prefix = prefix 493 self.ext = ext 494 self.size = size #the optional width,height to resize the input frames 495 self.startnum = startnum 496 self.current_frame = startnum #we start at frame 1 by default 497 498 #check that directory exists 499 if not os.path.exists(dirname): 500 print "Error. Directory: %s does not exist."%dirname 501 raise IOError
502
503 - def query(self):
504 numstr = str(self.current_frame).zfill(self.pad) 505 filename = self.prefix + numstr + "." + self.ext 506 f = os.path.join(self.dirname, filename) 507 508 if (self.maxframes == None) or (self.current_frame <= self.maxframes): 509 #then we query the next in the sequence until file not exists 510 if os.path.exists(f): 511 frame = pv.Image(f).asOpenCV() 512 self.current_frame += 1 513 return( pv.Image(self.resize(frame)) ) 514 else: 515 print "Image file %s does not exist. Stopping VideoFromImages."%f 516 517 return None
518
519 - def __iter__(self):
520 ''' Return an iterator for this video ''' 521 return VideoFromImages(self.dirname, self.maxframes, self.prefix, self.ext, self.pad, self.startnum, self.size)
522
523 -class VideoFromImageStack(VideoInterface):
524 ''' 525 This class allows the user to treat a stack of grayscale images in a 3D numpy array as a video. 526 We assume that the dimensions of the array are ordered as (frame number, width, height). 527 '''
528 - def __init__(self, imageStack, size=None):
529 ''' 530 imageStack is the numpy ndarray that represents the image stack. Should be of dimensions (frames,width,height). 531 Optionally, this can be any object, such as pyvision.ImageBuffer, that implements asStackBW() method that returns 532 the grayscale image stack. 533 size is the optional width,height to resize the input frames. 534 ''' 535 if str( type(imageStack) ) == "<type 'instance'>": 536 self.imageStack = imageStack.asStackBW() 537 else: 538 self.imageStack = imageStack 539 540 (f,_,_) = self.imageStack.shape 541 self.numFrames = f 542 self.current_frame = 0 543 self.size = size
544
545 - def query(self):
546 if self.current_frame < self.numFrames: 547 frame = pv.Image( self.imageStack[self.current_frame,:,:]) 548 self.current_frame += 1 549 return( pv.Image(self.resize(frame.asOpenCV()))) 550 return None
551
552 - def __iter__(self):
553 ''' Return an iterator for this video ''' 554 return VideoFromImageStack(self.imageStack, self.size)
555 556
557 -class FFMPEGVideo:
558 # TODO: there may be a bug with the popen interface 559 ''' 560 FFMPEGVideo is an alternate way to capture video from a file, 561 not directly using OpenCV's highgui. This class does not implement 562 the VideoInterface abstract class, and it does not have the same 563 usage pattern. 564 '''
565 - def __init__(self,filename,size=None,aspect=None,options=""):
566 self.filename = filename 567 self.size = size 568 self.aspect = aspect 569 self.options = options 570 571 # Open a pipe 572 args = "/opt/local/bin/ffmpeg -i %s %s -f yuv4mpegpipe - "%(filename,options) 573 #print args 574 575 self.stdin, self.stdout, self.stderr = os.popen3(args) 576 #popen = subprocess.Popen(args,executable="/opt/local/bin/ffmpeg") 577 578 line = self.stdout.readline() 579 #print line 580 #self.stdout.seek(0,os.SEEK_CUR) 581 582 _,w,h,_,_,aspect,_,_ = line.split() 583 584 # I am not sure what all this means but I am checking it anyway 585 assert format=='YUV4MPEG2' 586 #assert t1=='Ip' 587 #assert t2=='C420mpeg2' 588 #assert t3=='XYSCSS=420MPEG2' 589 590 # get the width and height 591 assert w[0] == "W" 592 assert h[0] == "H" 593 594 self.w = int(w[1:]) 595 self.h = int(h[1:]) 596 597 # Create frame caches 598 if size == None and self.aspect != None: 599 h = self.h 600 w = int(round(self.aspect*h)) 601 size = (w,h) 602 #print size 603 604 self.size = size 605 606 self.frame_y = cv.CreateImage( (self.w,self.h), cv.IPL_DEPTH_8U, 1 ) 607 self.frame_u2 = cv.CreateImage( (self.w/2,self.h/2), cv.IPL_DEPTH_8U, 1 ) 608 self.frame_v2 = cv.CreateImage( (self.w/2,self.h/2), cv.IPL_DEPTH_8U, 1 ) 609 610 self.frame_u = cv.CreateImage( (self.w,self.h), cv.IPL_DEPTH_8U, 1 ) 611 self.frame_v = cv.CreateImage( (self.w,self.h), cv.IPL_DEPTH_8U, 1 ) 612 self.frame_col = cv.CreateImage( (self.w,self.h), cv.IPL_DEPTH_8U, 3 ) 613 614 615 if self.size != None: 616 w,h = self.size 617 self.frame_resized = cv.CreateImage( (w,h),cv.IPL_DEPTH_8U,3)
618 619 620
621 - def frame(self):
622 _ = self.stdout.readline() 623 #print line 624 #print self.w,self.h 625 y = self.stdout.read(self.w*self.h) 626 u = self.stdout.read(self.w*self.h/4) 627 v = self.stdout.read(self.w*self.h/4) 628 if len(y) < self.w*self.h: 629 raise EOFError 630 631 cv.SetData(self.frame_y,y) 632 cv.SetData(self.frame_u2,u) 633 cv.SetData(self.frame_v2,v) 634 635 cv.Resize(self.frame_u2,self.frame_u) 636 cv.Resize(self.frame_v2,self.frame_v) 637 638 cv.Merge(self.frame_y,self.frame_u,self.frame_v,None,self.frame_col) 639 cv.CvtColor(self.frame_col,self.frame_col,cv.CV_YCrCb2RGB) 640 641 out = self.frame_col 642 643 if self.size != None: 644 cv.Resize(self.frame_col,self.frame_resized) 645 out = self.frame_resized 646 647 return pv.Image(self.frame_y),pv.Image(self.frame_u),pv.Image(self.frame_v),pv.Image(out)
648 649
650 - def __iter__(self):
651 ''' Return an iterator for this video ''' 652 return FFMPEGVideo(self.filename,size=self.size,aspect=self.aspect,options=self.options)
653 654
655 - def next(self):
656 try: 657 _,_,_,frame = self.frame() 658 except EOFError: 659 raise StopIteration("End of video sequence") 660 return frame
661