Nodes/comfyui-superside-nodes/Superside Portrait Sections
ComfyUI Node

Superside Portrait Sections

Build a portrait mask by checking boxes — eyes, lips, hair, clothing, merged

By Superside·Created about a month ago·Updated 3 days ago· 1
Superside Portrait Sections
  • image
  • mask
  • info
  • color_preview
api_key
skinfalse
nosetrue
eyestrue
eyebrowsfalse
earstrue
mouthtrue
lipstrue
hairtrue
hattrue
glassestrue
earringsfalse
neckfalse
necklacefalse
clothingfalse
skin_opacity1.00
nose_opacity1.00
eyes_opacity1.00
eyebrows_opacity1.00
ears_opacity1.00
mouth_opacity1.00
lips_opacity1.00
hair_opacity1.00
hat_opacity1.00
glasses_opacity1.00
earrings_opacity1.00
neck_opacity1.00
necklace_opacity1.00
clothing_opacity1.00
glasses_prompt_overrideeyeglasses frame only - the metal or plastic rim and temples, not the lens or the skin behind it
glasses_box_center_x-1
glasses_box_center_y-1
glasses_box_width-1
glasses_box_height-1
padding_percent0.0
partial_feather_percent0.0
partial_contract_percent0.0

The face-parsing problem, solved by checkboxes. When you want to retouch a portrait's skin but not touch the eyes, lips, or hair, you need a mask of everything to protect - and this node builds that mask from a list of facial sections you toggle on and off: skin, nose, eyes, eyebrows, ears, mouth, lips, hair, hat, glasses, earrings, neck, necklace, clothing. Each active section gets segmented and the results merge into one MASK output. It's the Superside in-house replacement for a local face-parsing model's per-region checklist, and it runs on fal's SAM 3 (fal-ai/sam-3/image) instead of local weights.

The canonical use case is an exclusion mask for a re-skin pass: retouch the skin, then composite the original back over everything this mask covers so eyes and hair come through untouched. The README is explicit about the trade-off vs. a dedicated local face-parsing network - SAM 3 is promptable and open-vocabulary rather than a fixed pixel-labeled taxonomy, so boundaries can be slightly less crisp, and you pay one extra fal call per active section. Keep your toggle count low and the cost stays low.

The inputs that matter

  • image, api_key - the essentials. Then the section toggles. The defaults mirror the original re-skin workflow's exclusion set (nose/eyes/ears/mouth/lips/hair/hat on, the rest off), which is a sane starting point: you generally do want to protect facial features and hair from a skin retouch.
  • Every section also has a <section>_opacity (0–1, default 1.0). This is the sophisticated bit: 1.0 writes the section fully white in the mask (fully protected - original wins in the composite); 0.5 writes gray, which blends 50% original / 50% generated - i.e. partial retouch on that section. clothing_opacity = 0.5, for instance, gets you a half-strength retouch on clothing. At all-defaults it reproduces the old binary mask exactly, so upgrading a saved workflow is safe.
  • padding_percent - grow the merged mask, useful when a section's edge is slightly loose.
  • partial_feather_percent / partial_contract_percent - for the gray partial sections only: feather softens the partial region's edge so the blend has no hard line, and contract erodes it inward first so the soft edge sits inside the region instead of bleeding a faint ring onto the surrounding skin. If you're using partial opacity, set contract near or above feather.
  • glasses_prompt_override - the SAM 3 text query for glasses (default targets just the frame/temples, not the lens). Tune it if the glasses mask keeps swallowing the lens.
  • glasses_box_center_x/y + glasses_box_width/height - an optional GroundingDINO-style box (e.g. from a Florence-2 region selector) so SAM 3 refines a known box instead of searching by text alone. The classic "text finds it, box nails it" two-stage pattern.

Three outputs: mask (MASK, merged), info (STRING, JSON of which sections were used), and color_preview (IMAGE) - a color-coded preview where each section is tinted so you can see the mask's coverage at a glance.

How it works

For each active toggle it makes one SAM 3 call with that section's text prompt, downloads the mask, applies opacity/feather/contract, and OR-merges everything into one mask. That means a section that fails its SAM call is skipped with a warning rather than killing the run - the info output is where you see that. Cost is directly proportional to active toggles, so disable the sections you don't need.

Installing it

cd ComfyUI/custom_nodes
git clone https://github.com/Superside/comfyui-superside-nodes
pip install -r requirements.txt

Restart ComfyUI, find it under Superside, paste a fal key into api_key (blank falls back to a FAL_KEY env var).

One real gotcha

For partial-opacity gray to survive into the composite, the downstream mask nodes must not binarize it - the README calls out that the pack's Grow Mask With Blur and Resize To Match both preserve gray, so stick to those if you're using partial sections. And remember: every active toggle is a billable fal call, so this node's cost adds up fast on a busy face with everything switched on.

CategorySuperside

Inputs (38)

NameTypeDefaultDescription
imageIMAGE
api_keySTRING
skinoptBOOLEANfalse
noseoptBOOLEANtrue
eyesoptBOOLEANtrue
eyebrowsoptBOOLEANfalse
earsoptBOOLEANtrue
mouthoptBOOLEANtrue
lipsoptBOOLEANtrue
hairoptBOOLEANtrue
hatoptBOOLEANtrue
glassesoptBOOLEANtrue
earringsoptBOOLEANfalse
neckoptBOOLEANfalse
necklaceoptBOOLEANfalse
clothingoptBOOLEANfalse
skin_opacityoptFLOAT1.000–1Opacity of 'skin' in the exclusion mask (only when 'skin' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
nose_opacityoptFLOAT1.000–1Opacity of 'nose' in the exclusion mask (only when 'nose' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
eyes_opacityoptFLOAT1.000–1Opacity of 'eyes' in the exclusion mask (only when 'eyes' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
eyebrows_opacityoptFLOAT1.000–1Opacity of 'eyebrows' in the exclusion mask (only when 'eyebrows' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
ears_opacityoptFLOAT1.000–1Opacity of 'ears' in the exclusion mask (only when 'ears' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
mouth_opacityoptFLOAT1.000–1Opacity of 'mouth' in the exclusion mask (only when 'mouth' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
lips_opacityoptFLOAT1.000–1Opacity of 'lips' in the exclusion mask (only when 'lips' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
hair_opacityoptFLOAT1.000–1Opacity of 'hair' in the exclusion mask (only when 'hair' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
hat_opacityoptFLOAT1.000–1Opacity of 'hat' in the exclusion mask (only when 'hat' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
glasses_opacityoptFLOAT1.000–1Opacity of 'glasses' in the exclusion mask (only when 'glasses' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
earrings_opacityoptFLOAT1.000–1Opacity of 'earrings' in the exclusion mask (only when 'earrings' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
neck_opacityoptFLOAT1.000–1Opacity of 'neck' in the exclusion mask (only when 'neck' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
necklace_opacityoptFLOAT1.000–1Opacity of 'necklace' in the exclusion mask (only when 'necklace' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
clothing_opacityoptFLOAT1.000–1Opacity of 'clothing' in the exclusion mask (only when 'clothing' is ON). 1.0 = fully preserve the original here (no retouch). 0.5 = partial (50% original / 50% generated in the final composite). 0.0 = no exclusion.
glasses_prompt_overrideoptSTRINGeyeglasses frame only - the metal or plastic rim and temples, not the lens or the skin behind itSAM 3 text query used for the 'glasses' toggle above. Edit this to tune how tightly it targets just the frame/temples vs. the whole glasses silhouette (frame+lens) - no code changes needed. Only used when 'glasses' is ON.
glasses_box_center_xoptINT-1-1–1000000Optional grounding box for the 'glasses' section, in the old GroundingDINO+SAM style: wire in a Florence-2 Smart Region Selector's center_x/center_y/crop_width/crop_height (query e.g. 'eyeglasses frame') and SAM 3 will refine that box into a precise mask instead of relying on text alone. Leave at -1 (unconnected) to use text-only prompting.
glasses_box_center_yoptINT-1-1–1000000
glasses_box_widthoptINT-1-1–1000000
glasses_box_heightoptINT-1-1–1000000
padding_percentoptFLOAT0.00–50
partial_feather_percentoptFLOAT0.00–25Feather (soft edge) applied ONLY to sections whose opacity is below 1.0 (e.g. clothing at 0.5). Softens the partial region's border so the downstream composite blends it gradually instead of showing a hard line / doubled edge. Full-opacity (1.0) sections are untouched here - they keep their crisp edge for the downstream grow/blur to handle. 0 = off.
partial_contract_percentoptFLOAT0.00–25Contract (erode inward) the mask of partial-opacity sections BEFORE feathering, so the soft edge sits INSIDE the region instead of bleeding outward past its true border (which shows as a faint ring/edge on the surrounding skin). Set it near partial_feather_percent to pull the feathered ramp back to the real edge. Only affects partial (<1.0 opacity) sections. 0 = off.

Outputs (3)

NameTypeDescription
maskMASK
infoSTRING
color_previewIMAGE