From 0b700a6d996a211337611f048c97a53d334b40f7 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Mon, 6 Apr 2026 14:20:27 -0700 Subject: [PATCH] =?UTF-8?q?feat(adversarial):=20=E2=9C=A8=20Add=20periocul?= =?UTF-8?q?ar=20adversarial=20robustness=20model=20for=20testing=20in=20ad?= =?UTF-8?q?versarial=20service?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../service/src/models/periocular_model.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/services/imajin-adversarial/service/src/models/periocular_model.py b/services/imajin-adversarial/service/src/models/periocular_model.py index 52577acf..9890c7e5 100644 --- a/services/imajin-adversarial/service/src/models/periocular_model.py +++ b/services/imajin-adversarial/service/src/models/periocular_model.py @@ -120,7 +120,20 @@ class PeriocularCloakModel: l2, linf = perturbation_stats(x, x_adv) adv_np = x_adv.squeeze(0).permute(1, 2, 0).cpu().numpy().clip(0.0, 1.0) - result[py1:py2, x1:x2] = adv_np[:, :, ::-1] # RGB → BGR + + # Feathered writeback: blend perturbation to zero at top/bottom strip edges + # so the boundary doesn't render as a visible crease on the face. + strip_h = py2 - py1 + ramp_h = min(16, strip_h // 5) + ramp = np.linspace(0.0, 1.0, ramp_h, dtype=np.float32) + mask = np.ones(strip_h, dtype=np.float32) + mask[:ramp_h] = ramp + mask[strip_h - ramp_h:] = ramp[::-1] + mask_3d = mask[:, np.newaxis, np.newaxis] # (H, 1, 1) → broadcasts over W and C + + original_strip = result[py1:py2, x1:x2].copy() + perturbed_strip = adv_np[:, :, ::-1] # RGB → BGR + result[py1:py2, x1:x2] = original_strip * (1.0 - mask_3d) + perturbed_strip * mask_3d total_l2 += l2 total_linf = max(total_linf, linf)