Align Face
Straighten a tilted head before it wrecks your pipeline
- image
- image
Faces tilted a few degrees look fine to you and terrible to any face model downstream. AlignFace fixes that: it detects the face, works out the angle between the eyes, and rotates the entire image so the eyes sit on a level line. Feed it a head that's listing to one side, get back a front-facing, level image the same size as the input. It's the "make it frontal" step that a lot of identity and restoration workflows quietly assume you already did.
The one-sentence version of when you need it: if your next node is a face-swap, a face-restore, or anything identity-sensitive, and your source photo is a casual selfie - run AlignFace first.
How it works
It uses the same RetinaFace resnet50 detector the rest of the pack uses. It finds all faces, picks the largest one (the "main" face), grabs the five facial landmarks, and takes the first two - left and right eye. The angle of the line between them is the tilt. It builds a rotation matrix around the midpoint of the eyes and rotates the whole image with OpenCV, using INTER_CUBIC interpolation and replicated borders so the corners don't go black.
Notable detail: angle_offset is not zero by default - it's +1.0 degree, a small nudge past "perfectly level" that the author apparently prefers (it's the same bias in the other face nodes). If you want textbook-level alignment, drop it to 0 or even negative for the opposite bias. It also runs the detector a second time on the rotated image and only returns the rotation if a face is still found - if alignment somehow loses the face, you get the original back instead of garbage.
The inputs and outputs
- image - your IMAGE tensor.
- half - run the detector in fp16. Off by default; flip it on if you're tight on VRAM. You won't notice a quality difference on modern GPUs.
- angle_offset - fine-tune the rotation in degrees, from -180 to 180. Use it when the automatic leveling is consistently a hair off.
One output, image - the rotated, same-size image. It rotates the whole canvas, so nothing is cropped away; tilted content at the edges just rotates with it.
How to install
Part of billwuhao/ComfyUI_PortraitTools:
cd ComfyUI/custom_nodes
git clone https://github.com/billwuhao/ComfyUI_PortraitTools.git
cd ComfyUI_PortraitTools
pip install -r requirements.txt # or: ./python_embeded/python.exe -m pip install -r requirements.txt
The one real dependency is the face detector: put detection_Resnet50_Final.pth in ComfyUI/models/facedetection/ (from the README's HuggingFace link - if you already have ReActor installed, the file is shared). Without it the node errors immediately. Dependencies otherwise are just opencv-python, PyYAML and huggingface_hub.
Where people get burned
- No face detected = input passed through unchanged. The node prints a message and hands you back the original image, which is forgiving but easy to miss - check your console if a run "did nothing."
- It rotates the whole frame, not just the face. If your subject is off-center and the background is complex, you'll see the world tilt around them. That's by design (it preserves resolution and context), but it means the output isn't a crop.
- It wants the eyes visible. Profile shots or heavy shadows where the landmarks can't be found will fall through to the pass-through path.
- One face at a time: with a group shot it takes the biggest face and levels that one, which may not be what you want.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| half | BOOLEAN | false | — |
| angle_offset | FLOAT | 1.0-180–180 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |