Image extend v5.1.0
Give the model room below the face so it can grow a neck and body
- face_mask
- image
- image
- mask_image
Image extend solves a framing problem that comes up constantly in head-swap and try-on work: your model generated a great face, but the crop cuts off right below the chin - there's no room for a neck, let alone shoulders - so any downstream inpaint has to invent anatomy in a pixel-thin strip. This node measures the face, and if the space below it isn't proportional enough, it extends the canvas downward (and sideways to preserve aspect ratio) with black borders, so a follow-up generation or inpaint pass actually has canvas to draw a body on.
Mechanically it's straightforward. It takes your face_mask, finds the face's bounding box via contour detection, and compares the distance from the bottom of the face to the bottom of the image against the face height multiplied by ratio. If the space below the face is too small, it computes how many pixels to add, pads the bottom with black, and pads the sides symmetrically to keep the aspect ratio - then hands you both the extended image and a mask that marks exactly which regions were added, so your inpaint knows what's "new canvas" and what's "don't touch."
Inputs
image- the original frame.face_mask- a mask of the face (from the pack's face-mask extraction, e.g. the facer node, or any mask you have). The node reads it as a single-channel contour source.ratio- default 1.5, range 1.2–2.0. Target ratio of space-below-face to face height. Higher = more neck/body room. If the image already meets the ratio, the node returns the image unchanged with an all-black extension mask.
Outputs
image- the extended frame.mask_image- the extension mask: white where new canvas was added, black elsewhere. Wire this to an inpaint as the region to regenerate, or to a composite to know where the padding lives.
How to use it
The canonical loop: extend the frame, inpaint the extension mask with a prompt for "neck and shoulders," then optionally crop back or composite. The black padding becomes the inpaint's playground - outpainting into a defined region instead of hoping the model guesses the whole scene.
Install and gotchas
Standard pack install (Manager → search "tri3d", or git clone https://github.com/TRI3D-LC/tri3d-comfyui-nodes into ComfyUI/custom_nodes, then restart). Keep the folder name tri3d-comfyui-nodes. Pure OpenCV/numpy - no model, no extra deps.
- The ratio check only fires when the face is too low in the frame. If the face is already high up with plenty of room below, nothing happens and you get an all-black mask - that's the "nothing to do" signal, not a bug.
- It extends with solid black, not mirrored content or a blur. Your inpaint has to do the work, so black is fine; just don't expect the extension to look like anything until you've run a pass over it.
- The face mask should be reasonably tight. A mask that includes hair or shoulders skews the face-height measurement and gives you a wrong ratio.
It's a small outpainting helper, but it's the difference between "inpaint a neck into a 20-pixel strip" and "give the model room to do its job." For portrait and try-on pipelines, that difference is the whole game.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| face_mask | IMAGE | — | |
| image | IMAGE | — | |
| ratio | FLOAT | 1.501.2–2 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask_image | IMAGE | — |