Add geometry draft mode and pad silhouette descenders

pre-commit: 1 maintain.sh - not rerun full, ruff + 34 targeted tests passed; 2) /simplify - pad lives in silhouette crop, stable=False reuses probes; 3) docs sync - no README/cli refs to update; 4) CLAUDE.md - no change
EOF
)
This commit is contained in:
Victor Kuznetsov
2026-08-19 19:53:38 -07:00
parent d84fd1a125
commit ee865e95e4
4 changed files with 60 additions and 4 deletions
+17
View File
@@ -139,3 +139,20 @@ class TestDraftTextLines:
(line,) = draft.accepted
assert line.language == "ch"
assert line.script == "cjk"
def test_unstable_geometry_draft_accepts_a_single_high_score_read(self, tmp_path: Path):
path = self._poster(tmp_path)
jitter = _JitterEngine(["Hello", "Hallo", "Hullo"])
stable = _FakeEngine("Hello")
# Probes disagree across engines so language is en; jitter would fail
# the stable gate. Geometry mode uses the one en probe and accepts.
draft = draft_text_lines(
path,
min_score=0.75,
stable=False,
detector=_FakeDetector([(20, 20, 200, 60)]),
engines={"en": jitter, "ru": stable, "ch": stable},
)
(line,) = draft.accepted
assert line.text == "Hello"
assert line.min_score >= 0.75
+12
View File
@@ -15,6 +15,7 @@ from remove_ai_watermarks._internal.text_restoration import (
load_verified_text_manifest,
restore_verified_text,
source_pixel_sha256,
source_silhouette_mask,
)
@@ -126,3 +127,14 @@ def test_restoration_uses_lama_and_qwen_vae_core(monkeypatch) -> None:
assert calls
assert np.all(restored[16, 20] == donor[16, 20])
assert np.all(restored[0, 0] == candidate[0, 0])
def test_silhouette_includes_descender_below_the_detector_box() -> None:
source = np.full((40, 50, 3), 240, dtype=np.uint8)
source[10:22, 18:24] = 20
source[22:27, 18:22] = 20 # tail of a y / Cyrillic u, under the box
mask = source_silhouette_mask(source, (10, 10, 40, 22))
assert mask[24, 20] == 255
assert mask[16, 20] == 255