mirror of
https://github.com/PR0M3TH3AN/unredact.git
synced 2026-10-27 16:50:30 +00:00
- Render each word at its OCR'd position instead of whole lines, so word spacing matches the original document exactly - Add y-offset correction using glyph bounding box - Add fine-grained font size search (±3 around coarse best, step 1) - Add alignment quality test (48.9% hit rate, >30% threshold) - Add scipy to dev dependencies Co-Authored-By: Claude Opus 4.6 <[email protected]>
52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
from pathlib import Path
|
|
|
|
import numpy as np
|
|
from PIL import Image
|
|
from scipy.ndimage import binary_dilation
|
|
|
|
from unredact.pipeline.rasterize import rasterize_pdf
|
|
from unredact.pipeline.ocr import ocr_page
|
|
from unredact.pipeline.font_detect import detect_font
|
|
from unredact.pipeline.overlay import render_overlay
|
|
|
|
|
|
def test_overlay_alignment_score(sample_pdf: Path):
|
|
"""Measure how well the overlay aligns with the original text.
|
|
|
|
Strategy: compare the overlay-only green pixels against the original
|
|
dark text pixels. Where they overlap (within a few pixels tolerance),
|
|
that's a hit. We want a reasonable hit rate.
|
|
"""
|
|
pages = rasterize_pdf(sample_pdf, first_page=1, last_page=1)
|
|
page = pages[0]
|
|
lines = ocr_page(page)
|
|
font_match = detect_font(lines, page)
|
|
overlay = render_overlay(page, lines, font_match)
|
|
|
|
orig_arr = np.array(page.convert("L")) # grayscale
|
|
overlay_arr = np.array(overlay)
|
|
|
|
# Original dark text pixels (< 128 on grayscale)
|
|
text_mask = orig_arr < 128
|
|
|
|
# Overlay green pixels (green channel > 100)
|
|
green_mask = overlay_arr[:, :, 1] > 100
|
|
|
|
# How many text pixels have green overlay nearby (within 3px tolerance)?
|
|
green_dilated = binary_dilation(green_mask, iterations=3)
|
|
|
|
overlap = text_mask & green_dilated
|
|
if text_mask.sum() == 0:
|
|
return
|
|
|
|
hit_rate = overlap.sum() / text_mask.sum()
|
|
print(f"\nAlignment hit rate: {hit_rate:.1%}")
|
|
print(f" Text pixels: {text_mask.sum()}")
|
|
print(f" Green pixels: {green_mask.sum()}")
|
|
print(f" Overlap pixels: {overlap.sum()}")
|
|
|
|
# We want at least 30% of text pixels to have overlay nearby
|
|
# (not 100% because redaction boxes are dark too, and headers/footers
|
|
# may use different fonts)
|
|
assert hit_rate > 0.3, f"Overlay alignment too low: {hit_rate:.1%}"
|