class Gestures(): def __init__(self): #initialize the webcam self.camera = Webcam() #initialize optical debug mode self.opticalDebugMode = False #initialize the video window cv2.namedWindow(WIN_NAME, cv2.CV_WINDOW_AUTOSIZE) #start collecting frames for processing self.init_frames() #initialize Algorithm instance self.alg = Algorithm() def start(self): """Runs image processing loop""" while True: self.update_frames() self.alg.calc_scroll(self.dir) key = cv2.waitKey(4) if key == 27: #Quit if the user presses ESC self.stop_gui() break if key == 104: #Toggle hand tracking debug window self.tracker.toggle_debug() if key == 111: #Toggle optical flow debug window self.toggle_optical() def init_frames(self): """Initiates camera and 3 initial frames for processing""" #Get 3 successive frames for difference calculation self.img0, self.frame0 = self.camera.get_frame_bgr_and_gray() self.img1, self.frame1 = self.camera.get_frame_bgr_and_gray() self.img2, self.frame2 = self.camera.get_frame_bgr_and_gray() if USE_HANDTRACKING: self.init_hand_tracking() def init_hand_tracking(self): """Initiates hand tracker and 3 initial bounding point sets""" #Initialize hand tracker self.tracker = HandTracking() #Get 3 successive sets of features (feature: array of points) #Each feature array is based on a frame's bounding boxes #and indicates the areas for which optical flow should be calculated self.mpts0 = self.tracker.getBoundingMidpoints(self.img0) self.mpts1 = self.tracker.getBoundingMidpoints(self.img1) self.mpts2 = self.tracker.getBoundingMidpoints(self.img2) def update_frames(self): """Updates frames for next loop of processing""" #Store old frames self.img0 = self.img1 self.frame0 = self.frame1 #Get new rgb and grayscale frames self.img1, self.frame1 = self.camera.get_frame_bgr_and_gray() #Update bounding arrays if USE_HANDTRACKING: self.mpts0 = self.mpts1 self.mpts1 = self.tracker.getBoundingMidpoints(self.img1) self.dir = self.get_direction_vector() self.tracker.update_dir_data(self.dir) if self.opticalDebugMode: #Show optical flow field flow = cv2.calcOpticalFlowFarneback(self.frame0, self.frame1, PYR_SCALE, LEVELS, WINSIZE, ITER, POLY_N, POLY_SIGMA, FLAGS) image = self.alg.create_flow( self.frame1, flow, 10) #create the flow overlay for display self.show_image(image) def get_direction_vector(self): """Calculates the vector between the midpoints of bounding boxes.""" if len(self.mpts0) is not len(self.mpts1): return diffs = [] for i in range(len(self.mpts0)): mp0 = self.mpts0[i] mp1 = self.mpts1[i] diff = [a - b for a, b in zip(mp1, mp0)] dist = np.sqrt(diff[0]**2 + diff[1]**2) diffs.append((diff, dist)) if len(diffs) == 0: return None return max(diffs, key=lambda a: a[1]) def toggle_optical(self): """Toggle the optical flow debug window""" self.opticalDebugMode = not self.opticalDebugMode if self.opticalDebugMode: #initialize the video window cv2.namedWindow(WIN_NAME, cv2.CV_WINDOW_AUTOSIZE) else: self.stop_gui() def show_image(self, img): """Show a GUI with the webcam feed for debugging purposes""" cv2.imshow(WIN_NAME, img) def stop_gui(self): """Stop the webcam""" cv2.destroyWindow(WIN_NAME)