ComfyUI Node

Region Split

Turn a detector's masks into regions you can actually use

By Nynxz·Created 11 months ago·Updated about 12 hours ago· 4
Region Split
  • masks
  • bboxes
  • image
  • masks
  • fusion_layout
  • subject_masks
  • count
◄directionauto►
◄shapestrip►
◄padding0.50►
◄max_regions0►
◄min_size0.002►
◄snap16►
◄gap0►

A face detection mask is a terrible mask for a regional LoRA. It covers a face and nothing else, so the body below it belongs to no region at all - and if you've wired two of them, you've also got a ragged gap between them and possibly an overlap. Regional LoRAs want something a segmenter doesn't produce: the frame divided between the subjects, every pixel owned by exactly one of them.

Region Split is the conversion. It finds each subject's box - from a per-object mask batch, from the separate blobs of a union mask, or straight from SAM3's bounding boxes - orders them along the frame, and puts each boundary halfway between one subject's far edge and the next one's near edge. The middle of the gap when they're apart, the middle of the overlap when they touch. What comes out is one clean strip per subject.

The inputs

direction (auto, columns, rows) - auto picks the axis the subjects are spread out along more, which is right most of the time. shape picks strip (full height of the frame, so a subject owns the body below its face) or box (the strip cut down to the subject's own extent plus padding). strip is the default and it's the one regional LoRAs want.

padding (0.5, 0 to 4) only applies to box shape, and it's expressed as a fraction of the subject's own size - a face at 0.5 reaches roughly the shoulders.

max_regions (0 = all) keeps only the largest N subjects, which is the answer to "the detector also found the background faces in a poster". min_size (0.002) drops detections smaller than that fraction of the frame, which handles specks. snap (16) rounds each boundary to a multiple of that many pixels so it lands on the latent grid instead of slicing a latent cell in half - leave it alone unless you know better. gap leaves unclaimed pixels between neighbours.

Optional: masks (a batch, one per subject, or one mask whose blobs are the subjects), bboxes (SAM3's bounding boxes, used when no masks are wired - and it needs image for the frame size), and image (which sets the frame; unwired, the masks' size is used).

The outputs

masks is the regions, numbered the way Region LoRAs numbers them - left to right, or top to bottom. fusion_layout hands the same regions over as boxes for Fusion Regions or Region Sketch, which is the bridge into the rest of the group. subject_masks gives you the detections back in the same order, for anything that wants the actual face rather than its strip - detailers, mostly. count tells you how many subjects it found, which is worth wiring to a text node the first few times you run a new detector prompt.

high-noise pass ──> image ──> SAM3 Detect ──> masks ──> Region Split ──> masks ──> Regions from Masks

The two-pass shape is the point: generate at high denoise to get a composition, have a detector find the people in it, split the frame between them, then run the second pass with a proper region per subject. That's the workflow this node was written for.

Install

Manager → search Nynxz → ComfyUI-NynxzNodes, or:

comfy node install comfyui-nynxz-nodes

From source:

cd ComfyUI/custom_nodes
git clone https://github.com/Nynxz/ComfyUI-NynxzNodes
cd ComfyUI-NynxzNodes
pnpm install && pnpm build

Restart. No models - it consumes whatever your detector produced. It does import scipy.ndimage, and so do a couple of nodes in this pack; ComfyUI normally ships scipy, but if the pack fails to import on a minimal container, pip install scipy in the ComfyUI environment is the fix.

Troubleshooting

Regions are in the wrong order. They're ordered along the chosen axis, so direction = auto on subjects spread diagonally can pick the axis you didn't expect. Force columns or rows and check with Region Overlay.

One region, count = 1. Your masks came in as a single blob (union mask where the subjects touch), or max_regions is 1, or min_size filtered everything else out. A union mask only splits into blobs if there's actual empty space between the subjects.

Boundaries cut through a subject. That's the halfway rule doing its job on overlapping boxes - mid-overlap. shape = box with some padding cuts a tighter region instead of a full strip.

Regions look slightly misaligned with the model's grid. Raise snap to 32 or 64, or check your width/height match the output's aspect.

CategoryNynxz/Regions

Inputs (10)

NameTypeDefaultDescription
directionCOMBOautocolumns = split left to right; rows = top to bottom; auto = along whichever way the subjects are spread out more.
shapeCOMBOstripstrip = the full height (or width) of the frame, so a subject owns the body below its face too; box = the strip cut down to the subject's own extent plus `padding`.
paddingFLOAT0.500–4For shape = box: grow the subject's extent along the strip by this fraction of its size (a face at 0.5 reaches the shoulders).
max_regionsINT00–64Keep only this many subjects, the largest. 0 = all of them. Use it when the detector also picks up background faces.
min_sizeFLOAT0.0020–0.5Ignore detections smaller than this fraction of the frame — specks and stray blobs.
snapINT161–128Round each boundary to this many pixels, so it lands on the latent grid instead of splitting a latent cell.
gapINT00–512Pixels left unclaimed between neighbouring regions.
masksoptMASKThe subjects: a batch with one mask per subject (SAM3 Detect with individual_masks), or one mask whose separate blobs are the subjects.
bboxesoptBOUNDING_BOX[object Object]SAM3 Detect's bboxes, used when no masks are wired. Needs `image` for the frame size.
imageoptIMAGESets the frame size. Unwired = the masks' size.

Outputs (4)

NameTypeDescription
masksMASK—
fusion_layoutNYNXZ_FUSION_LAYOUTThe regions as boxes, for Fusion Regions' or Region Sketch's `layout`.
subject_masksMASKThe detections themselves, in the same order as the regions.
countINT—