Nodes/ComfyUI-MultiMaskOps/Mask Deduplicate
ComfyUI Node

Mask Deduplicate

When your segmenter hands you the same subject twice (or three times)

By INuBq8·Created 2 months ago·Updated 2 months ago· 0
Mask Deduplicate
  • masks
  • masks
  • removed_count
  • group_images
iou_threshold0.90
keep
threshold0.50

Run a SAM-style segmenter at multiple thresholds or boxes and you'll get duplicates: the same subject detected two or three times with slightly different masks. That's not a bug in your workflow, it's how the tools work - and it becomes a real problem the moment you feed those masks onward, because "expand five copies of the same person" is not the operation you wanted. Mask Deduplicate finds the repeats and collapses them, so each subject survives once.

How it works

The interesting part is transitive IoU grouping. The node computes pairwise Intersection-over-Union between every pair of masks; any pair above iou_threshold counts as duplicates. Then grouping is transitive: if A overlaps B and B overlaps C (each above the threshold), all three merge into one group - even if A and C never directly overlap enough. The math is union-find connected components, and it means you get one group per subject, not per directly-overlapping pair. That transitivity is the difference between this node and a naive "drop anything within X overlap of something kept" approach, which can split one subject into competing survivors.

Each group is then collapsed to a single mask using the keep mode:

  • largest, smallest, first - keep one existing mask from the group.
  • OR - union of the group (soft max), useful when each detection has a piece the others miss.
  • AND - intersection (soft min), useful when you want only the pixels every detection agrees on.

Inputs that matter

  • masks - a list of masks (run Mask Batch To List first if you have a batch).
  • iou_threshold - default 0.9, which is strict: only near-identical masks merge. If your duplicates are looser (same subject, different box sizes), drop toward 0.7–0.8 and retest. Too low and it starts merging genuinely different subjects that happen to touch.
  • keep - how to collapse each group. largest is the usual default; first preserves original ordering, which matters if you're chaining into Mask Sort By Position.
  • threshold - the binarization cutoff for computing IoU and mask areas (pixels ≥ threshold count as "on"). It does not alter AND/OR output values - soft masks stay soft.

Outputs

Three outputs, and the two extras are more useful than they look:

  • masks - one mask per group, deduplicated.
  • removed_count - an integer telling you how many masks got removed. Wire it to a text display; if it reads 0 when you expected duplicates, your threshold is too strict.
  • group_images - a debug image per duplicate group, each mask drawn in a distinct color with overlaps blended so overlapping regions read as a mixed color. Only groups with 2+ members appear.

The gotcha

When nothing was duplicated, group_images emits a single blank white image instead of an empty list. That's intentional - some downstream nodes dislike empty list outputs - but the first time you see a white image on the debug output you'll think something broke. It didn't; that's the "no duplicates found" signal.

Two empty masks count as identical (their IoU is treated as 1.0), so if your segmenter emits blank masks, deduplication will happily merge all of them into one. Drop empties upstream if that matters.

Installation

The pack-wide install, nothing special:

cd ComfyUI/custom_nodes
git clone https://github.com/INuBq8/ComfyUI-MultiMaskOps

Restart, find the nodes under MultiMaskOps. No model downloads; requirements.txt is empty (torch/scipy/torchvision ship with ComfyUI). Manager search "MultiMaskOps" is the easier path once its listing is live.

This is the node you add when your multi-subject workflow starts acting like the same person keeps showing up in the output - because that's literally what happened to your masks.

CategoryMultiMaskOps

Inputs (4)

NameTypeDefaultDescription
masksMASKA list of masks to deduplicate.
iou_thresholdFLOAT0.900–1Minimum Intersection-over-Union for two masks to count as duplicates. Grouping is transitive: if A~B and B~C, all three merge. Higher = stricter (only near-identical masks merge).
keepCOMBOHow to collapse each duplicate group. largest/smallest/first pick one existing mask; OR = union of the group (max); AND = intersection of the group (min).
thresholdFLOAT0.500–1Binarization cutoff for computing IoU and mask areas. Pixels >= threshold count as 'on'. Does not affect AND/OR output values.

Outputs (3)

NameTypeDescription
masksMASKThe deduplicated masks, one per duplicate group.
removed_countINTHow many masks were removed as duplicates.
group_imagesIMAGEOne image per duplicate group, each mask in a distinct color (overlaps blend). Only groups with 2+ members are shown.