DOGMA DualMask v56.6
DOGMA DualMask v56.6 and the 12-pixel difference that matters
- mask
- inpaint_mask
- blend_mask
- inpaint_preview
- blend_preview
- info
You have one approved mask and you need two. Not because the pack is being fussy - because sampling and compositing want genuinely different things, and using the same mask for both is how you get a ring of noise around every repaired object.
The idea
Standard inpainting practice, per the KB's inpainting doc: mask blur and padding exist because a masked pass with a razor-thin boundary has no context. The model gets told "these pixels are unknown, those pixels are gospel", right at the mask edge, and it resolves that tension badly - visible seams, a dark or soft rim.
The DOGMA pipeline had a related injury, and the author's own account of it is on Reddit: running hundreds of VACE inpaintings for a broadcast spot, mask edges were the part that needed hand work frame by frame. DualMask is the two-mask discipline that came out of that. Give the sampler a slightly fatter mask so the generated pixels have support and don't have to make up a boundary. Give the compositor the exact approved mask, so nothing you didn't verify ever gets pasted over your source.
How it works
The threshold and the dilation, both in about ten lines:
seed = (mask.float() >= .5).float()[:, None]
radius = min(32, max(8, round(min(mask.shape[-2:]) * .012)))
size = 2 * radius + 1
wide = F.max_pool2d(seed, (1, size), 1, (0, radius))
wide = F.max_pool2d(wide, (size, 1), 1, (radius, 0))
Two separable max-pools, horizontally then vertically, which is a square dilation of radius pixels. On a 1024-wide crop that's 12px; the radius scales with the crop, clamped between 8 and 32, and there's no widget for it. inpaint_mask is the dilated mask, blend_mask is the exact one.
The info string says the rest out loud: "Exact approved ownership: no closing, hole filling or blend growth. Noise support +12px only." Note what it deliberately does not do - no morphological closing, no filling interior holes. Holes in your approved mask are treated as information (a window in a facade, the gap between two pedestrians), not as errors to patch over.
Inputs and outputs
- mask - the approved, ownership-resolved mask. In practice from
DOGMAMaskOwnershipV567orDOGMAFinalMasksV567. - kind -
STRUCTURE/SURFACE/OBJECT, normally fromDOGMADenoiseCategoryV566. It's a required wire, but the shipped v56.6 code doesn't branch on it; the two masks are built the same way regardless.
Outputs: inpaint_mask and blend_mask (both MASK), plus inpaint_preview and blend_preview (IMAGE) so you can eyeball what you're about to sample with, and info.
Wiring, and this trips people up:
inpaint_mask→generation_masksonDOGMASoftStitchV566and →maskonDOGMAMaskedDenoiseLatentV566. It's the support mask.blend_mask→blend_maskson the stitch node. That's the alpha seed.- In the stitch node the final seed is
blend AND generation, so the dilation can never widen what gets composited. Two masks in, one ownership rule out.
Install
comfy node install comfyui-dogma-nodes
# or
cd ComfyUI/custom_nodes
git clone https://github.com/axior/ComfyUI-DOGMA-Nodes
pip install -r ComfyUI-DOGMA-Nodes/requirements.txt
The README says the pack is PyTorch-only; requirements.txt disagrees (scipy>=1.10), and while this node only needs torch, the module it lives in imports scipy.ndimage at the top. So install via Manager or run the pip line - hand-copying the folder without it fails at import, not at this node. No models to download for DualMask itself.
Gotchas
Check your mask range. The node assumes 0..1 probabilities. A mask that arrives scaled 0..255 reads as "everything is >= 0.5" and you'll silently get a full-frame dilation - the previews exist so you catch that in five seconds rather than after a 40-minute render. Same rule as the SAM guards upstream, which reject masks whose values fall outside 0..1.
The radius isn't a dial. If you need 24px of support on a 512px crop, either resize, dilate upstream, or accept the 8px you're getting. It scales with the crop rather than the object, so a small vehicle in a big crop gets proportionally more support than the same vehicle cropped tight.
Don't use inpaint_mask as your composite mask. It's the single most likely mis-wire in the graph, and it looks fine until you notice the fringe.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| kind | STRING | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| inpaint_mask | MASK | — |
| blend_mask | MASK | — |
| inpaint_preview | IMAGE | — |
| blend_preview | IMAGE | — |
| info | STRING | — |