From 97654c5dcdf74a341d6e2a259dfbbb85b99d396e Mon Sep 17 00:00:00 2001 From: John Peterson <33739318+Coincadink@users.noreply.github.com> Date: Mon, 31 Mar 2025 15:24:16 -0600 Subject: [PATCH 1/6] Swap to after_idle call to thread image processing --- src/gui.py | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/src/gui.py b/src/gui.py index 3f2e8f3..c15d461 100644 --- a/src/gui.py +++ b/src/gui.py @@ -735,38 +735,14 @@ def __init__( self.camera = c self.pending_frame = None - def _on_new_frame(self): - # FIXME: is this really the only way tkinter exposes to do this?? - # We want to send frames from the callback over to the main thread, - # but in way where it just grabs the most recently-made-available frame. - # If you send an event, events will just pile up in the queue if we ever fall behind. - # This might have the same problem! - # I have no idea how to fix this - self.event_dispatcher.root.after(33, lambda: self._on_new_frame()) - if self.pending_frame is None: - return - image, dimensions, format = self.pending_frame - - try: - filename = self.snapshots_pending.get_nowait() - print(f"Saving image {filename}") - img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - cv2.imwrite(filename, img) - except queue.Empty: - pass - - self.gui_camera_preview(image, dimensions) - def start(self): if not self.camera: print("No camera available") return - # self.event_dispatcher.root.bind('<>', lambda x: self._on_new_frame(x)) - def cameraCallback(image, dimensions, format): self.pending_frame = (image, dimensions, format) - # self.event_dispatcher.root.event_generate('<>', when='tail') + self.event_dispatcher.root.after_idle(lambda: self._on_new_frame(image, dimensions, format)) if not self.camera.open(): print("Camera failed to start") @@ -775,8 +751,17 @@ def cameraCallback(image, dimensions, format): self.camera.setStreamCaptureCallback(cameraCallback) if not self.camera.startStreamCapture(): print("Failed to start stream capture for camera") + + def _on_new_frame(self, image, dimensions, format): + try: + filename = self.snapshots_pending.get_nowait() + print(f"Saving image {filename}") + img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + cv2.imwrite(f"{self.event_dispatcher.snapshot_directory}/{filename}", img) + except queue.Empty: + pass - self._on_new_frame() + self.gui_camera_preview(image, dimensions) def cleanup(self): if self.camera is not None: @@ -1724,6 +1709,7 @@ def main(): camera_config = config["camera"] + # Camera Type Selection if camera_config["type"] == "webcam": try: index = int(camera_config["index"]) @@ -1742,6 +1728,7 @@ def main(): print(f"config.toml specifies invalid camera type {camera_config['type']}") return 1 + # GUI-Scaling try: camera_scale = float(camera_config["gui-scale"]) except Exception: From 309525d50855411209f46be3155791b0e94bc449 Mon Sep 17 00:00:00 2001 From: John Peterson <33739318+Coincadink@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:33:16 -0600 Subject: [PATCH 2/6] Revert to old autofocus --- config.toml | 6 +++--- src/gui.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/config.toml b/config.toml index 33c7ed6..47f65a4 100644 --- a/config.toml +++ b/config.toml @@ -1,9 +1,9 @@ [camera] -type = "none" +type = "flir" gui-scale = 0.1 [stage] -homing = false -enabled = false +homing = true +enabled = true port = "COM4" baud-rate = 115200 diff --git a/src/gui.py b/src/gui.py index c15d461..3c67c01 100644 --- a/src/gui.py +++ b/src/gui.py @@ -33,10 +33,10 @@ def compute_focus_score(camera_image, blue_only): camera_image = camera_image.copy() - camera_image[:, :, 1] = 0 # green should never be used for focus - if blue_only: - camera_image[:, :, 0] = 0 # disable red - img = cv2.cvtColor(camera_image, cv2.COLOR_RGB2GRAY) + # camera_image[:, :, 1] = 0 # green should never be used for focus + # if blue_only: + # camera_image[:, :, 0] = 0 # disable red + img = cv2.cvtColor(camera_image, cv2.COLOR_BGR2GRAY) img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5) mean = np.sum(img) / (img.shape[0] * img.shape[1]) img_lapl = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=1) / mean From 5e0c2db76ac22581ac0540c1f748c53f92913a1b Mon Sep 17 00:00:00 2001 From: John Peterson <33739318+Coincadink@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:28:33 -0600 Subject: [PATCH 3/6] Update gui.py --- src/gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui.py b/src/gui.py index 3c67c01..384a612 100644 --- a/src/gui.py +++ b/src/gui.py @@ -1571,7 +1571,7 @@ def __init__(self, parent, model: EventDispatcher): # TODO: Tune default offsets self.x_settings = OffsetAmountFrame(self.frame, "X", 1050) self.x_settings.frame.grid(row=0, column=0) - self.y_settings = OffsetAmountFrame(self.frame, "Y", 900) + self.y_settings = OffsetAmountFrame(self.frame, "Y", 525) self.y_settings.frame.grid(row=1, column=0) def on_begin(): From d08a3ba6f6c20d2c54826d6b6872c2b97d8380b4 Mon Sep 17 00:00:00 2001 From: John Peterson <33739318+Coincadink@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:29:36 -0600 Subject: [PATCH 4/6] Offset --- src/gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui.py b/src/gui.py index 384a612..def27b7 100644 --- a/src/gui.py +++ b/src/gui.py @@ -1569,7 +1569,7 @@ def __init__(self, parent, model: EventDispatcher): self.model = model # TODO: Tune default offsets - self.x_settings = OffsetAmountFrame(self.frame, "X", 1050) + self.x_settings = OffsetAmountFrame(self.frame, "X", 840) self.x_settings.frame.grid(row=0, column=0) self.y_settings = OffsetAmountFrame(self.frame, "Y", 525) self.y_settings.frame.grid(row=1, column=0) From b87693d5fc5b32ce9135d4570b4caee69ebd2fac Mon Sep 17 00:00:00 2001 From: John Peterson <33739318+Coincadink@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:34:22 -0600 Subject: [PATCH 5/6] constants --- src/gui.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui.py b/src/gui.py index def27b7..c359b7b 100644 --- a/src/gui.py +++ b/src/gui.py @@ -927,7 +927,7 @@ def callback_set(): self.step_size_intputs.append( IntEntry( parent=self.relative_frame, - default=10, + default=[840, 540, 200][i], min_value=-1000, max_value=1000, ) @@ -1571,7 +1571,7 @@ def __init__(self, parent, model: EventDispatcher): # TODO: Tune default offsets self.x_settings = OffsetAmountFrame(self.frame, "X", 840) self.x_settings.frame.grid(row=0, column=0) - self.y_settings = OffsetAmountFrame(self.frame, "Y", 525) + self.y_settings = OffsetAmountFrame(self.frame, "Y", 540) self.y_settings.frame.grid(row=1, column=0) def on_begin(): @@ -1674,7 +1674,7 @@ def on_start(): self.camera.start() if self.event_dispatcher.hardware.stage.has_homing(): self.event_dispatcher.home_stage() - self.event_dispatcher.move_relative({"x": 5000.0, "y": 3500.0, "z": 1900.0}) + self.event_dispatcher.move_relative({"x": 1000.0, "y": 3500.0, "z": 4000.0}) messagebox.showinfo( message="BEFORE CONTINUING: Ensure that you move the projector window to the correct display! Click on the fullscreen, completely black window, then press Windows Key + Shift + Left Arrow until it no longer is visible!" ) From 59bcd3326871196701dc415e05557625a5f9f120 Mon Sep 17 00:00:00 2001 From: John Peterson <33739318+Coincadink@users.noreply.github.com> Date: Wed, 9 Apr 2025 12:34:40 -0600 Subject: [PATCH 6/6] oops --- src/gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui.py b/src/gui.py index c359b7b..9b074ac 100644 --- a/src/gui.py +++ b/src/gui.py @@ -1674,7 +1674,7 @@ def on_start(): self.camera.start() if self.event_dispatcher.hardware.stage.has_homing(): self.event_dispatcher.home_stage() - self.event_dispatcher.move_relative({"x": 1000.0, "y": 3500.0, "z": 4000.0}) + self.event_dispatcher.move_relative({"x": 10000.0, "y": 3500.0, "z": 4000.0}) messagebox.showinfo( message="BEFORE CONTINUING: Ensure that you move the projector window to the correct display! Click on the fullscreen, completely black window, then press Windows Key + Shift + Left Arrow until it no longer is visible!" )