ComfyUI Node

BiSeNet Mask

Pick exactly which face parts survive into your mask

By dchatel·Created 2 years ago·Updated 11 months ago· 183
BiSeNet Mask
  • crop
  • MASK
skintrue
left_browtrue
right_browtrue
left_eyetrue
right_eyetrue
eyeglassestrue
left_eartrue
right_eartrue
earringtrue
nosetrue
mouthtrue
upper_liptrue
lower_liptrue
neckfalse
necklacefalse
clothfalse
hairfalse
hatfalse

Most face masks are dumb. A bounding box or a convex hull tells you where the head is; it doesn't tell you which pixels are lips and which are glasses. BiSeNet Mask is the node that answers that question, by running a real face-parsing segmentation model over a face crop and letting you switch individual facial parts on and off in the mask. Want to inpaint only the mouth while leaving the eyes and skin frozen? This is the node that lets you do that, instead of fighting a solid blob mask.

It's part of the facetools pack's mask family (alongside JonathandinuMask), and it exists because the pack's CropFaces node offers BiSeNet as a mask_type - this node is the same segmentation engine exposed directly, so you can build or refine masks without going through the full detect-crop-warp pipeline.

The inputs, which are the whole show

Just two kinds: a crop image and nineteen booleans, one per facial region the model can segment. The defaults leave the actual face on (skin, brows, eyes, glasses, ears, earring, nose, mouth, lips) and leave the periphery off (neck, necklace, cloth, hair, hat all default to false). Toggle a part off and its pixels fall out of the final mask. That's the entire workflow of the node: the mask is the union of every region you leave switched on.

The underlying model is BiSeNet from the face-parsing.PyTorch project, a 19-class face segmentation network. The source shows each toggle mapping straight to a class id, then the output mask is built by OR-ing together every enabled class. Occlusion-aware in the literal sense: it segments actual pixels, so a hand over part of the face doesn't wreck the whole mask.

What it needs

Two setup items, both easy to miss:

# 1. The BiSeNet weights (79999_iter.pth) → ComfyUI/models/bisenet/
#    (Google Drive link in the pack README)
# 2. A CUDA GPU - the node hardcodes .cuda() in the source

That last one is the real gotcha. This node will not run on CPU; the segmentation tensors are moved to CUDA unconditionally. If you're on a Mac or a CPU-only box, BiSeNet Mask is a dead end and JonathandinuMask is the fallback (it picks a device more gracefully, though it's heavier).

When to use it

Targeted fixes. The killer case is inpainting one feature - "fix this character's mouth" - where you want the mask tight to the lips and nowhere else, so the inpaint model doesn't get to redraw the nose and skin around it. It's also how you keep a character's identity intact: freeze everything except the region you actually want regenerated. That's the exact property the wider face-detailing conversation keeps circling - the less you let the model touch, the more the resemblance survives.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/dchatel/comfyui_facetools

or ComfyUI Manager → search facetools → restart. The node itself adds nothing beyond the pack's shared dependencies (torch, and a BiSeNet module that ships inside the repo), so the only real requirement beyond install is dropping 79999_iter.pth into ComfyUI/models/bisenet/.

Categoryfacetools

Inputs (19)

NameTypeDefaultDescription
cropIMAGE
skinBOOLEANtrue
left_browBOOLEANtrue
right_browBOOLEANtrue
left_eyeBOOLEANtrue
right_eyeBOOLEANtrue
eyeglassesBOOLEANtrue
left_earBOOLEANtrue
right_earBOOLEANtrue
earringBOOLEANtrue
noseBOOLEANtrue
mouthBOOLEANtrue
upper_lipBOOLEANtrue
lower_lipBOOLEANtrue
neckBOOLEANfalse
necklaceBOOLEANfalse
clothBOOLEANfalse
hairBOOLEANfalse
hatBOOLEANfalse

Outputs (1)

NameTypeDescription
MASKMASK