Nodes/ComfyUI-TinyBee/Face Body Aspect Bounds
ComfyUI Node

Face Body Aspect Bounds

The Crop That Keeps the Face

By TinyBeeman·Created about a year ago·Updated about a month ago· 1
Face Body Aspect Bounds
    • body_x
    • body_y
    • body_width
    • body_height
    • face_x
    • face_y
    • face_width
    • face_height
    • face_x_body_rel
    • face_y_body_rel
    face_x0
    face_y0
    face_width128
    face_height128
    body_x0
    body_y0
    body_width256
    body_height512
    aspect_ratio1.00
    exceedBoundsfalse
    ensureUpperBodyPct0.00
    image_width512
    image_height512

    The classic failure in portrait generation isn't the model - it's the crop. You resize a body-region crop to a target aspect ratio, and the head gets sliced off, or the composition is awkward because the box recentered on something that isn't the face. Face Body Aspect Bounds is purpose-built for that: you give it a body bounding box and a face box inside it, and it resizes the body box to your aspect ratio while guaranteeing the face stays inside and preserving the face's original relative position. This is the node that makes "crop the person, keep the head" a solved problem.

    How it works

    You provide two boxes and one target:

    • Body box: body_x, body_y, body_width, body_height.
    • Face box: face_x, face_y, face_width, face_height - given relative to the body box's top-left corner.
    • aspect_ratio: the width/height you want the output body box to have (default 1.0).

    The outputs hand back both boxes, recomputed: body_x, body_y, body_width, body_height and face_x, face_y, face_width, face_height - the latter re-expressed relative to the new body box, so downstream code that assumes face-coords-are-body-relative stays correct.

    The core mechanism is the neat part. First it computes the face's position as a fraction of the body box - frac_x, frac_y - rather than assuming the face is dead-center. Then it works out the smallest aspect-correct body size that can still fully contain the face, and (by default) fits the body box down toward that snug size - never larger than the original body box. The body box is then repositioned so the face keeps the same relative spot it had before, with corrections to make sure the face is fully inside. The result: a tighter, aspect-correct body crop where the head lands where it should, headroom included.

    A detail worth noting: the node picks the "body direction" from the body box's own shape - a box taller than wide means the body extends vertically, and the face-keeping logic orients accordingly. Near-square boxes default to upright, since that's the common case. So this node is less naive than it first appears about how a person is oriented.

    Where you'd actually use it

    • Face-detector → crop pipelines: feed boxes from a face detector (Florence2-style caption parsing or an object detector) into this, then use the resulting box to crop or inpaint the body region.
    • Portrait reframing: normalize a person-crop to a consistent aspect for a batch.
    • Composition control: keep natural headroom instead of hard-centering the face.

    Installing it

    Part of ComfyUI-TinyBee under 🐝TinyBee/Util:

    1. ComfyUI Manager → Install Custom Nodes → search "ComfyUI-TinyBee" → Install, then restart ComfyUI.
    cd ComfyUI/custom_nodes
    git clone https://github.com/TinyBeeman/ComfyUI-TinyBee
    

    Restart. No models; it's pure coordinate math, so none of the pack's requirements.txt entries (pillow, jsonata) come into play.

    Gotchas

    The face box must be relative to the body box, which trips people up the first time - if your detector gives you absolute coordinates, subtract the body origin first. The default behavior also shrinks the body toward the face rather than growing outward, so if your face and body boxes are imprecise, you may get a crop that's snugger than you wanted. And remember the output face box is relative to the new body box - that's consistent with the input convention, but it means the absolute face position shifted along with the body. Feed it sane boxes and this node quietly turns a fiddly geometry problem into a single node.

    Category🐝TinyBee/Util

    Inputs (13)

    NameTypeDefaultDescription
    face_xINT0-10000–10000
    face_yINT0-10000–10000
    face_widthINT1281–10000
    face_heightINT1281–10000
    body_xINT0-10000–10000
    body_yINT0-10000–10000
    body_widthINT2561–10000
    body_heightINT5121–10000
    aspect_ratioFLOAT1.000.01–100
    exceedBoundsBOOLEANfalse
    ensureUpperBodyPctFLOAT0.000–10
    image_widthINT5121–10000
    image_heightINT5121–10000

    Outputs (10)

    NameTypeDescription
    body_xINT
    body_yINT
    body_widthINT
    body_heightINT
    face_xINT
    face_yINT
    face_widthINT
    face_heightINT
    face_x_body_relINT
    face_y_body_relINT