From 4e11c851e7e3902d01b0d4ad5b85fb2248fc8399 Mon Sep 17 00:00:00 2001 From: 2ManyProjects Date: Thu, 8 Jan 2026 00:41:30 -0600 Subject: [PATCH] Fixing mosaic --- src/stitching_scanner.py | 63 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/src/stitching_scanner.py b/src/stitching_scanner.py index d07d097..3b78b00 100644 --- a/src/stitching_scanner.py +++ b/src/stitching_scanner.py @@ -41,6 +41,8 @@ class StitchState: direction: str = '' cumulative_x: float = 0.0 cumulative_y: float = 0.0 + current_x: float = 0.0 + current_y: float = 0.0 last_displacement: Tuple[float, float] = (0.0, 0.0) current_row: int = 0 total_rows: int = 0 @@ -194,6 +196,49 @@ class StitchingScanner: result[:, w_strip - blend_w:w_strip] = blended result[:, w_strip:] = base[:, blend_w:] return result + def _blend_vertical_at_x(self, base: np.ndarray, strip: np.ndarray, + blend_height: int, append_below: bool) -> np.ndarray: + mh, mw = base.shape[:2] + sh, sw = strip.shape[:2] + + # Match widths + if sw > mw: + strip = strip[:, :mw] + elif sw < mw: + pad = np.zeros((sh, mw - sw, 3), dtype=np.uint8) + strip = np.hstack([strip, pad]) + + blend_h = min(blend_height, sh, mh) + + if blend_h <= 0: + if append_below: + return np.vstack([base, strip]) + return np.vstack([strip, base]) + + if append_below: + alpha = np.linspace(1, 0, blend_h, dtype=np.float32)[:, np.newaxis, np.newaxis] + base_overlap = base[-blend_h:].astype(np.float32) + strip_overlap = strip[:blend_h].astype(np.float32) + blended = (base_overlap * alpha + strip_overlap * (1 - alpha)).astype(np.uint8) + + result_h = mh + sh - blend_h + result = np.zeros((result_h, mw, 3), dtype=np.uint8) + result[:mh - blend_h] = base[:-blend_h] + result[mh - blend_h:mh] = blended + result[mh:] = strip[blend_h:] + return result + else: + alpha = np.linspace(0, 1, blend_h, dtype=np.float32)[:, np.newaxis, np.newaxis] + strip_overlap = strip[-blend_h:].astype(np.float32) + base_overlap = base[:blend_h].astype(np.float32) + blended = (strip_overlap * (1 - alpha) + base_overlap * alpha).astype(np.uint8) + + result_h = mh + sh - blend_h + result = np.zeros((result_h, mw, 3), dtype=np.uint8) + result[:sh - blend_h] = strip[:-blend_h] + result[sh - blend_h:sh] = blended + result[sh:] = base[blend_h:] + return result def _blend_vertical(self, base: np.ndarray, strip: np.ndarray, blend_height: int, append_below: bool) -> np.ndarray: @@ -291,13 +336,13 @@ class StitchingScanner: if direction == ScanDirection.DOWN: strip_end = min(h, append_height + BLEND_WIDTH) new_strip = frame[:strip_end:, :] - self.mosaic = self._blend_vertical( - self.mosaic, new_strip, BLEND_WIDTH, append_below=False) + self.mosaic = self._blend_vertical_at_x( + self.mosaic, new_strip, BLEND_WIDTH, append_below=False, x_offset=int(self.state.current_x)) else: strip_start = max(0, h - append_height - BLEND_WIDTH) new_strip = frame[:strip_start, :] - self.mosaic = self._blend_vertical( - self.mosaic, new_strip, BLEND_WIDTH, append_below=True) + self.mosaic = self._blend_vertical_at_x( + self.mosaic, new_strip, BLEND_WIDTH, append_below=True, x_offset=int(self.state.current_x)) self._displacement_since_append_x = 0.0 self._displacement_since_append_y = fractional_remainder @@ -438,6 +483,7 @@ class StitchingScanner: threshold_pixels = h * self.config.displacement_threshold max_dim = self.config.max_mosaic_height current_dim = lambda: self.state.mosaic_height + total_x = 0 if direction == ScanDirection.DOWN else self.config.max_mosaic_width start_cmd = 'S' if direction == ScanDirection.DOWN else 'N' stop_cmd = 's' if direction == ScanDirection.DOWN else 'n' @@ -449,8 +495,11 @@ class StitchingScanner: no_movement_count = 0 max_no_movement = 50 stop_reason = 'stopped' - total_x = 0 - + if direction == ScanDirection.RIGHT: + self.state.current_x = self.state.mosaic_width - w # At right edge + elif direction == ScanDirection.LEFT: + self.state.current_x = 0 + while self.running and not self.paused: if time.time() - start_time > self.config.max_scan_time: self.log("Scan timeout") @@ -479,6 +528,7 @@ class StitchingScanner: self._displacement_since_append_x += dx self._displacement_since_append_y += dy total_x += dx + self.state.current_x += dx with self._state_lock: self.state.cumulative_x = self._displacement_since_append_x @@ -556,6 +606,7 @@ class StitchingScanner: self._displacement_since_append_y += dy total_y += dy + self.state.current_y += dy with self._state_lock: self.state.cumulative_y = total_y