From 0cd0ad63343c0e9ad7ded66dfc89cb8c18d45bb7 Mon Sep 17 00:00:00 2001 From: Prohurtz <48768484+RedHawk989@users.noreply.github.com> Date: Wed, 12 Jul 2023 09:38:34 -0500 Subject: [PATCH] revert camera thread, util opencv bug fix instead --- EyeTrackApp/camera.py | 79 ++++++++++++------------------------ EyeTrackApp/eye_processor.py | 3 +- EyeTrackApp/leap.py | 12 +----- 3 files changed, 29 insertions(+), 65 deletions(-) diff --git a/EyeTrackApp/camera.py b/EyeTrackApp/camera.py index e8d7b4e..497e536 100644 --- a/EyeTrackApp/camera.py +++ b/EyeTrackApp/camera.py @@ -5,11 +5,11 @@ import serial import serial.tools.list_ports import threading import time -import asyncio + from colorama import Fore from config import EyeTrackConfig from enum import Enum -import concurrent.futures + WAIT_TIME = 0.1 # Serial communication protocol: @@ -48,8 +48,7 @@ class Camera: self.cancellation_event = cancellation_event self.current_capture_source = config.capture_source self.cv2_camera: "cv2.VideoCapture" = None - self.timeout = 5 # Timeout in seconds - self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) + self.serial_connection = None self.last_frame_time = time.time() self.frame_number = 0 @@ -71,33 +70,14 @@ class Camera: def set_output_queue(self, camera_output_outgoing: "queue.Queue"): self.camera_output_outgoing = camera_output_outgoing - def init_camera(self): - if self.cv2_camera == None: - # time.sleep(0.5) # Very important wait - def init(): - return cv2.VideoCapture(self.current_capture_source) - future = self.executor.submit(init) - future.add_done_callback(self.done_callback) - else: - pass - - def done_callback(self, future): - try: - time.sleep(0.5) # Very important wait - self.cv2_camera = future.result() - except Exception: - # Set cv2_camera to None if an exception occurred - self.cv2_camera = None - if future == "stop": - # Release the camera resource - if self.cv2_camera is not None: - self.cv2_camera.release() def run(self): + OPENCV_PARAMS = [ + cv2.CAP_PROP_OPEN_TIMEOUT_MSEC, 5000, + cv2.CAP_PROP_READ_TIMEOUT_MSEC, 5000, + ] while True: - if self.cancellation_event.is_set(): #TODO: fix stall when app closes and cam not found + if self.cancellation_event.is_set(): print(f"{Fore.CYAN}[INFO] Exiting Capture thread{Fore.RESET}") - self.done_callback("stop") - # print('close') return should_push = True # If things aren't open, retry until they are. Don't let read requests come in any earlier @@ -105,8 +85,7 @@ class Camera: if ( self.config.capture_source != None and self.config.capture_source != "" ): - # if self.cv2_camera is not None: - # print(self.cv2_camera, self.cv2_camera.isOpened(),self.camera_status) + if "COM" in str(self.current_capture_source): if ( self.serial_connection is None @@ -120,19 +99,21 @@ class Camera: if ( self.cv2_camera is None or not self.cv2_camera.isOpened() - # or self.camera_status == CameraState.DISCONNECTED + or self.camera_status == CameraState.DISCONNECTED or self.config.capture_source != self.current_capture_source ): - print(self.error_message.format(self.config.capture_source)) # This requires a wait, otherwise we can error and possible screw up the camera # firmware. Fickle things. if self.cancellation_event.wait(WAIT_TIME): return self.current_capture_source = self.config.capture_source - self.init_camera() - self.camera_status = CameraState.CONNECTED - #self.cv2_camera = cv2.VideoCapture(self.current_capture_source) + # self.cv2_camera = cv2.VideoCapture(self.current_capture_source) + + self.cv2_camera = cv2.VideoCapture() + self.cv2_camera.setExceptionMode(True) + # https://github.com/opencv/opencv/blob/4.8.0/modules/videoio/include/opencv2/videoio.hpp#L803 + self.cv2_camera.open(self.current_capture_source, cv2.CAP_FFMPEG, params=OPENCV_PARAMS) should_push = False else: # We don't have a capture source to try yet, wait for one to show up in the GUI. @@ -152,17 +133,13 @@ class Camera: if not should_push: # if we get all the way down here, consider ourselves connected self.camera_status = CameraState.CONNECTED - if self.cancellation_event.is_set(): #TODO: fix stall when app closes and cam not found - print(f"{Fore.CYAN}[INFO] Exiting Capture thread{Fore.RESET}") - # self.done_callback("stop") - # print('close') + def get_cv2_camera_picture(self, should_push): try: ret, image = self.cv2_camera.read() if not ret: self.cv2_camera.set(cv2.CAP_PROP_POS_FRAMES, 0) raise RuntimeError("Problem while getting frame") - self.newft = time.time() frame_number = self.cv2_camera.get(cv2.CAP_PROP_POS_FRAMES) # Calculate the fps. current_frame_time = time.time() @@ -172,18 +149,16 @@ class Camera: self.bps = len(image) / delta_time self.frame_number = self.frame_number + 1 self.fps = (self.fps + self.pf_fps) / 2 - if self.newft != self.prevft: - self.fps = 1 / (self.newft - self.prevft) - self.prevft = self.newft - self.fps = int(self.fps) - if len(self.fl) < 60: - self.fl.append(self.fps) - else: - self.fl.pop(0) - self.fl.append(self.fps) - self.fps = sum(self.fl) / len(self.fl) + self.newft = time.time() + self.fps = 1 / (self.newft - self.prevft) + self.prevft = self.newft + self.fps = int(self.fps) + if len(self.fl) < 60: + self.fl.append(self.fps) else: - self.fps = 69 + self.fl.pop(0) + self.fl.append(self.fps) + self.fps = sum(self.fl) / len(self.fl) #self.bps = image.nbytes if should_push: self.push_image_to_queue(image, frame_number, self.fps) @@ -293,4 +268,4 @@ class Camera: print( f"{Fore.YELLOW}[WARN] CAPTURE QUEUE BACKPRESSURE OF {qsize}. CHECK FOR CRASH OR TIMING ISSUES IN ALGORITHM.{Fore.RESET}") self.camera_output_outgoing.put((image, frame_number, fps)) - self.capture_event.clear() + self.capture_event.clear() \ No newline at end of file diff --git a/EyeTrackApp/eye_processor.py b/EyeTrackApp/eye_processor.py index 07bb17b..a8829f3 100644 --- a/EyeTrackApp/eye_processor.py +++ b/EyeTrackApp/eye_processor.py @@ -282,7 +282,6 @@ class EyeProcessor: self.eyeopen = 0.0 else: self.eyeopen = ibo - print(self.eyeopen) self.output_images_and_update( self.thresh, EyeInfo(self.current_algo, self.out_x, self.out_y, 0, self.eyeopen), @@ -293,7 +292,7 @@ class EyeProcessor: def LEAPM(self): self.thresh = self.current_image_gray.copy() - self.current_image_gray, self.rawx, self.rawy, self.eyeopen = self.er_leap.run(self.current_image_gray, True) + self.current_image_gray, self.rawx, self.rawy, self.eyeopen = self.er_leap.run(self.current_image_gray) self.thresh = self.current_image_gray.copy() self.out_x, self.out_y = cal.cal_osc(self, self.rawx, self.rawy) self.current_algorithm = EyeInfoOrigin.LEAP diff --git a/EyeTrackApp/leap.py b/EyeTrackApp/leap.py index 0279ae1..0f5c7b4 100644 --- a/EyeTrackApp/leap.py +++ b/EyeTrackApp/leap.py @@ -124,8 +124,6 @@ class LEAP_C(object): self.openlist = [] self.x = 0 self.y = 0 - self.frame_lim_count = 0 - self.last_lid = 0.7 self.ort_session1 = onnxruntime.InferenceSession( @@ -151,13 +149,6 @@ class LEAP_C(object): break def leap_run(self): - if self.lid_only == True: - if self.frame_lim_count > 0: - self.frame_lim_count = 0 - return self.current_image_gray, float(0), float(0), self.last_lid, - else: - self.frame_lim_count += 1 - pass img = self.current_image_gray.copy() img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) @@ -216,8 +207,7 @@ class External_Run_LEAP(object): def __init__(self): self.algo = LEAP_C() - def run(self, current_image_gray, trackmode): - self.algo.lid_only = trackmode + def run(self, current_image_gray): self.algo.current_image_gray = current_image_gray img, x, y, per = self.algo.leap_run() return img, x, y, per \ No newline at end of file