Nodes/ComfyUI-MoonNodes/πŸŒ— Moon SEGS to Indexed Mask List
ComfyUI Node

πŸŒ— Moon SEGS to Indexed Mask List

From 'detected character' to 'region 2's mask' in one node

By m0rtus59Β·Created 4 months agoΒ·Updated 17 days agoΒ· 7
πŸŒ— Moon SEGS to Indexed Mask List
  • segs_or_masks
  • base_masks
  • MASK
β—„fallback_to_basefalseβ–Ί

Regional prompting needs one mask per region, in a fixed order, and the mask at index N has to line up with the prompt for region N. Detectors don't care about your indexing - they hand you whatever they found, in whatever order they found it. Moon SEGS to Indexed Mask List is the adapter that sits between the two: it takes detection output (or raw masks) and turns it into the indexed mask list the Moon regional chain expects.

What it eats

The single required input segs_or_masks accepts either:

  • SEGS - the format from the ComfyUI Impact Pack ecosystem: the (height, width), [SEG objects] tuple that comes out of detectors like FaceDetailer, BBOX detectors or SAM. Each SEG carries a cropped_mask plus its crop_region, and the node pastes each crop back into a full-canvas binary mask at the right position.
  • MASK batch/list - what SAM or Florence-2 style nodes produce. Each frame in the batch becomes one indexed mask, in order.

Either way, masks are thresholded at 0.5, so you get clean binary regions rather than soft alpha.

What it does with them

There are two modes, and the difference is the whole point.

Standalone (no base_masks): you just get the detected masks back, one per index. Simple, and honestly most of what a beginner needs - detector out, patcher in.

Indexed Matcher (connect base_masks): this is the mode that justifies the node's name. You give it a reference layout - typically the region masks you already drew with Moon Mask Maker, where region 0 is "left character" and region 1 is "right character." Every detection is scored against each reference region by overlap, then assigned to the one it covers most. The output has exactly as many masks as your reference layout, so index N always corresponds to region N's prompt, no matter what order the detector returned things in. If a region got no detection, fallback_to_base (default off) substitutes the reference mask for that slot so your regional chain never sees a hole.

Output is a single MASK list - the tooltips note it can carry either SEGS or MASK in, and it always emits MASK out.

Where it fits

The natural workflow: Moon Mask Maker defines your composition, Moon SEGS to Indexed Masks takes a character detection pass (Impact Pack's Ultralytics detector, or SAM) and snaps the detections into that layout, and the result feeds straight into Moon Anima Regional Patcher - or the SDXL regional sampler the same pack ships. You get "prompt for the left region applies to whoever was detected on the left," automatically.

Install and gotchas

cd ComfyUI/custom_nodes
git clone https://github.com/m0rtus59/ComfyUI-MoonNodes.git
cd ComfyUI-MoonNodes
pip install -r requirements.txt

Then restart ComfyUI, or grab "ComfyUI-MoonNodes" from ComfyUI Manager. The pack's only pinned dependency is google-genai, imported at load time by the Gemini nodes - so install it even though you're not using Gemini, or the whole pack won't load.

A couple of honest warnings. If you're feeding it SEGS from a YOLO/Ultralytics detector, remember that since Impact Pack v8.0 the Ultralytics provider lives in the separately-installed Impact Subpack - install that too or the detector won't be there to produce SEGS. And this is a small, AI-assisted, one-author pack; the code works and is tested, but don't expect the polish of Impact Pack itself. The Indexed Matcher assigns detections greedily by overlap, so two characters who heavily overlap can still get merged onto one region - that's a limitation of the approach, not a bug to chase.

CategoryMoonNodes

Inputs (3)

NameTypeDefaultDescription
segs_or_masksSEGS,MASKMandatory: Accepts either SEGS (Ultralytics/Impact) or MASK batch/list (SAM/Florence-2).
base_masksoptMASKOptional: Reference layout mask list to index-match against.
fallback_to_baseoptBOOLEANfalseIf True and base_masks provided, use base mask if no detection exists for a region index.

Outputs (1)

NameTypeDescription
MASKMASKβ€”