Nodes/DOGMA Nodes/DOGMA Object Native Crops v1.0.11
ComfyUI Node

DOGMA Object Native Crops v1.0.11

Keep whole objects in one tile instead of slicing through them

By axior·Created 6 months ago·Updated 16 days ago· 2
DOGMA Object Native Crops v1.0.11
  • image
  • masks
  • crops
  • crop_masks
  • stitch
  • info
◄category—►
◄kind—►
◄target_long_side2048►
◄group_gap_px180►
◄context_px160►
◄max_objects_per_chunk6►
◄max_chunks4►
◄mask_threshold0.30►

What it is

Same job as DOGMANativeChunkCropsV2 - turn a category's masks into native-resolution crop tiles with masks and stitch metadata - with one philosophical difference. Chunk crops cut a grid across the masked region. This cuts around objects.

For each mask instance it computes the bounding box, then greedily merges nearby boxes into groups as long as the merged box still fits the render budget and the group doesn't exceed max_objects_per_chunk objects. Each surviving group becomes one tile with context_px of surround. A single object too large to fit the budget is the only case that falls back to spatial tiling - and then only within that object's own box.

The v1.0.11 changelog describes it as restoring "object-preserving grouping from earlier V54.5/V56/V68 design while retaining the hard no-downscale budget", so this is the older idea reinstated, not a new one. It also tells you what changed while it was gone: purely spatial windows cut through objects, and whatever renders each tile then sees half a car.

Why the grouping matters in practice

If the thing re-rendering your tiles is a diffusion model, a tile that contains a whole object gives it a coherent subject and a consistent prompt. A tile that contains half an object gives it a crop seam and a plausible-looking wrong answer. If the thing consuming tiles is a VLM - captioning, auditing, describing - the same argument applies harder, because "what is this?" is much easier to answer from a whole object.

The cost is resolution efficiency. Three small objects within group_gap_px of each other become one tile: fewer tiles, better coherence, and more pixels spent on empty space between them. Since the node can't downscale, that empty space is only acceptable as long as the merged box fits under target_long_side. Push group_gap_px up and target_long_side down and you'll start hitting the fold-back case where everything becomes spatial windows again.

Inputs

  • image (IMAGE) - the source frame. First image of a batch, and only that one.
  • masks (MASK) - the approved instances.
  • category, kind (STRING, forced inputs) - category labels reports; kind is carried for wiring parity and isn't branched on in this version.
  • target_long_side (INT, 512–4096, step 32, default 2048) - tile render budget.
  • group_gap_px (INT, 0–1200, default 180) - how far apart two objects can be and still merge into one tile. This node is where this input actually does something.
  • context_px (INT, 32–640, step 32, default 160) - surround around the group, halved and clamped if the group is nearly budget-sized.
  • max_objects_per_chunk (INT, 1–20, default 6) - a merge is refused if it would exceed this many objects. Also live only here.
  • max_chunks (INT, 1–24, default 4) - tile ceiling; extras get ranked by mask coverage and deferred.
  • mask_threshold (FLOAT, 0.05–0.8, default 0.3) - union threshold.

Outputs

  • crops (IMAGE, list), crop_masks (MASK, list) - tiles and their masks, each padded to multiples of 32 with a 32px ownership strip shared with the neighbouring core.
  • stitch (DOGMA_STITCH, list) - source x/y, crop size, source size, pad amounts, model_mode='native_or_upscale_only'. Feed it to a stitch node, or use the fields to paste back yourself.
  • info (STRING) - window count, deferred count, and a per-tile line like 2: source 1440x980 -> render 1440x1020.

Empty masks give sentinels rather than an error: a 1×64×64 image, a zero mask, [{'noop': True}], and a message that no diffusion is required - which is what you want when a category was intentionally culled upstream.

Where people get burned

Deferred tiles look like success. The output list is whatever fit under max_chunks; the rest is reported in info and otherwise absent. Nothing downstream can tell you that half your buildings were skipped, because there's no error to raise. Read that string, or put it on a Show Text node next to the render.

group_gap_px fights target_long_side. Merging is only allowed if the padded group fits the budget, so with a 1024 budget and six objects at 180px gaps you'll find everything reverting to spatial windows - which is the fallback you were trying to avoid. Either raise the budget or lower the gap.

Tiles are big. At target_long_side 2048 a single tile is a 2048-class render, and this node never downscales, so a six-tile scene is six renders at that size. That's the price of native detail; the KB's tiled-upscaling comparison is the right mental model - you're buying fidelity with VRAM and time.

Install

Manager → search DOGMA Nodes, or:

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

scipy>=1.10 from requirements.txt is the pack's whole Python dependency list; no models, no core patches. One implementation detail that produces a confusing error if you hit it: this node imports its geometry helpers from DOGMANativeChunkCropsV2's module by looking that class up in ComfyUI's registry, so a partial install fails with a message about a missing node rather than about crops. If a v1.0.11 node complains about a v2 node, that's a broken install, not a version conflict.

CategoryDOGMA/v1.0.11

Inputs (10)

NameTypeDefaultDescription
imageIMAGE—
masksMASK—
categorySTRING—
kindSTRING—
target_long_sideINT2048512–4096—
group_gap_pxINT1800–1200—
context_pxINT16032–640—
max_objects_per_chunkINT61–20—
max_chunksINT41–24—
mask_thresholdFLOAT0.300.05–0.8—

Outputs (4)

NameTypeDescription
cropsIMAGE—
crop_masksMASK—
stitchDOGMA_STITCH—
infoSTRING—