Mask Merger
Merge a whole mask batch into one mask — no chained composite nodes
- mask_batch
- merged_mask
You've got twelve masks and you need one. That's the whole job, and this node does it in a single click.
Every serious ComfyUI workflow ends up in this situation sooner or later. You run SAM or GroundingDINO over an image and it hands you a batch of masks - one per detected object, all stacked in a single MASK tensor of shape [B, H, W]. Or you're working on video and every frame contributes its own silhouette mask, and what you actually want is the whole motion path painted on one canvas (there's a whole r/comfyui thread about exactly that - someone stitching 24 frame masks into a single "flow mask" for a runner). Or you've got several regions you want to inpaint at once. Either way, downstream nodes almost always want one mask, not twelve.
Mask Merger (MaskBatchMergeAdd) is the smallest possible answer: one input, one output, zero settings. It takes a whole mask batch and adds every mask together into a single merged mask.
How it works
The source is about twenty lines, and the entire mechanism is two lines of PyTorch:
merged = torch.sum(mask_batch, dim=0, keepdim=True)
merged = torch.clamp(merged, 0.0, 1.0)
That's it. Sum the batch along the batch dimension, then clamp so nothing exceeds 1.0. Because ComfyUI masks live in the 0–1 range, adding them gives you 2 (or more) wherever masks overlap - the clamp is what keeps the result from blowing out to a white blob where your masks touched. So this is a union operation, not a blend: every pixel that any mask covered ends up as 1.0, everything else stays 0.0. The README calls it "Add Mode," and that's exactly what it is - there's no subtract, no intersect, no feather-aware mode. If you needed intersection you'd build it another way.
Where people get caught: if your masks have different resolutions, torch.sum will throw a shape-mismatch error - it can't add a 512×512 mask to a 768×768 one. Any node producing the batch (SAM, GroundingDINO, the segmentation packs) will usually keep them consistent, but if you've resized one mask somewhere in the chain before it hits this node, that's your first suspect. Also, soft feathered masks that overlap will get their overlap hard-clamped to 1.0 - fine for binary masks, slightly lossy for heavily feathered ones.
The inputs and outputs that matter
There's only one of each, which makes this the friendliest possible first custom node.
mask_batch(MASK, required) - the batch of masks you want merged. Feed it the output of any segmentation/masking node.merged_mask(MASK) - a single[1, H, W]mask, ready to wire into an inpainting setup, a ControlNet mask input,ImageCompositeMasked, a detailer, or anything else that wants one mask instead of a stack.
You can't misconfigure it because there's nothing to configure. If you feed it a single mask instead of a batch, it still works - summing a batch of one is a no-op, so it passes straight through harmlessly.
Install
Install via ComfyUI Manager by searching for ComfyUI Mask Batch Merger, or from the command line:
cd ComfyUI/custom_nodes
git clone https://github.com/mmmmmmmmme/ComfyUI_MaskBatchMerger
Then restart ComfyUI. Good news on dependencies: the README and requirements.txt say no extra dependencies - the pillow/numpy/torch lines are just ComfyUI's own stack, so there's nothing to download and nothing heavy to trip over. You'll find the node under the mmmmmmmmm category, or by searching "Mask Merger."
Should you reach for it?
It's not a flashy node - it has zero social footprint, zero impressions, and the author ships a YouTube walkthrough rather than docs. But that's fine, because the honest truth is you don't need hand-holding for a node this small. The alternative is chaining MaskComposite after MaskComposite for every mask in your batch, which is fiddly and breaks the moment the batch size changes. This does the whole batch in one step regardless of how many masks arrive, which is the "self-adaptable towards any mask batch size" the README brags about. For merging detected objects into a single inpaint region, or collapsing a video's frame masks into one motion path, it's the one I'd reach for.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| mask_batch | MASK | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| merged_mask | MASK | — |