From 230d0ed0a112f5f56eb2e44de3378c420be7d2c2 Mon Sep 17 00:00:00 2001 From: Alex-Gilbert Date: Tue, 17 Feb 2026 12:33:47 -0600 Subject: [PATCH] fix: use clean neighboring lines for font detection near redactions Redaction boxes corrupt OCR text and add spurious dark pixels that break pixel-based font scoring. Now uses wider crop padding (3x) and prefers the nearest non-overlapping line for font detection. Co-Authored-By: Claude Opus 4.6 --- unredact/app.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/unredact/app.py b/unredact/app.py index ff03288..de80c4f 100644 --- a/unredact/app.py +++ b/unredact/app.py @@ -148,7 +148,9 @@ class AnalyzeRequest(BaseModel): def _run_analysis(page_img: Image.Image, rx: int, ry: int, rw: int, rh: int) -> dict | None: """Run OCR + font detection for a redaction box. Returns analysis dict or None.""" - pad_y = rh + # Use wider padding to capture neighboring lines for font detection + # (the line containing the redaction has corrupted OCR and pixel data). + pad_y = rh * 3 crop_y1 = max(0, ry - pad_y) crop_y2 = min(page_img.height, ry + rh + pad_y) line_crop = page_img.crop((0, crop_y1, page_img.width, crop_y2)) @@ -160,7 +162,22 @@ def _run_analysis(page_img: Image.Image, rx: int, ry: int, rw: int, rh: int) -> redaction_cy = (ry - crop_y1) + rh / 2 best_line = min(lines, key=lambda l: abs((l.y + l.h / 2) - redaction_cy)) - font_match = detect_font_for_line(best_line, line_crop) + # For font detection, prefer a nearby line that does NOT overlap the + # redaction box — the redaction's dark pixels and OCR artifacts make + # pixel-based scoring unreliable on the redaction line itself. + red_y1_local = ry - crop_y1 + red_y2_local = ry + rh - crop_y1 + clean_lines = [ + line for line in lines + if not (line.y < red_y2_local and line.y + line.h > red_y1_local) + and len(line.text.strip()) >= 5 + ] + if clean_lines: + font_line = min(clean_lines, key=lambda l: abs((l.y + l.h / 2) - redaction_cy)) + else: + font_line = best_line + + font_match = detect_font_for_line(font_line, line_crop) segments = [] gap = {"x": rx, "w": rw}