Fix left-side gutter detection: find peak instead of scanning from edge
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 40s
CI / test-go-edu-search (push) Successful in 42s
CI / test-python-klausur (push) Failing after 2m39s
CI / test-python-agent-core (push) Successful in 30s
CI / test-nodejs-website (push) Successful in 32s

Left-side book fold shadows have a V-shape: brightness dips from the
edge toward a peak at ~5-10% of width, then rises again. The previous
algorithm scanned from the edge inward and immediately found a low
dark fraction (0.13 at x=0), missing the gutter entirely.

Now finds the PEAK of the dark fraction profile first, then scans from
that peak toward the page center to find the transition point. Works
for both V-shaped left gutters and edge-darkening right gutters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-11 16:52:23 +02:00
parent 9c5e950c99
commit 00f7a7154c

View File

@@ -535,19 +535,30 @@ def _detect_gutter_continuity(
if region_w <= 2 * margin + 10:
return None
# Scan from edge inward to find where frac drops below transition threshold
# Find the peak of dark fraction (gutter center).
# For right gutters the peak is near the edge; for left gutters
# (V-shaped spine shadow) the peak may be well inside the region.
transition_thresh = 0.50
peak_frac = float(np.max(frac_smooth[margin:region_w - margin]))
if peak_frac < 0.70:
logger.debug(
"%s gutter: peak dark fraction %.2f < 0.70", side.capitalize(), peak_frac,
)
return None
peak_x = int(np.argmax(frac_smooth[margin:region_w - margin])) + margin
gutter_inner = None # local x in search_region
if side == "right":
# Scan from right edge (region_w - 1) inward (toward 0)
for x in range(region_w - 1 - margin, margin, -1):
# Scan from peak toward the page center (leftward)
for x in range(peak_x, margin, -1):
if frac_smooth[x] < transition_thresh:
gutter_inner = x + 1 # crop just past the transition
gutter_inner = x + 1
break
else:
# Scan from left edge (0) inward (toward region_w)
for x in range(margin, region_w - margin):
# Scan from peak toward the page center (rightward)
for x in range(peak_x, region_w - margin):
if frac_smooth[x] < transition_thresh:
gutter_inner = x - 1
break