BiSeNet Mask
Pick exactly which face parts survive into your mask
- crop
- MASK
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/.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| crop | IMAGE | — | |
| skin | BOOLEAN | true | — |
| left_brow | BOOLEAN | true | — |
| right_brow | BOOLEAN | true | — |
| left_eye | BOOLEAN | true | — |
| right_eye | BOOLEAN | true | — |
| eyeglasses | BOOLEAN | true | — |
| left_ear | BOOLEAN | true | — |
| right_ear | BOOLEAN | true | — |
| earring | BOOLEAN | true | — |
| nose | BOOLEAN | true | — |
| mouth | BOOLEAN | true | — |
| upper_lip | BOOLEAN | true | — |
| lower_lip | BOOLEAN | true | — |
| neck | BOOLEAN | false | — |
| necklace | BOOLEAN | false | — |
| cloth | BOOLEAN | false | — |
| hair | BOOLEAN | false | — |
| hat | BOOLEAN | false | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MASK | MASK | — |