better x offset

This commit is contained in:
2ManyProjects 2026-01-10 00:47:56 -06:00
parent ef611b6798
commit 96422fe0d2

View file

@ -160,32 +160,17 @@ class StitchingScanner:
self.log(f"Initialized mosaic: {frame.shape[1]}x{frame.shape[0]}") self.log(f"Initialized mosaic: {frame.shape[1]}x{frame.shape[0]}")
def _blend_horizontal_at_y(self, base: np.ndarray, strip: np.ndarray, def _blend_horizontal_at_y(self, base: np.ndarray, strip: np.ndarray,
blend_width: int, append_right: bool, blend_width: int, append_right: bool, x_offset: int = None,
x_off: int = 0,
y_offset: int = 0) -> np.ndarray: y_offset: int = 0) -> np.ndarray:
h_base, w_base = base.shape[:2] h_base, w_base = base.shape[:2]
h_strip, w_strip = strip.shape[:2] h_strip, w_strip = strip.shape[:2]
# Clamp y_offset # Clamp y_offset
y_offset = max(0, min(y_offset, h_base - h_strip)) y_offset = max(0, min(y_offset, h_base - h_strip))
blend_w = min(blend_width, w_strip, w_base) blend_w = min(blend_width, w_strip, w_base)
# Early exit: no blending
if blend_w <= 0 or blend_w >= w_strip:
if append_right:
result_width = w_base + w_strip
result = np.zeros((h_base, result_width, 3), dtype=np.uint8)
result[:, :w_base] = base
result[y_offset:y_offset + h_strip, w_base:] = strip
return result
else:
result_width = w_base + w_strip
result = np.zeros((h_base, result_width, 3), dtype=np.uint8)
result[:, w_strip:] = base
result[y_offset:y_offset + h_strip, :w_strip] = strip
return result
if append_right: if append_right:
# Expand mosaic to the right
result_width = w_base + w_strip - blend_w result_width = w_base + w_strip - blend_w
result = np.zeros((h_base, result_width, 3), dtype=np.uint8) result = np.zeros((h_base, result_width, 3), dtype=np.uint8)
@ -195,16 +180,11 @@ class StitchingScanner:
self.log(f" result: {result_width}x{h_base}") self.log(f" result: {result_width}x{h_base}")
# Step 1: Copy entire base # Step 1: Copy entire base
self.log(f" Step 1: Copy base to result[:, :w_base] -> [:, :{w_base}]")
result[:, :w_base] = base result[:, :w_base] = base
# Step 2: Copy non-overlap portion of strip at correct Y # Step 2: Copy non-overlap portion of strip at correct Y
x_start = w_base x_place = w_base
x_end = result_width self.log(f" Placing strip at X={w_base - blend_w}:{result_width}, Y={y_offset}:{y_offset + h_strip}")
y_start = y_offset
y_end = y_offset + h_strip
self.log(f" Step 2: Place strip at X={x_start}:{x_end}, Y={y_start}:{y_end}")
self.log(f" Strip source: [:, {blend_w}:] -> {w_strip - blend_w} cols")
result[y_offset:y_offset + h_strip, w_base:] = strip[:, blend_w:] result[y_offset:y_offset + h_strip, w_base:] = strip[:, blend_w:]
# Step 3: Create blend # Step 3: Create blend
@ -213,50 +193,55 @@ class StitchingScanner:
strip_overlap = strip[:, :blend_w].astype(np.float32) strip_overlap = strip[:, :blend_w].astype(np.float32)
blended = (base_overlap * alpha + strip_overlap * (1 - alpha)).astype(np.uint8) blended = (base_overlap * alpha + strip_overlap * (1 - alpha)).astype(np.uint8)
# Step 4: Place blend (overwrites part of base at correct Y) # Step 4: Place blend
blend_x_start = w_base - blend_w
blend_x_end = w_base
self.log(f" Step 4: Blend zone at X={blend_x_start}:{blend_x_end}, Y={y_start}:{y_end}")
result[y_offset:y_offset + h_strip, w_base - blend_w:w_base] = blended result[y_offset:y_offset + h_strip, w_base - blend_w:w_base] = blended
self.log(f" Final: Strip placed at X={w_base - blend_w}, Y={y_offset}")
return result return result
else: # append_left else: # append_left - place at x_offset, NO width expansion
result_width = w_base + w_strip - blend_w # x_offset is where the LEFT edge of the strip should go
result = np.zeros((h_base, result_width, 3), dtype=np.uint8) if x_offset is None:
x_offset = 0
# Clamp x_offset to valid range
x_offset = max(0, min(x_offset, w_base - blend_w))
self.log(f"=== _blend_horizontal_at_y (append_left) ===") self.log(f"=== _blend_horizontal_at_y (append_left) ===")
self.log(f" base: {w_base}x{h_base}, strip: {w_strip}x{h_strip}") self.log(f" base: {w_base}x{h_base}, strip: {w_strip}x{h_strip}")
self.log(f" y_offset: {y_offset}, blend_w: {blend_w}") self.log(f" x_offset: {x_offset}, y_offset: {y_offset}, blend_w: {blend_w}")
self.log(f" result: {result_width}x{h_base}")
# Step 1: Copy ENTIRE base shifted right # Result is same size as base (no expansion when going left)
base_x_start = w_strip - blend_w result = base.copy()
self.log(f" Step 1: Copy base to result[:, {base_x_start}:] (shifted right)")
result[:, w_strip - blend_w:] = base
# Step 2: Copy non-overlap portion of strip at correct Y # Calculate placement bounds
strip_x_end = w_strip - blend_w strip_x_start = x_offset
y_start = y_offset strip_x_end = min(x_offset + w_strip, w_base)
y_end = y_offset + h_strip strip_cols_to_copy = strip_x_end - strip_x_start
self.log(f" Step 2: Place strip at X=0:{strip_x_end}, Y={y_start}:{y_end}")
self.log(f" Strip source: [:, :{strip_x_end}] -> {strip_x_end} cols")
result[y_offset:y_offset + h_strip, :w_strip - blend_w] = strip[:, :w_strip - blend_w]
# Step 3: Create blend self.log(f" Placing strip at X={strip_x_start}:{strip_x_end}, Y={y_offset}:{y_offset + h_strip}")
alpha = np.linspace(0, 1, blend_w, dtype=np.float32)[np.newaxis, :, np.newaxis] self.log(f" Strip cols to copy: {strip_cols_to_copy}")
# Step 1: Copy strip content (non-blend portion) at correct position
# For LEFT scanning, blend is on the RIGHT side of the strip
non_blend_end = strip_cols_to_copy - blend_w
if non_blend_end > 0:
result[y_offset:y_offset + h_strip, strip_x_start:strip_x_start + non_blend_end] = strip[:, :non_blend_end]
self.log(f" Step 1: Placed non-blend at X={strip_x_start}:{strip_x_start + non_blend_end}")
# Step 2: Create blend on the RIGHT edge of strip (blending with existing content)
blend_x_start = strip_x_end - blend_w
blend_x_end = strip_x_end
if blend_w > 0 and blend_x_start >= strip_x_start:
alpha = np.linspace(1, 0, blend_w, dtype=np.float32)[np.newaxis, :, np.newaxis]
strip_overlap = strip[:, -blend_w:].astype(np.float32) strip_overlap = strip[:, -blend_w:].astype(np.float32)
base_overlap = base[y_offset:y_offset + h_strip, :blend_w].astype(np.float32) base_overlap = base[y_offset:y_offset + h_strip, blend_x_start:blend_x_end].astype(np.float32)
blended = (strip_overlap * (1 - alpha) + base_overlap * alpha).astype(np.uint8) blended = (strip_overlap * alpha + base_overlap * (1 - alpha)).astype(np.uint8)
# Step 4: Place blend at correct Y result[y_offset:y_offset + h_strip, blend_x_start:blend_x_end] = blended
blend_x_start = w_strip - blend_w self.log(f" Step 2: Blend zone at X={blend_x_start}:{blend_x_end}")
blend_x_end = w_strip
self.log(f" Step 4: Blend zone at X={blend_x_start}:{blend_x_end}, Y={y_start}:{y_end}")
result[y_offset:y_offset + h_strip, w_strip - blend_w:w_strip] = blended
self.log(f" Final: Strip placed at X=0, Y={y_offset} (base shifted right by {base_x_start})") self.log(f" Final: Strip placed at X={strip_x_start}, Y={y_offset}, mosaic size unchanged: {w_base}x{h_base}")
return result return result
def _blend_horizontal(self, base: np.ndarray, strip: np.ndarray, def _blend_horizontal(self, base: np.ndarray, strip: np.ndarray,
@ -433,12 +418,12 @@ class StitchingScanner:
strip_start = max(0, w - append_width - BLEND_WIDTH) strip_start = max(0, w - append_width - BLEND_WIDTH)
new_strip = frame[:, strip_start:] new_strip = frame[:, strip_start:]
self.mosaic = self._blend_horizontal_at_y( self.mosaic = self._blend_horizontal_at_y(
self.mosaic, new_strip, BLEND_WIDTH, append_right=True, x_off=int(self.state.current_x), y_offset=y_offset) self.mosaic, new_strip, BLEND_WIDTH, append_right=True, x_offset=int(self.state.current_x), y_offset=y_offset)
else: else:
strip_end = min(w, append_width + BLEND_WIDTH) strip_end = min(w, append_width + BLEND_WIDTH)
new_strip = frame[:, :strip_end] new_strip = frame[:, :strip_end]
self.mosaic = self._blend_horizontal_at_y( self.mosaic = self._blend_horizontal_at_y(
self.mosaic, new_strip, BLEND_WIDTH, append_right=False, x_off=int(self.state.current_x), y_offset=y_offset) self.mosaic, new_strip, BLEND_WIDTH, append_right=False, x_offset=int(self.state.current_x), y_offset=y_offset)
self._displacement_since_append_x = fractional_remainder self._displacement_since_append_x = fractional_remainder
self._displacement_since_append_y = 0.0 self._displacement_since_append_y = 0.0