Flux FaceIR Detect And Align Face
Finding, straightening, and exporting the face so the restoration has something to work on
- retinaface_model
- image
- aligned_face
- align_params
- align_params_json
In the whole-image FaceIR workflow, this is the "detect" half of detect-restore-paste. Flux FaceIR Detect And Align Face finds faces in a full photo, picks one, and warps it into a clean, square, front-facing crop that Flux FaceIR Restore Face can actually fix. Then - this is the clever part - it hands you the parameters to put the fixed face back exactly where it came from.
The name is a lie in the fun way: nothing is being restored here, only located and straightened. But a restoration model is only as good as its crop, and this node is why the crop doesn't wreck the result.
How it works
Under the hood it's the classic detect-crop-paste loop from the detailing playbook, minus the inpainting. RetinaFace returns bounding boxes plus five facial landmarks (eyes, nose, mouth corners). The node estimates an affine transform that maps those landmarks onto a canonical template, then warps the photo so the face is centered and upright at a fixed square size - typically 512px. The template geometry, the transform, and the inverse transform are all bundled into align_params, which the paste-back node later inverts to drop the restored face onto the original pixels.
A detail worth knowing: if nothing's found at your confidence threshold, it doesn't just fail - it retries with progressively lower thresholds and larger resize scales before giving up. For a noisy old photo that barely registers as a face, that fallback chain is often the difference between "restored" and an error.
The inputs that matter
You'll touch maybe four of these:
face_selection-largest,center, orhighest_score.largestis right for a single-subject portrait;centeris the pick for group shots where you want the middle face.face_size- the output crop resolution, default 512. Match it to theresolutionon Restore Face and you avoid a resize round-trip.crop_scale- default 1.35. This one's a subtle lever: it widens the crop beyond the pure landmark box to pull in forehead, chin, and shoulders. More context means a more natural restored face; too much and you're restoring background too.conf_threshold- default 0.6. Drop it toward 0.3–0.4 if the fallback chain still misses and the image genuinely has a face in it.
The NMS and resize_short_edge knobs are detector plumbing. Leave them. crop_shift_y nudges the crop vertically - a positive value pushes the face lower in the frame, so you see more forehead and hair above it (and less chin); negative does the reverse. border_mode decides how out-of-frame edges fill - constant is a fine default.
The outputs, and where they go
aligned_face(IMAGE) - the straightened square crop → into Flux FaceIR Restore Face.align_params(FACEIR_ALIGN_PARAMS) - the opaque geometry bundle → into Flux FaceIR Paste Restored Face. Keep this paired with the exact image that produced it.align_params_json(STRING) - the same data as readable JSON, for debugging or export. You won't wire it into anything.
Installing and getting it running
The pack ships via ComfyUI Manager (search Flux FaceIR) or git clone https://github.com/cosmicrealm/ComfyUI-Flux-FaceIR into custom_nodes, then python install.py and a full restart. Before this node will run you need the detector weights:
mkdir -p ComfyUI/models/face_detectors
wget -O ComfyUI/models/face_detectors/retinaface_r34.pth \
https://github.com/yakhyo/retinaface-pytorch/releases/download/v0.0.1/retinaface_r34.pth
The bundled full_image_restore.json workflow wires everything up (it runs a couple of detect nodes at different crop_scale values, so don't be surprised to see it twice in the graph).
Where people get burned
- "No face detected" ValueError - it tried every fallback and found nothing. Either the face is too small/obscured for the defaults (lower
conf_threshold), or you fed it a batch item that genuinely has no face in it. The node processes each image in the batch and will tell you exactly which one and what it tried. - Face comes back looking like a different person - that's usually not this node's fault; it's the restoration being blind (see the reference-guided option on Restore Face). What this node can cause is an awkward crop that the restorer then invents details for. Widen
crop_scaleand re-run before blaming the model.
One honest caveat: this is a per-face, per-image job. A batch of twenty photos is twenty detect-and-align passes, and each one downstream eats a full 50-step diffusion run. Batch accordingly.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| retinaface_model | RETINAFACE_MODEL | — | |
| image | IMAGE | — | |
| face_selection | COMBO | largest | 3 options: largest, center, highest_score |
| face_size | INT | 512256–1024 | — |
| crop_scale | FLOAT | 1.351–2.5 | — |
| crop_shift_y | FLOAT | 0.00-0.25–0.25 | — |
| conf_threshold | FLOAT | 0.600.05–0.99 | — |
| pre_nms_topk | INT | 50001–20000 | — |
| nms_threshold | FLOAT | 0.400.05–0.95 | — |
| post_nms_topk | INT | 7501–5000 | — |
| resize_short_edge | INT | 6400–4096 | — |
| border_mode | COMBO | constant | 3 options: constant, reflect101, reflect |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| aligned_face | IMAGE | — |
| align_params | FACEIR_ALIGN_PARAMS | — |
| align_params_json | STRING | — |