Mask Separate
Cut a messy mask into its individual objects — this is the one you'll keep
- mask
- mask
- count
You have a mask that covers five objects at once and you want five masks, one per object. That's the whole job, and Mask Separate does it well - it's probably the most genuinely useful node in the whole 1hewNodes mask group. Think of it as "connected components, but tuned for the way we actually cut people and props out."
What it's for
Every time a background-removal or segmentation step hands you one big mask covering several separate subjects, you need this split before you can do per-subject work: individual inpaint passes, per-object upscaling, pasting each region onto its own canvas. It also plays directly with the pack's other glue nodes - separate each object, process them in a list, then Mask List to Batch stacks them back for anything that wants a batch.
How it works
The mechanism is a classic computer-vision pipeline wearing a friendly face. The mask is thresholded to a binary (values above threshold become "inside"), then scikit-image's label finds connected regions using your chosen connectivity (8-neighbor is the default and almost always what you want; 4-neighbor splits diagonally-touching blobs). Each region is filtered by min_area, sorted per sort_mode, and copied out as its own mask.
Nice detail: each output region keeps the original soft mask values, not a hard binary. So feathering and semi-transparent edges survive the split instead of becoming jagged cutouts. The outputs are a batch of region masks plus an INT count, so you can wire the count into a loop or a counter without a separate node.
The inputs that matter
- threshold (
FLOAT, default 0.5) - the cut line between inside and outside. Lower it if your mask is faint and regions are dropping out. - min_area (
INT, default 1) - kills specks smaller than this in pixels. The #1 tool for deleting noise-regions. - sort_mode -
top_to_bottom(default),left_to_right, orarea_desc(biggest first). For multi-row layouts the node groups by row, so reading order stays sane. - connectivity -
8or4, as above. Rarely touch it.
Outputs: mask (one per region, batched) and count (INT).
Installing it
ComfyUI Manager → search ComfyUI-1hewNodes → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/1hew/ComfyUI-1hewNodes
Restart ComfyUI. No model files needed - this runs on numpy + scikit-image, both in the pack's requirements (along with heavier things like rembg and ultralytics that install anyway). Pack is built on ComfyUI's newer comfy_api.latest API, so if nothing registers, update ComfyUI.
Common issues
If you're getting way more regions than you expect, your mask has anti-aliased noise and min_area is doing no work - bump it. If two objects that touch get merged into one region, that's 8-connectivity doing its job; either lower the threshold or accept that touching objects are one blob. And the familiar empty case: no region clears the area filter, and you get a zero-frame mask plus count = 0, which is exactly the signal you want for an "if anything was found" branch.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| threshold | FLOAT | 0.500–1 | — |
| min_area | INT | 11–100000000 | — |
| sort_mode | COMBO | top_to_bottom | 3 options: top_to_bottom, left_to_right, area_desc |
| connectivity | COMBO | 8 | 2 options: 8, 4 |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |
| count | INT | — |