Nodes/ComfyUI-JH-PixelPro/JHPixelProUnwrapFace
ComfyUI Node

JHPixelProUnwrapFace

Put Your Edited Face Back on the Canvas

By jetthuangai·Created 5 months ago·Updated 4 months ago· 5
JHPixelProUnwrapFace
  • edited_aligned
  • original_image
  • mask_override
  • image_composited
  • mask_used
inverse_matrix_json[[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]]
feather_radius16

JHPixelProUnwrapFace is the return trip in the pack's face-edit pipeline. The pattern: the FacialAligner node warps a face into a canonical frame - a consistent eye/nose/mouth position - you run your AI work on that aligned crop (ControlNet, face detail, inpaint), and then this node warps the edited result back onto the original canvas and composites it in. Without it you'd be stuck editing on the aligned crop and pasting back with a crude box that never lines up.

It consumes the inverse_matrix_json that the FacialAligner emits - the inverse affine that maps the canonical frame back to the original photo. Wire the aligner's output straight into this node's inverse_matrix_json input; no manual paste. The node warps via kornia.warp_affine and alpha-composites with a feathered mask, so everything outside the face stays untouched. This is the same "edit the crop, stitch back the whole frame" discipline the community converges on for face detail - the unmasked parts of the image never pass through the edit at all.

Inputs:

  • edited_aligned - the aligned face IMAGE after your edit (from your ControlNet/inpaint chain).
  • original_image - the full original canvas, the composite target. The output matches its size exactly.
  • inverse_matrix_json - from the FacialAligner. The default is identity, a safe pass-through if nothing is wired.
  • feather_radius (default 16) - Gaussian blur on the auto face mask. Higher = smoother blend, 0 = hard edge. Ignored if you wire mask_override.
  • mask_override (optional MASK) - a custom mask in original-canvas coordinates to restrict the composite to a precise region.

Outputs:

  • image_composited - the edit back on the full canvas.
  • mask_used - the actual mask applied; wire it into a downstream ImageBlend if you want multiply/screen blends instead of plain alpha-over.

The standout tip: mask_override is where you fix the "face edge looks pasted" problem. Feed a skin-region mask from SAM or rembg, and the edit only lands on skin, leaving hair and background alone.

Install is the shared pack install:

cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt

Restart and it's under ComfyUI-JH-PixelPro/face, or use ComfyUI Manager → search "ComfyUI-JH-PixelPro". If you get an import failure at startup, check for a kornia version clash with another pack - a recurring ComfyUI pain point - and pin kornia to 0.7.x.

Troubleshooting: this node requires the FacialAligner upstream. Hand-pasting a matrix risks shape and unit mismatch, and the README is explicit about always pairing them - let the wire carry the matrix. Round-trip softening is real: align + edit + unwrap puts the image through two bilinear resamples plus a feather, so don't chain multiple unwrap rounds; expect ~10–34/255 softening in uint8, which is fine for retouch and not fine for near-lossless. And it's warp-dominated: at 2048² on CPU it's roughly 200 ms, versus well under 60 ms on GPU - use CUDA for production 2K+ work.

CategoryComfyUI-JH-PixelPro/face

Inputs (5)

NameTypeDefaultDescription
edited_alignedIMAGE
original_imageIMAGE
inverse_matrix_jsonSTRING[[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]]Output of S-06 Facial Aligner — Bx3x3 (or Bx2x3) affine per batch, JSON serialized. Default identity is a safe pass-through when nothing is wired.
feather_radiusFLOAT160–128Gaussian edge blur (pixels) applied to the auto-generated mask. Higher = smoother blend at cost of softer face edge; 0 = hard edge. Ignored when mask_override is wired.
mask_overrideoptMASK

Outputs (2)

NameTypeDescription
image_compositedIMAGE
mask_usedMASK