Nodes/ComfyUI-DAELab-Custom-Nodes-Library/Badge Semantic Region Merge V1 (DAELab)
ComfyUI Node

Badge Semantic Region Merge V1 (DAELab)

Four edits, one image, later slots win

By TeutonicMepheles·Created 4 months ago·Updated 3 days ago· 0
Badge Semantic Region Merge V1 (DAELab)
  • base_image
  • region_1_image
  • region_1_mask
  • region_2_image
  • region_2_mask
  • region_3_image
  • region_3_mask
  • region_4_image
  • region_4_mask
  • image
  • report
◄region_1_status—►
◄region_2_status—►
◄region_3_status—►
◄region_4_status—►

Four channels of local GPT Image 2 edits is a nice idea right up to the moment you have to put them back together. Each channel saw the same base image, each one changed a different region, and half of them might not have run at all because their masks were empty or their switch was off. Badge Semantic Region Merge V1 is the deterministic glue: base image plus four (image, mask, status) triples in, one composited image and one report out.

The maths, which is deliberately dull

Start with base_image. For each slot in order 1→4, blend with that slot's mask: result = result * (1 - mask) + channel_image * mask. No feathering, no gradient, no alpha compositing - hard masks, thresholded at 0.5, straight replacement.

Order matters and the node says so in its own description: later slots win on overlap. If slot 2 and slot 4 both claim a pixel, the pixel comes from slot 4. That's a simple, predictable precedence rule, and it means you order your channels by priority when you wire them: the thing you care least about goes first.

Three numbers go into the report, and they're the whole reason to use this instead of four chained "image composite masked" nodes:

  • gpt_node_use_count - how many of the four channels actually expanded a paid GPT node. Summed from each channel's own status JSON. This is your spend for this stage, in one integer.
  • overlap_pixels - how many pixels more than one channel touched, i.e. how much of your result depended on the slot ordering. Zero is a tidy workflow; a large number means your masks are fighting.
  • outside_max_abs_diff - the maximum absolute difference between the output and the base outside every mask. It should be exactly 0.0. If it isn't, something upstream is not honouring its mask and you should stop before you compound the problem.

The full per-channel statuses are nested in the report too, so a failing channel is identifiable by slot and region ID rather than by vibes.

All eight inputs are required

That's the part that trips people up. There's no "optional" second channel - the schema demands four images, four masks and four status strings, always. So what do you do when you only have two edits?

You wire all four channels and leave the unused ones disabled. A disabled channel returns its base image unchanged, a zero mask and a status saying no_active_region_for_slot. Merging a zero mask contributes nothing and doesn't cost a credit. This is the intended usage, not a workaround: the tools are built as a fixed four-lane bus, and the enabled boolean on each channel is how you populate it.

The region_N_status inputs are forceInput strings - they must come from the channel's call_status output, not from a text node you typed into. The merge node parses them as JSON and reports status_parse_error if you hand it something else.

Where it sits

Channel 1..4 → Merge → your next deterministic stage. In the pack's studio branch that next stage is the colour-lock node; in a height branch it's the structure constraint. Then a final visual check.

Treat the merge's image as your master from here on. Re-running the merge alone is free; re-running the channels isn't. If you're tuning the downstream composite, disconnect the channels (or bypass them) so ComfyUI's cache doesn't decide to re-execute a paid node you didn't mean to re-roll. reroll_revision on each channel is the only thing that's supposed to force that.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/TeutonicMepheles/ComfyUI-DAELab-Custom-Nodes-Library.git

Restart and refresh. The node is registered as DAELAB.BadgeSemanticRegionMergeV1 under DAELab/Badge/PP. Clone the whole repository - the root __init__.py registers every node and the shared web/ folder serves the front-end panels; a lone nodes/ subfolder won't import.

ComfyUI Manager users: search the pack title "ComfyUI-DAELab-Custom-Nodes-Library", then restart for good measure. Node ID stability is an explicit promise of this pack, so existing workflows keep working across updates.

Troubleshooting

Dimension mismatches are errors, not auto-resizes: every channel image and mask must match the base canvas exactly. If you have a 1024 base and a 768 channel result, that's a workflow bug - usually a channel pointed at an un-normalised image - and the node will refuse rather than silently scuff the geometry.

If gpt_node_use_count is lower than you expected, the missing channel told you why in its reason field. disabled, empty_or_too_small_mask, or no_active_region_for_slot are all cheap outcomes; the expensive mistake is assuming a channel ran when it didn't and building the rest of your workflow on a region that was never repainted.

Finally, this is where the pack's fixed four-channel budget lives. If you need five region edits, that's two merge nodes and a composite, not a bigger graph - and before you go there, ask whether five separate GPT edits is the right tool versus one region plus a deterministic material pass.

CategoryDAELab/Badge/PP

Inputs (13)

NameTypeDefaultDescription
base_imageIMAGE—
region_1_imageIMAGE—
region_1_maskMASK—
region_1_statusSTRING—
region_2_imageIMAGE—
region_2_maskMASK—
region_2_statusSTRING—
region_3_imageIMAGE—
region_3_maskMASK—
region_3_statusSTRING—
region_4_imageIMAGE—
region_4_maskMASK—
region_4_statusSTRING—

Outputs (2)

NameTypeDescription
imageIMAGE—
reportSTRING—