Nodes/PortraitUtils/MQ BBox (MIN)
ComfyUI Node

MQ BBox (MIN)

Turn a noisy mask into a reliable subject box

By heyburns·Created 11 months ago·Updated 4 months ago· 1
MQ BBox (MIN)
  • mask
  • x
  • y
  • w
  • h
  • debug
invert_maskauto
q_left0.005
q_right0.995
q_top0.005
q_bottom0.995
min_span_px8
tight_cropfalse

Subject masks from models are rarely clean. There are speckles, holes, a stray arm floating outside the body, a big blob of false positive in the corner. If you compute a bounding box straight off that mask, you get a box that's too big or slightly offset, and every crop built on it inherits the sloppiness. MQBBoxMin fixes this the statistical way: instead of taking the mask's min/max extremes, it uses quantiles per edge, so a few stray pixels on the left edge don't balloon the box by half the image width.

Feed it a MASK, and it returns x, y, w, h plus a debug string. The controls that matter:

  • invert_mask (auto/false/true) - whether the mask is "subject is white" or "subject is black." auto guesses from the mask's fill ratio, which works most of the time; set it explicitly if auto picks wrong.
  • q_left/q_right/q_top/q_bottom - the quantile cutoffs per edge (defaults 0.005 and 0.995). At the defaults it trims the outermost 0.5% of mask mass on each side, which is exactly enough to shrug off salt-and-pepper noise without touching the real subject. Tighten toward 0.01/0.99 for noisier masks, loosen for precision work.
  • min_span_px (default 8) - a floor on the box size so a mask that's nearly empty doesn't produce a degenerate 1×1 box.
  • tight_crop - the important one. Its tooltip says it best: ON gives a tight subject bbox with smart aspect ratio, OFF gives the full frame (with a minimal aspect-ratio crop applied downstream). With tight_crop on, the node computes the quantile box, pads it a little, then tries to fit it inside the smallest container among the common ratios (1:1, 2:3, 3:2, 3:4, 4:3, 9:16, 16:9) so the box you get is already aspect-friendly. That's the "smart AR" step, and it's why the output crops look deliberate instead of accidental.

The debug output tells you which foreground it picked, the raw quantile box, and which smart ratio won - genuinely useful when the box lands somewhere surprising. This is the front end of the pack's framing stack: its output feeds FitAspectHeadSafe, which turns the box into a head-safe crop at a chosen aspect.

Install

Manager → search "PortraitUtils", or:

cd ComfyUI/custom_nodes
git clone https://github.com/heyburns/PortraitUtils

Restart. Pure numpy/torch math on the mask tensor; no extra deps.

Common issues

  • Box is way too big - tight_crop is off, so you're getting the full frame by design. Flip it on if you want the subject-box behavior.
  • Box hugs a corner that's all noise - the mask has a solid false-positive blob the quantiles can't outvote. Fix the mask upstream; no quantile setting rescues a fundamentally wrong mask.
  • auto invert picked wrong - force invert_mask to true/false explicitly. auto guesses by fill ratio, and a nearly-full or nearly-empty mask breaks the heuristic.
  • Box shrinks or jumps between runs - masks from different segmentation runs vary; quantiles damp it but don't eliminate it. Feed it the same mask source and it's stable.

Every "intelligent crop" in this pack is only as good as its box, and this is where the box comes from.

CategoryPortraitUtils/Transform

Inputs (8)

NameTypeDefaultDescription
maskMASK
invert_maskCOMBOauto3 options: auto, false, true
q_leftFLOAT0.0050–0.2
q_rightFLOAT0.9950.8–1
q_topFLOAT0.0050–0.2
q_bottomFLOAT0.9950.8–1
min_span_pxINT81–2048
tight_cropBOOLEANfalseON: tight subject bbox with smart AR; OFF: full frame (minimal AR crop downstream).

Outputs (5)

NameTypeDescription
xINT
yINT
wINT
hINT
debugSTRING