Nodes/OcclusionMask/Occlusion Mask (Face Protection for ReActor)
ComfyUI Node

Occlusion Mask (Face Protection for ReActor)

Occlusion Mask

By ialhabbal·Created about a year ago·Updated 4 months ago· 38
Occlusion Mask (Face Protection for ReActor)
  • input_image
  • IMAGE
  • MASK
  • PREVIEW
face_targetLargest face only
face_crop_padding0.15
fallback_to_full_imagefalse
detection_sensitivity0.65
mask_expansion6
edge_softness4
mask_modeSoft (recommended)

Ever swapped a face only to watch the microphone, the hand, or the sunglasses get painted over with forehead? That's the ReActor trap this node exists to fix. ReActor is a pixel-level, post-process face swap - it doesn't know there's a mic in front of your subject's mouth, so it cheerfully replaces those pixels with skin. Occlusion Mask detects whatever is physically covering the face and hands ReActor a mask that says "leave these pixels alone." The name is accurate: it protects occluders, not faces.

How it works

This is a two-model pipeline, and the clever part is that it's two models disagreeing on purpose:

  1. InsightFace detects the face(s) - the same backbone under ReActor, Roop, and FaceFusion.
  2. The face region is cropped (with padding), resized to 256×256, and run through occluder.onnx, which flags "something is in front of the face here."
  3. XSeg_model.onnx (a DeepFaceLab model) marks the actual face-skin region.
  4. Final mask = occluder AND NOT face skin. That second step is what stops the occluder from protecting the whole cheek - if XSeg says it's skin, it gets swapped.

Then the mask is expanded, feathered, and pasted back onto the full image, unioned across every detected face. Nothing here calls an API or needs a key - it's all local ONNX inference, and the models load once and cache, so batches get faster after the first frame.

The inputs that actually matter

Eight required inputs, but you'll live in four of them. The defaults (sensitivity 0.65, expansion +6, softness 4, Soft mode) are a genuinely good start.

  • detection_sensitivity (0–1, default 0.65) - the one you'll tune most. Low catches only big stuff like a hand over the mouth; high catches thin wires and mesh but risks bleeding into face edges.
  • mask_expansion (default +6) - grows the mask as a safety buffer so swap pixels don't leak under the object's edge. Go negative only if the mask is eating real face skin.
  • edge_softness (default 4) - Gaussian blur after expansion, so the protected object blends instead of showing a hard seam. 4–8px for most things.
  • mask_mode - Soft (gradient mask, best-looking) vs Hard (strict 0/1). Flip to Hard if you see ghosting at object boundaries.

face_target switches from "Largest face only" (fast, correct for single subjects) to "All faces" for group shots, face_crop_padding widens the detection window if objects near the face edge are missed, and fallback_to_full_image treats the whole frame as the face region when InsightFace can't find a face at all - useful for heavy occlusion, but leave it off otherwise.

Wiring it up

Three outputs: IMAGE (a clean passthrough) → ReActor's image input, MASK → ReActor's face_mask input, and PREVIEW → any Preview Image node. The preview is the whole game: red overlay = protected pixels, green boxes = detected faces. Tune until the mic is fully red and the cheeks aren't, then run the swap.

Load Image → OcclusionMask → IMAGE → ReActor
                     MASK → ReActor (face_mask)
                 PREVIEW → Preview Image

Installing it

The repo's README now says "Moved to ComfyUI-ialhabbal" - this node lives in the author's 8-node suite, so install that instead:

cd ComfyUI/custom_nodes
git clone https://github.com/ialhabbal/ComfyUI-ialhabbal.git

Then pip install insightface onnxruntime opencv-python numpy Pillow retina-face ultralytics segment-anything, and restart. Note the heavy bit: InsightFace has a well-earned reputation as one of the worst installs in local AI - the May 2026 1.0 release finally dropped the C++ build requirement, so current installs are far less cursed than the old guides suggest.

The gotcha that bites everyone: the node expects occluder.onnx and XSeg_model.onnx in a models/ folder inside the custom node directory, and the repo removed those files in April 2026 to slim down. Fresh installs must source them and drop them in place; InsightFace's buffalo_l pack, by contrast, auto-downloads on first run.

Troubleshooting

  • Preview shows no protection → raise sensitivity to 0.75–0.85, then raise crop padding.
  • Red bleeding onto cheeks/lips → lower sensitivity, then negative expansion (-3 to -8).
  • Seam or halo around the object → expansion +3–5 and softness +2–3.
  • Empty mask entirely → InsightFace found no face; enable fallback or fix the InsightFace install.
  • Ghosting at object edges → switch to Hard mask mode.

For the record: a singer with a handheld mic is the classic use case - sensitivity 0.65, expansion +8, softness 5, Soft. That's the author's own starting point. And if you're just swapping clean faces with nothing in front of them, you don't need this node at all.

Categoryimage/faceswap

Inputs (8)

NameTypeDefaultDescription
input_imageIMAGE
face_targetCOMBOLargest face onlyLargest face only: fastest, best for single-subject images. All faces: processes every detected face independently and unions the masks.
face_crop_paddingFLOAT0.150–0.5How much extra area around the detected face bounding box to include before running the occlusion models. Increase if objects near the face edges are being missed. 15% is a good default.
fallback_to_full_imageBOOLEANfalseIf enabled and no face is detected, the entire image is treated as the face region. Useful for heavily occluded faces. Disable for safety to avoid accidental full-image masking.
detection_sensitivityFLOAT0.650–1Controls how aggressively objects are detected. LOW (0.2–0.4): only very prominent occlusions like a hand covering the face. MID (0.5–0.7): good default — catches microphones, glasses, held objects. HIGH (0.8–1.0): catches subtle occlusions but may bleed into face edges.
mask_expansionINT6-20–50Expands (positive) or shrinks (negative) the detected occlusion mask. Positive values add a safety margin around objects — recommended to avoid faceswap pixels bleeding under object edges. Negative values trim the mask if it's accidentally covering face skin.
edge_softnessINT40–30Gaussian blur applied to the mask AFTER expansion. Soft edges create a smoother transition between the swapped face and the preserved object, avoiding hard seams. 4–8px is recommended for most cases.
mask_modeCOMBOSoft (recommended)Soft: the mask retains gradient values (0.0–1.0) allowing partial blending at object boundaries — best for natural-looking results. Hard: mask is strictly 0 or 1 — use if ReActor produces ghosting artifacts with soft masks.

Outputs (3)

NameTypeDescription
IMAGEIMAGE
MASKMASK
PREVIEWIMAGE