Skip to content

Blur + remove background: cut out from the clean photo, clip the blur to it - #47

Merged
JamesmarkeyUK merged 1 commit into
mainfrom
claude/blur-face-remove-bg-order-v9yj7k
Jul 27, 2026
Merged

Blur + remove background: cut out from the clean photo, clip the blur to it#47
JamesmarkeyUK merged 1 commit into
mainfrom
claude/blur-face-remove-bg-order-v9yj7k

Conversation

@JamesmarkeyUK

Copy link
Copy Markdown
Contributor

The bug

Blurring faces and then removing the background left an opaque blurred rectangle where the face was — the hair around it cut out cleanly, but the background inside the blur square survived.

removeBackground was running the segmentation model on img.file, which after a redaction is the baked blurred PNG. With no detail left inside the blur, the model classifies the entire blurred block as foreground, so nothing inside it gets cut away.

The fix

The blur is now modelled as a layer above the background edit, so the two compose in either order:

  • removeBackground always segments the clean, un-blurred image (faceOriginal when a redaction is applied), so the matte is computed from real pixels.
  • The redaction is re-baked over the finished cut-out, rendered from the opaque pre-removal photo and stencilled by the cut-out's alpha — renderRedacted's new mask argument, a destination-in composite. The blurred layer is deleted in exactly the same places the background is. Rendering from the opaque original (rather than blurring the transparent cut-out) keeps the silhouette crisp; resampling transparency directly would smear the alpha and fray the edge.
  • bgOriginal / bgCutout now always hold clean snapshots, and faceOriginal holds the un-blurred image for whichever background state is current. Restore background and Remove blur stay available and undo independently, in any order. Restoring the background re-bakes the blur onto the full image rather than silently un-redacting the faces.
  • Both re-bakes run before the new bitmap is swapped in (bakeFaceBlur is pure and touches no store state), so neither action ever shows an un-redacted frame.
  • Face detection after a removal runs on the opaque original, not the subject-against-black cut-out.

Verification

npm run typecheck and npm run build pass.

The real renderRedacted was also driven in headless Chromium against a synthetic photo + cut-out, with a face box deliberately straddling the cut-out edge:

sample point result
background area, outside face box [0,0,0,0] — removed
inside face box, in the removed-background area [0,0,0,0] — blur erased with the background
inside face box, inside subject blurred, alpha 255
inside subject, outside face box pixel-identical to original
no-mask path (blur only) unchanged, opaque throughout

Round-trips checked by trace: blur → remove bg → restore bg → remove bg (cache hit) returns to a consistent state at each step, with no leaked or double-revoked object URLs.


Generated by Claude Code

… to it

Blurring faces and then removing the background left an opaque blurred
rectangle where the face was. The segmentation model was being handed the
already-blurred bake: with no detail left inside the redaction it keeps the
whole blurred block as foreground, so the "background" inside that block
survived the cut-out.

Model the blur as a layer *above* the background edit instead, so the two
compose in either order:

- `removeBackground` always segments the clean, un-blurred image
  (`faceOriginal` when a redaction is applied), so the matte is computed from
  real pixels.
- The redaction is then re-baked over the finished cut-out, rendered from the
  opaque pre-removal photo and stencilled by the cut-out's alpha
  (`renderRedacted`'s new `mask` argument, a `destination-in` composite). The
  blurred layer is deleted in exactly the same places the background is, and
  rendering from the opaque original keeps the silhouette crisp — resampling
  the transparent cut-out directly would smear its alpha.
- `bgOriginal` / `bgCutout` now always hold clean snapshots, and `faceOriginal`
  holds the un-blurred image for whichever background state is current, so
  Restore background / Remove blur both stay available and undo independently.
  Restoring the background re-bakes the blur onto the full image rather than
  silently un-redacting it.
- Both re-bakes run before the new bitmap is swapped in, so neither action ever
  shows an un-redacted frame, and face detection after a removal runs on the
  opaque original rather than a subject against black.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PWVk4ejHQqT27pjX4wgcQq
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying universal-images with  Cloudflare Pages  Cloudflare Pages

Latest commit: 21dcd2f
Status: ✅  Deploy successful!
Preview URL: https://52249aeb.universal-images-60x.pages.dev
Branch Preview URL: https://claude-blur-face-remove-bg-o.universal-images-60x.pages.dev

View logs

@JamesmarkeyUK
JamesmarkeyUK merged commit 4fec1a4 into main Jul 27, 2026
2 checks passed
@JamesmarkeyUK
JamesmarkeyUK deleted the claude/blur-face-remove-bg-order-v9yj7k branch July 27, 2026 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants