def run_detector(): # import os # os.environ['SDL_VIDEODRIVER'] = 'windib' # os.environ['SDL_VIDEODRIVER'] = 'directx' parser = OptionParser(usage="""\ Detect SnapMyinfo QRcodes in a live video stream Usage: %prog [options] camera_index """) parser.add_option('-f','--fs','--fullscreen', dest="fullscreen", default=False, action='store_true', help="""Run the Live Decoder full screen.""") parser.add_option('--hw','--hw_accel', dest="hw_accel", default=False, action='store_true', help="""Runs pygame with the directx hw driver (if avail). Automatically assumes fullscreen.""") parser.add_option('-s','--scale', dest="scale", default=4.0, action='store', type="float", help="""Sets the precision of code tracking. Valid values are >1.0 and less than 8.0. Lower values represent more accurate tracking, but consume more CPU.""") parser.add_option('--flip', dest="flip", default=False, action='store_true', help="""Flip the video image horizontally before processing.""") parser.add_option('-m','--max_cards', dest="tracker_count", default=3, type="int", action="store", help="""The number of simultaneous snap codes that can be tracked in the video stream.""") parser.add_option('--nv','--no_video', dest="no_video", default=False, action="store_true", help="""A debugging option, turns off the video stream from the web cam.""") parser.add_option('-d','--debug', dest="debug", default=False, action="store_true", help="""Debugging option, turns on fps display and additional tracking data on the display.""") opts, args = parser.parse_args() import os os.environ['SDL_VIDEODRIVER'] = 'windib' if opts.hw_accel: os.environ['SDL_VIDEODRIVER'] = 'directx' opts.fullscreen = True # initialize pygame pygame.init() display_size = (800,600) video_size = (1280,720) # scale is roughly equivalent to tracking precision # the higher the scale, the less precise, but faster, the gross # tracking will be scale of 1 means 1:1 tracking, but can be slow # recommend 2-4 as a good scale/precision factor. higher res images # usually benefit from higher scale scale = opts.scale # this can be used to throttle the max framerate processed. 0 means no throttle max_frame_rate = 30 names = [args[0]] name = names[0] if not opts.no_video: # connect to web camera and set the webcam options capture = cvCreateCameraCapture( int(name) ) cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, video_size[0] ) cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, video_size[1] ) # query the camera once to get the camera properties # the frame is just a throwaway cvQueryFrame( capture ) # get the camera properties (o_width,o_height) = [cvGetCaptureProperty(capture, prop) for prop in [CV_CAP_PROP_FRAME_WIDTH,CV_CAP_PROP_FRAME_HEIGHT]] video_size = (int(o_width),int(o_height)) else: blank = cvCreateImage(video_size,8,3) cvZero(blank) # create the pygame display flags = 0 if opts.fullscreen: flags = pygame.FULLSCREEN if opts.hw_accel: flags = flags|pygame.HWSURFACE|pygame.DOUBLEBUF display_layer = pygame.display.set_mode( display_size, flags ) video = pygame.Surface(video_size).convert() # set the window name pygame.display.set_caption('Live Detector') # some debug information # print the current driver being used print 'Driver %s\nVideo Input Resolution: %s\nDisplay Resolution: %s\n' % (pygame.display.get_driver(), video_size, display_size) # for convert to work, pygame video mode has to be set image_buffer = ImageBuffer(video_size,display_size,scale) if opts.no_video: image_buffer.frame_buffer = cvCreateImage(video_size,8,3) # blank = cvCreateImage(video_size,8,3) # cvZero(blank) worker = GrossTracker(image_buffer) # pool of tracker objects pool = TrackerPool(image_buffer, opts.tracker_count) thread_objects.append(pool) status = Status() connector = Connector(pool,status) connector.start() thread_objects.append(connector) # for i in range(4): # win_name = "thread-%d" % i # cvNamedWindow(win_name, CV_WINDOW_AUTOSIZE) pyg_clock = pygame.time.Clock() update_count = 0 last_rects = [] last_fills = [] hud_last_fills = [] if opts.debug: dbg = DebugDisplay() snap_logo = pygame.image.load('./images/snap_logo.png').convert_alpha() still = False running = True fps = 0.0 while running: pyg_clock.tick(max_frame_rate) if update_count > 20: fps = pyg_clock.get_fps() update_count = 0 update_count += 1 # get the pygame events events = pygame.event.get() for e in events: # 'quit' event key if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE): running = False elif e.type == KEYDOWN and e.unicode == u't': still = True # take a frame from the web camera if opts.no_video: cvCopy(blank,image_buffer.frame_buffer) else: image_buffer.frame_buffer = cvQueryFrame( capture ) if opts.flip: cvFlip(image_buffer.frame_buffer,image_buffer.frame_buffer,1) # update the image buffer with the latest frame image_buffer.update() # analyze the small frame to find collapsed candidates squares = worker.analyze_frame() # check squares and assign a tracker if new pool.check(squares) # update all trackers pool.update() status.update() # clear the paint buffer for rect in last_rects: pygame.gfxdraw.rectangle(image_buffer.paint_buffer, rect, Color(0,0,0)) last_rects = [] for blank in last_fills: image_buffer.paint_buffer.fill((0,0,0),blank) last_fills = [] for blank in hud_last_fills: image_buffer.hud_buffer.fill((0,0,0,0),blank) hud_last_fills = [] # draw the sprite and tracker boundaries # boundaries will be replaced (or turned off) pool.sort_active() for t_id in pool.active_trackers: #rect = pool.trackers[t_id].get_bound_rect() center = pool.trackers[t_id].get_avg_center(2) frame_color = Color(128,255,128) if pool.trackers[t_id].sprite: # print str(dir(pool.trackers[t_id].sprite)) sprite_size = pool.trackers[t_id].sprite.get_size() # print str(sprite_size) x_diff = sprite_size[0] / 2.0 y_diff = sprite_size[1] / 2.0 # frame_color = Color(250,250,255) rect = pygame.Rect(center.x * image_buffer.display_scale[0] - x_diff, center.y * image_buffer.display_scale[1] - y_diff, sprite_size[0],sprite_size[1]) # pygame.gfxdraw.rectangle(image_buffer.paint_buffer, rect, pool.trackers[t_id].color) # last_rects.append(rect) #if pool.trackers[t_id].user_id: image_buffer.paint_buffer.blit(pool.trackers[t_id].sprite,(rect.x ,rect.y )) last_fills.append(rect) #pygame.Rect(rect.x ,rect.y ,closer_img.size[0],closer_img.size[1])) else: # rect = pygame.Rect(center.x * scale - 100, center.y * scale - 100, 200,200) # # # pygame.gfxdraw.rectangle(image_buffer.paint_buffer, rect, frame_color) # last_rects.append(rect) #c = pygame.Color(164,229,135,150) #c1 = pygame.Color(164,229,135,255) c = pygame.Color(229,229,135,200) # c1 = pygame.Color(229,229,135,255) pygame.gfxdraw.filled_polygon(image_buffer.hud_buffer, pool.trackers[t_id].get_bounding_points(),c) # pygame.gfxdraw.polygon(image_buffer.hud_buffer, pool.trackers[t_id].get_bounding_points(),c1) # pygame.gfxdraw.rectangle(image_buffer.hud_buffer, rect, frame_color) # pygame.gfxdraw.filled_polygon(image_buffer.hud_buffer, pool.trackers[t_id].get_bounding_points(),c) hud_last_fills.append(pool.trackers[t_id].get_bound_rect()) # draw the orphans and frame rate display # debug for now, lets me know when it's trying to lock onto something if opts.debug: fps_sprite = dbg.gen_sprite('''%.2f fps''' % fps) image_buffer.hud_buffer.blit(fps_sprite,(image_buffer.display_size[0]-100,10)) fps_rect = pygame.Rect(video_size[0]-100,10, dbg.size[0], dbg.size[1]) hud_last_fills.append(fps_rect) for orphans in pool.orphan_frames: for orphan in orphans: orphan = pygame.Rect(orphan.x * image_buffer.display_scale[0], orphan.y * image_buffer.display_scale[1], orphan.width * image_buffer.display_scale[0], orphan.height * image_buffer.display_scale[1]) pygame.gfxdraw.rectangle(image_buffer.paint_buffer, orphan, Color(190,255,190)) last_rects.append(orphan) # no data in the frame buffer means we're done if not image_buffer.frame_buffer: break # Surf_dat array is not oriented the same way as the pyame display so # first it's transposed. Then the # the surface RGB values are not the same as the cameras # this means that two of the channels have to be swapped in the numpy # array before being blit'ted onto the array surf_dat = image_buffer.frame_buffer.as_numpy_array().transpose(1,0,2)[...,...,::-1] # blit_array zaps anything on the surface and completely replaces it with the array, much # faster than converting the bufer to a surface and bliting it # replaces video with the data in surf_dat surfarray.blit_array(video,surf_dat) # this resizes the video surface and stores it in display_layer. Completely # overwrites whatever is in display_layer pygame.transform.scale(video, image_buffer.display_size, display_layer) # blit the paint buffer onto the surface. Paint buffer has a chromakey so all black values will show through display_layer.blit(image_buffer.paint_buffer,(0,0)) # the "HUD" is added next. display_layer.blit(image_buffer.hud_buffer,(0,0)) # Write out the status sprite to the display_layer if status.sprite: display_layer.blit(status.sprite,(10,image_buffer.display_size[1] - status.height - 10 )) # finally watermark the screen with the company logo and name of the product # putting it here means it always shows above the other layers logo_size = snap_logo.get_size() display_layer.blit(snap_logo,(image_buffer.display_size[0]-logo_size[0]-10 , image_buffer.display_size[1]-logo_size[1]-10)) if still == True: pygame.image.save(display_layer, 'test.jpg') still = False # flip() actually displays the surface pygame.display.flip() # we've left the loop # exit print 'exiting...'