Face-Shaper
Draw the face you want, and let Qwen-Image-Edit make it real
- settings_list
- IMAGE
- LIST
The name is a bit of a lie, in the best way. Face-Shaper never touches your photo - it draws a face. Black line art on a white (or transparent) canvas: head outline, jaw, forehead, eyes, irises, brows, nose, lips. What you get out is a structural guide image, meant to be dropped into an image-editing workflow as a conditioning reference for Qwen-Image-Edit-2511. You shape the line drawing, and the edit model shapes the actual face to match.
That's the whole reason this node exists. Prose prompts are terrible at precise geometry - "narrower jaw, wider-set eyes, fuller upper lip" is a coin flip even on a good day. A drawn mask isn't. It's the same trick behind the "crop-and-stitch" conditioning people bolt onto Qwen-Image-Edit because the model re-emits the whole frame and drifts if you leave structure to chance. Here you get a parametric sketch instead of hand-drawing it in an image editor. One README warning up front: it currently works only with Qwen-Image-Edit-2511, so don't expect Flux Kontext or the 2509 revision to obey it the same way.
How it works
Every feature starts life as coordinates parsed from the pack's bundled Face_Mask_female.svg, normalized to a 0–1 space. Each group (eyes, brows, nose, lips, head) gets its own scale/translate/rotate applied before pixel conversion, so scaling an eye doesn't stretch its neighbor. That relative space is then projected onto your canvas with x = (rx - 0.5) * canvas_width * camera_distance + canvas_width / 2 - and, nicely, there's a virtual camera here. camera_distance is global zoom, camera_pos_x/y pan, and fov_mm (neutral at 80) applies actual radial lens distortion: barrel below 80, pincushion above. It's a small touch, but edit models respond to lens geometry, so a little distortion can sell the shot. Drawing is plain Pillow polylines and circles, returned as a float32 0–1 tensor.
The reset button in the footer and the settings_list input are one feature split in two: the node's second output is a LIST of every current parameter, and feeding that list back into settings_list restores it - that's your preset system, with backward compatibility for older saved lists built in.
The inputs that matter
You'll actually touch a fraction of the ~45 widgets. Start with these:
canvas_width/canvas_height- 1024 default; output size, not the model's.transparent_background- off gives RGB white, on gives RGBA with a transparent canvas. Only flip it on if your downstream node can handle an alpha channel.line_thickness- 2.0 default; the stroke width. Anything below ~1 rounds to a 1px line.gender-femaleormale, but read the fine print: male currently uses the female coordinate data (the README says so). Don't expect a distinct male anatomy yet.
Then the geometry sliders: head_size_x/y, jaw_size_x, fore_head_size_x for the skull shape; eye_left_* / eye_right_* (including independent eye_left_rotation / eye_right_rotation, great for expression); iris_*; eyebrow_*; nose_pos_y / nose_size_* / nose_tip_pos_y; and lip_size_x, lip_upper_size_y, lip_lower_size_y. Positions are fractions of the canvas (positive x = right, positive y = down), sizes are multipliers around 1.0.
Wiring it up
Outputs are IMAGE and LIST. The bundled Workflow_Face_Shaper_Qwen_Edit_2511.json shows the intended path: your source portrait, overlaid with the face-shaper image, fed into a Qwen Image Edit sampler node alongside the photo as a conditioning reference. The mask image and settings_list also make it easy to batch-compare face shapes - render one, dial the list, render the next.
Install
cd ComfyUI/custom_nodes/
git clone https://github.com/EricRorich/ComfyUI-face-shaper.git
Then restart ComfyUI - it lands under the face category as Face Shaper. ComfyUI Manager can also find it by searching "ComfyUI-face-shaper". There are no extra pip dependencies (torch, numpy, Pillow all ship with ComfyUI), and the node downloads no model files itself. The catch is upstream: to actually use it you'll need the Qwen-Image-Edit-2511 weights plus its VAE (qwen_image_vae.safetensors) and a Qwen Edit sampler pack - the workflow file names QwenImageIntegratedKSampler, which comes from a separate integration pack.
Gotchas
- It's young. This is a WIP pack from early 2026 with essentially zero community track record yet. If something misbehaves, the GitHub issues page is your only real knowledge base.
- The white/RGBA background is part of the guide. If it fights your composition, overlay it with transparency rather than blending it flat - the CR Overlay node in the bundled workflow is doing exactly that.
- Don't fight
fov_mmuntil you've seen what 80 looks like. Default first, fiddle later.
Inputs (48)
| Name | Type | Default | Description |
|---|---|---|---|
| canvas_width | INT | 1024256–2048 | — |
| canvas_height | INT | 1024256–2048 | — |
| transparent_background | BOOLEAN | false | — |
| line_thickness | FLOAT | 2.00.5–10 | — |
| gender | COMBO | 2 options: female, male | |
| fov_mm | FLOAT | 8016–200 | — |
| camera_distance | FLOAT | 1.000.5–2 | — |
| camera_pos_x | FLOAT | 0.00-0.5–0.5 | — |
| camera_pos_y | FLOAT | 0.00-0.5–0.5 | — |
| head_size_x | FLOAT | 1.000.5–2 | — |
| head_size_y | FLOAT | 1.000.5–2 | — |
| jaw_size_x | FLOAT | 1.000.5–2 | — |
| fore_head_size_x | FLOAT | 1.000.5–2 | — |
| eye_left_size_x | FLOAT | 1.000.5–3 | — |
| eye_left_size_y | FLOAT | 1.000.5–3 | — |
| eye_left_pos_x | FLOAT | 0.00-0.5–0.5 | — |
| eye_left_pos_y | FLOAT | 0.00-0.5–0.5 | — |
| eye_left_rotation | FLOAT | 0.0-45–45 | — |
| eye_right_size_x | FLOAT | 1.000.5–3 | — |
| eye_right_size_y | FLOAT | 1.000.5–3 | — |
| eye_right_pos_x | FLOAT | 0.00-0.5–0.5 | — |
| eye_right_pos_y | FLOAT | 0.00-0.5–0.5 | — |
| eye_right_rotation | FLOAT | 0.0-45–45 | — |
| iris_left_size | FLOAT | 1.000.5–3 | — |
| iris_left_pos_x | FLOAT | 0.000-0.25–0.25 | — |
| iris_left_pos_y | FLOAT | 0.000-0.25–0.25 | — |
| iris_right_size | FLOAT | 1.000.5–3 | — |
| iris_right_pos_x | FLOAT | 0.000-0.25–0.25 | — |
| iris_right_pos_y | FLOAT | 0.000-0.25–0.25 | — |
| eyebrow_left_size_x | FLOAT | 1.000.5–2 | — |
| eyebrow_left_size_y | FLOAT | 1.000.5–2 | — |
| eyebrow_left_pos_x | FLOAT | 0.00-0.5–0.5 | — |
| eyebrow_left_pos_y | FLOAT | 0.00-0.5–0.5 | — |
| eyebrow_left_rotation | FLOAT | 0.0-45–45 | — |
| eyebrow_right_size_x | FLOAT | 1.000.5–2 | — |
| eyebrow_right_size_y | FLOAT | 1.000.5–2 | — |
| eyebrow_right_pos_x | FLOAT | 0.00-0.5–0.5 | — |
| eyebrow_right_pos_y | FLOAT | 0.00-0.5–0.5 | — |
| eyebrow_right_rotation | FLOAT | 0.0-45–45 | — |
| nose_pos_y | FLOAT | 0.00-1–1 | — |
| nose_size_x | FLOAT | 1.000–2 | — |
| nose_size_y | FLOAT | 1.000–2 | — |
| nose_tip_pos_y | FLOAT | 0.000-0.2–0.2 | — |
| lips_pos_y | FLOAT | 0.00-0.5–0.5 | — |
| lip_size_x | FLOAT | 1.000–2 | — |
| lip_upper_size_y | FLOAT | 1.000.5–2 | — |
| lip_lower_size_y | FLOAT | 1.000.5–2 | — |
| settings_listopt | LIST | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| LIST | LIST | — |