Nodes/DOGMA Nodes/DOGMA MaskOwnershipBounded v2
ComfyUI Node

DOGMA MaskOwnershipBounded v2

Stop two categories from owning the same pixels

By axior·Created 6 months ago·Updated 16 days ago· 2
DOGMA MaskOwnershipBounded v2
  • mask_1
  • mask_2
  • mask_3
  • mask_4
  • mask_5
  • mask_1
  • mask_2
  • mask_3
  • mask_4
  • mask_5
  • ownership_report
◄category_1—►
◄category_2—►
◄category_3—►
◄category_4—►
◄category_5—►

The problem, which is not obvious until you render

Run five categories of masks over one photo and they will overlap. The person's legs sit inside the "pavement" mask. The car sits inside the "road" mask. The building's windows sit inside the "sky" mask. Individually each mask is defensible - the surface is pavement, and the legs are on it - but if you then render each category with its own prompt and paste the results back, the same pixels get painted twice, and you get double-denoised mush exactly where objects meet their backgrounds.

DOGMAMaskOwnershipBoundedV2 resolves that. Five mask/category pairs in, five masks out, each pixel belonging to at most one category.

How the resolution works

Category names are canonicalised first (the pack folds synonyms - people/person, car/vehicle, road/street), and then a fixed priority decides who wins:

  1. people
  2. vehicles
  3. anything else (unrecognised categories)
  4. structural targets (buildings, house, cathedral, bridge, tower, facade)
  5. surfaces and background - road, ground, pavement, floor, water, grass, vegetation, sky

The node walks that order once. For each category it subtracts everything already claimed, keeps what's left, then adds its own kept pixels to the claimed set. Instances that end up with fewer than 9 pixels are dropped entirely rather than returned as slivers. A category that's been fully eaten by higher-priority masks comes back empty, and the report says so.

The priority is fixed, not configurable, and it's the right shape for this kind of work: keep the objects, let the surfaces absorb the subtraction. Turning it around would mean pavement masks chewing object-shaped holes out of people, which is the opposite of what you want when the object is the thing you're re-rendering at higher quality.

One geometry rule before any of that: all five masks must be the same H×W and three-dimensional, or you get DOGMA: ownership geometry mismatch. That check exists because a silently broadcast mismatch would produce confidence-inspiring garbage.

Inputs and outputs

  • mask_1…mask_5 (MASK) and category_1…category_5 (STRING, forced to a wire) - all required, so all ten sockets need something connected. Feed empty masks for unused slots; the node handles a zero-instance category fine, it just reports it as skipped.

Outputs:

  • mask_1…mask_5 (MASK) - the de-overlapped versions, in the same slot order. These are what you render from.
  • ownership_report (STRING) - one line per slot: people: 3 non-overlapping instances. or road: 0 non-overlapping instances. Fully occluded/empty category skipped; ownership retained by earlier categories.

Where people get burned

Subtraction is per-pixel, not per-instance. A pavement mask with a person standing on it comes back with a person-shaped hole, not a trimmed instance. That's correct for the job - you don't want the pavement re-render touching the person - but it means the mask is no longer a clean object, and anything downstream that assumes convexity or does a big dilate/feather will re-open the overlap you just resolved. If you feather, feather inward.

Nine pixels is a small threshold. Sensor-noise specks can survive it if they're clumped. If you're seeing one-instance-per-dust-speck in your masks, the cleanup belongs at the detection stage, not here.

Five slots, not eight. If you're coming from DOGMACategories8V111 with all eight categories populated, this node can't take all of them. You'll need to be selective about which five categories actually get rendered - which is the same decision DOGMAChooseCategoriesV111 exists to make - or run two ownership nodes on disjoint sets, with the caveat that they won't know about each other's claims.

Boxed in by design. Like everything in the v2 family, this node has no free parameters. No priority override, no overlap threshold, no way to say "let road win over vehicle". That's the bounded philosophy: fewer knobs, fewer ways to get a result you can't explain. If you need configurable overlap resolution semantics - soft blending, per-class weights, an ownership map you can inspect - that's not this node and you'd be building it.

Install

Manager → search DOGMA Nodes, or:

cd ComfyUI/custom_nodes
git clone https://github.com/axior/ComfyUI-DOGMA-Nodes
# restart ComfyUI

requirements.txt ships scipy>=1.10 as the pack's only Python dependency; no models are downloaded and no ComfyUI internals are patched. Note the internal wiring, since it explains one specific error: this node looks up the pack's v56.7 module for its canonicalisation and category rules, so a copy of the pack with missing files gives you DOGMA v2 requires the existing node pack containing DOGMASAMSearchV567 rather than anything about masks.

And the standard caveat for the pack: one author, DOGMA workflow, CPU-validated with mocked model calls, no community footprint worth measuring. For mask arithmetic like this, the honesty of the report is what makes it usable - you can see the per-category counts and the skip decisions, and that's enough to tell whether it did what you meant.

CategoryDOGMA/v2

Inputs (10)

NameTypeDefaultDescription
mask_1MASK—
category_1STRING—
mask_2MASK—
category_2STRING—
mask_3MASK—
category_3STRING—
mask_4MASK—
category_4STRING—
mask_5MASK—
category_5STRING—

Outputs (6)

NameTypeDescription
mask_1MASK—
mask_2MASK—
mask_3MASK—
mask_4MASK—
mask_5MASK—
ownership_reportSTRING—