MQ BBox (MIN)
Turn a noisy mask into a reliable subject box
- mask
- x
- y
- w
- h
- debug
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."autoguesses from the mask's fill ratio, which works most of the time; set it explicitly ifautopicks 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). Withtight_cropon, 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_cropis 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.
autoinvert picked wrong - forceinvert_masktotrue/falseexplicitly.autoguesses 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.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| invert_mask | COMBO | auto | 3 options: auto, false, true |
| q_left | FLOAT | 0.0050–0.2 | — |
| q_right | FLOAT | 0.9950.8–1 | — |
| q_top | FLOAT | 0.0050–0.2 | — |
| q_bottom | FLOAT | 0.9950.8–1 | — |
| min_span_px | INT | 81–2048 | — |
| tight_crop | BOOLEAN | false | ON: tight subject bbox with smart AR; OFF: full frame (minimal AR crop downstream). |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| x | INT | — |
| y | INT | — |
| w | INT | — |
| h | INT | — |
| debug | STRING | — |