Nodes/ComfyUI-Utility-Suite/Combine Masks (SEGS & MASK)
ComfyUI Node

Combine Masks (SEGS & MASK)

Composite a Mask Into Every SEG Without Rebuilding the Boxes

By tom-m-2020·Created about a month ago·Updated 7 days ago· 1
Combine Masks (SEGS & MASK)
  • segs
  • masks
  • segs
◄x0►
◄y0►
◄operation▾►

Once you understand SEGS, the detail loop stops being mysterious. A SEGS value is a two-part structure: the source canvas size, and a list of segment entries - each with its own crop rectangle, its cropped image, its confidence, a label, and crucially a cropped_mask. Every detailer, DetailerForEach, SEGSPaste and SEGS filter in the ecosystem reads that cropped_mask as the answer to "where am I allowed to work inside this box". So the moment you want to change where work happens, you want to edit masks inside SEGS - and that is a fiddly structure to rebuild by hand.

This node does one specific edit: take a MASK and composite it into every segment's cropped mask.

How it works

For each segment it pulls out the cropped mask (the destination), pulls the corresponding mask from your masks input (the source), stamps the source into the destination at offset x, y, applies one of six operations, clamps the result to 0-1, and puts the new array back into the entry with cropped_mask replaced. Everything else about the segment - its crop region, its bbox, its confidence, its cropped image - is passed through untouched.

Two details from the source that matter in practice:

  • x and y are crop-local, not canvas coordinates. The destination really is the segment's cropped mask, so (0,0) is the top-left corner of that segment's box, not of the image. A 200x200 crop with a 50x50 mask and x=75, y=75 centres it. This is the single most surprising thing about the node, and it is worth knowing before you conclude the placement is broken.
  • Sources pair with segments by index, and the last one repeats. Give it one mask and every segment gets that mask. Give it a batch and entry 0 gets mask 0, entry 1 gets mask 1, and so on; if you run out of masks, the final one is reused for the remainder. Nothing resizes: a source larger than the destination is clipped at the destination edge.

operation is one of multiply, add, subtract, and, or, xor. The first three are arithmetic on continuous 0-1 values, clamped afterwards; the last three round each side to boolean first, so they binarise anything soft you feed them. Everything is clipped at the destination boundary, so a stamp that runs off the crop is silently truncated.

What you use it for

The classic case is refining a box into a shape. A YOLO detector gives you a rectangle per face; you run SAM over the same region to get a polygon; then you multiply the SAM mask into the SEGS so the detail pass follows the face outline instead of the rectangle - which is the seam fix everyone eventually reaches for once they notice the visible patch edges.

The other direction is subtraction. If two detectors both found a person and one also found their hands, stamp subtract on the hand masks and the person pass stops covering the hands, so your hand detailer is not fighting a face detailer for the same pixels. Union works the same way with add or or, and it is how you merge two detector passes before a single detail run.

Install

Part of ComfyUI-Utility-Suite: ComfyUI Manager → search ComfyUI-Utility-Suite → install → restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/tom-m-2020/ComfyUI-Utility-Suite

Restart ComfyUI. It needs Impact Pack in your workflow for the SEGS to come from somewhere, but nothing from Impact is vendored - SEGS is just a structure the pack understands. No models, no downloads; the declared dependency is opencv-python-headless. The pack is written against ComfyUI's V3 node API, so keep the backend reasonably current.

Traps

SEGS comes in as one value, masks come in as a list. The node is declared with list inputs, and it deliberately takes the first SEGS it sees while consuming the whole mask container. If you hand it a list of SEGS, you get the first one processed and the rest ignored - silently.

Mask/source mismatch is silent by design. There is no "wrong number of masks" error, because repeating the last one is the intended behaviour. If half your faces got the wrong treatment, count your masks.

Structure validation is strict in one place. Every entry must have a crop region that sits inside the declared canvas, and the cropped mask must match the crop extent exactly, or you get a type error naming the offending entry index. That is a feature - it catches a malformed detector output before it propagates into a detail pass - but it does mean third-party nodes that build SEGS by hand sometimes get rejected here.

CategoryUtility Suite/SEGS

Inputs (5)

NameTypeDefaultDescription
segsSEGS—
masksMASK—
xINT00–16384—
yINT00–16384—
operationCOMBO6 options: multiply, add, subtract, and, or, xor

Outputs (1)

NameTypeDescription
segsSEGS—