Nodes/ComfyUI-MaskBatchPermutations/Combinatorial Detailer
ComfyUI Node

Combinatorial Detailer

When the detailer ruins a face, make it try every fix at once

By curiousjp·Created 2 years ago·Updated 2 years ago· 5
Combinatorial Detailer
  • masks
  • base_image
  • candidates
  • IMAGE

The author of this pack put it better than I can, and it's the entire pitch: "Automatic face detailing without direct operator intervention usually works well, but occasionally it wrecks an otherwise good face. Instead of having to hand compose them back together in something like GIMP and fix the metadata, I decided to create this instead."

That "this" is Combinatorial Detailer, the flagship node of the curiousjp/ComfyUI-MaskBatchPermutations pack. Where the pack's sibling Permute Mask Batch gives you every combination of masks, this node gives you every combination of images: given a base image, a set of mask regions, and a batch of candidate images (say, the output of two detailer passes with deliberately different prompts or seeds), it renders every possible way of filling those regions. Three regions and two candidates produces (2+1)³ = 27 output images. Every single one, in one run.

How it works

Under the hood it's base-(candidates+1) counting. Each output image is a combination where every mask region is in one of n+1 states: it either keeps the base image (state 0) or shows one of the candidates. The code walks the whole space, and for each mask it does a hard torch.where swap - where the mask equals 1, the candidate's pixels replace the base's. Output 0 is always the untouched base image, so your "do nothing" control is right there at the start of the batch.

Inputs and outputs

  • masks (MASK) - the regions, typically straight out of Impact Pack's SEGS to Mask Batch node.
  • base_image (IMAGE) - the image everything starts from, i.e. the one you'd hand-compose in GIMP.
  • candidates (IMAGE) - a batch of candidate images, one per alternative detail pass.
  • IMAGE output - a batch of (candidates+1)ᵐᵃˢᵏˢ images, ready to feed a preview node.

The README's example workflow runs two DetailerForEach passes with deliberately divergent prompts - that's the trick for actually seeing what changed - and concatenates their outputs with ImageBatch before this node.

The two traps that actually catch people

The batch size is a cliff, not a slope. (c+1)ⁿ explodes fast: 4 masks × 3 candidates is 256 full-resolution images, all materialized in memory at once (the node isn't lazy, it builds the whole tensor up front). It's genuinely great for 2–3 regions; it's a footgun past that. Watch your RAM.

This node assumes binary masks and matching sizes. The swap is torch.where(mask == 1, ...) - a hard cut, not a feathered blend. Soft, gradient-edged masks won't do what you expect; you want hard 0/1 masks from SEGS. And every candidate plus the base has to be the same width/height, because the replacement happens in-place on a tensor of one fixed shape. Candidates that come out of detailers at different resolutions will error or silently misbehave - upscale them to the base before batching.

Installing it

Search ComfyUI-MaskBatchPermutations in ComfyUI Manager, or:

cd ComfyUI/custom_nodes
git clone https://github.com/curiousjp/ComfyUI-MaskBatchPermutations

then restart. There's no requirements.txt and no model download - the whole pack is one MIT-licensed file that only imports torch. One of the painless installs in an ecosystem famous for dependency hell.

When to reach for it

Whenever you catch yourself thinking "I'll just rerun the detailer with a different seed and compare." That's the workflow this node replaces - it's the compare grid you'd otherwise assemble by hand. If you're happy with a single FaceDetailer run, you don't need it. The moment you're agonizing over which detail pass to keep, you do.

Categoryimage

Inputs (3)

NameTypeDefaultDescription
masksMASK
base_imageIMAGE
candidatesIMAGE

Outputs (1)

NameTypeDescription
IMAGEIMAGE