refactor(face-restore): wipe GFPGAN path, --restore-faces is PhotoMaker-only

The GFPGAN `restore` extra and its `face_restore.py` module are gone. They were
oracle-confirmed to re-introduce SynthID by blending watermarked original face
pixels at fidelity weight 0.5 (clean A/B: gemini_3 controlnet 0.20 detected WITH
GFPGAN, clean WITHOUT). Keeping them as the default restore method was a footgun
for the removal pipeline. PhotoMaker-V2 (added in the previous commit) is the
single shipped restore path now -- identity-as-embedding, SynthID-safe by
construction.

Removed:
- src/remove_ai_watermarks/face_restore.py + tests/test_face_restore.py
- pyproject.toml `restore` extra (gfpgan/facexlib/basicsr + scipy/numba pins)
- pyproject.toml `[tool.uv.extra-build-dependencies] basicsr = [...]` build pin
- CLI: `--restore-faces-method` and `--restore-faces-weight` (no method choice
  to make, no GFPGAN weight knob to expose)
- InvisibleEngine._restore_faces method (only _restore_faces_photomaker remains)
- All restore-faces-method / restore-faces-weight threading through cmd_*
  signatures and _process_batch_image

Kept:
- `--restore-faces / --no-restore-faces`: now binds to PhotoMaker-V2.
- All adopted oracle findings about GFPGAN re-introducing SynthID (kept in the
  research docs as historical context that explains why the path was removed).

Docs updated: CLAUDE.md (restore extras bullet collapsed to photomaker, removed
face_restore Key-modules bullet, several inline GFPGAN refs scrubbed), README.md
(face-identity callout + install section now point to the photomaker extra),
docs/synthid.md 5.5 (net recipe), docs/controlnet-removal-pipeline-research.md
(recommendations).

ruff + strict pyright (src/) clean; 578 tests pass (the 9 GFPGAN tests are gone,
the 9 PhotoMaker tests stay green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Victor Kuznetsov
2026-06-08 15:35:37 -07:00
parent 1439eb0714
commit 439eeadc07
11 changed files with 64 additions and 1638 deletions
+5 -3
View File
@@ -124,9 +124,11 @@ Gemini app; the two payloads are vendor-specific and never cross-checked):
- **Fix the seed in prod.** The non-determinism is purely `seed=None` (random); a fixed
`--seed` makes every run reproduce the certified-clean result, so you ship a
deterministic, re-certifiable config (and the seed sweep collapses to one config).
- **Rework `--restore-faces` before any removal use:** run GFPGAN on the diffusion-CLEANED
image (not the original), or drop the weight well below 0.5, or leave it off — then
re-validate on the oracle.
- **`--restore-faces` is SynthID-safe by construction now (PhotoMaker-V2, 2026-06-04).**
The GFPGAN-on-original path that re-added SynthID was removed; the shipped restore
carries identity in a SynthID-invariant OpenCLIP embedding and regenerates fresh
pixels conditioned on it. Needs the `photomaker` extra. See
`docs/synthid-robust-identity-research.md`.
- **No local SynthID detector exists** → the service can't self-verify; bake in strength
margin and periodic oracle spot-checks.
- **Lesson:** visual-quality / face-identity recovery does NOT prove removal — only the
+3 -2
View File
@@ -568,8 +568,9 @@ table.
**Net for raiw.cc:** (1) controlnet needs a higher, per-vendor strength than
`default` -- CERTIFIED OpenAI 0.20 / Gemini 0.30 (above); add a controlnet-specific
schedule to `resolve_strength`, do not reuse the default ladder; (2) the
`--restore-faces` pass can re-add SynthID and must be reworked (restore on the
cleaned image / lower weight / off) before it is safe in a removal pipeline; (3)
`--restore-faces` pass is now SynthID-safe by construction (the GFPGAN-on-original
path that re-added SynthID was removed 2026-06-04; the shipped restore is
PhotoMaker-V2, identity-as-embedding, see `synthid-robust-identity-research.md`); (3)
removal near threshold is seed-non-deterministic -> FIX the prod seed (kills the
coin-flip; ship a deterministic certified config).