Face Fit or Restore
Give the face its own resolution, then put it back
- image
- fp_pipe
- image_sequence
- image
- fp_pipe
- mask
- bbox_size
This is the node that makes the "fit, fix, restore" workflow real, and it's the closest thing in the pack to what you already know from face-detailer tools. The underlying problem is the same one ADetailer solved: a face that's 60×60 pixels inside a 1024 render barely has any latent budget, so it comes out smeared no matter how good your checkpoint is. The fix is to give that face its own high-resolution pass. ADetailer automates that with inpainting; FaceFitAndRestore gives you the manual, deterministic version - and it's the same trick that made faces work before inpainting detailers existed.
Fit mode detects the face with MediaPipe, rotates the image so the eyes are level, crops a square around the face (with padding_percent of extra margin, 0–1), and resizes to a workable size. Restore is the return trip: it takes your edited face, resizes it back, and places it into the original frame using the crop box and rotation angle it recorded during Fit - plus a matching mask so you can blend seams instead of leaving a hard edge.
How to chain it
- Fit on the original image → get a clean 512/1024/2048 face crop and an
fp_pipethat remembers exactly where that face came from. - Process the crop - img2img, inpaint, upscale, or a HighPassFilter clarity pass. Do whatever you want; it's now at a resolution where it can actually hold detail.
- Restore with the edited face in
imageand the originalfp_pipewired in → out comes the full frame with your fixed face seated back in place, plus a mask of the touched region.
That's a two-node round trip with zero inference hidden inside it, which makes it gloriously inspectable: you can see exactly what got cropped, exactly what got changed, and exactly where it went back.
Inputs and outputs that matter
mode- Fit or Restore. Restore hard-requiresfp_pipefrom an earlier Fit; it errors out otherwise.workflow-imagefor a single picture,image_sequenceto chew through a sequence. Sequence mode consumes theimage_sequenceDICT that ImageFeeder emits, andoutput_mode(current_framevsbatch_sequence) picks whether you get the one frame you're on or the whole run stacked into a batch.bbox_size- 512, 1024, or 2048. This is your "resolution budget" knob; 1024 is a sane default for faces, 2048 if you're upscaling later.padding_percent- extra room around the face. A little padding stops the crop from kissing the hairline; too much and you're back to low-res face in a high-res box.
Outputs: image, fp_pipe, mask (the face region, rotated back to frame space), and bbox_size as an INT (handy if you want to wire the crop size downstream).
Installing
Shared pack install - Manager search "Face Processor", or:
cd ComfyUI/custom_nodes
git clone https://github.com/SykkoAtHome/ComfyUI_FaceProcessor.git
then restart ComfyUI and let requirements.txt (mediapipe, dlib, pandas, cupy-cuda12x) install. The MediaPipe face model downloads itself on first Fit; no manual model fetching.
Troubleshooting
- Restore with no
fp_pipe- the node explicitly validates and returns nothing useful. The error message is printed to console, and you'll seeNonecome out the image port. Fit first, always. - No face found - Fit returns the original image unchanged plus an empty mask. A profile shot that MediaPipe can't land on will silently pass through.
- Sequence out of sync - Restore reads
fp_pipe["frames"]and matches by frame index, so the number of frames you Fit has to match what you Restore. If your sequence length changes between passes, later frames error out per-frame. - The restore seam - you get a mask precisely because the hard crop edge will show. Blur/feather it or composite with it; that's the intended workflow, not a bug.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| workflow | COMBO | image | 2 options: image, image_sequence |
| mode | COMBO | Fit | 2 options: Fit, Restore |
| output_mode | COMBO | current_frame | 2 options: current_frame, batch_sequence |
| padding_percent | FLOAT | 0.000–1 | — |
| bbox_size | COMBO | 1024 | 3 options: 512, 1024, 2048 |
| imageopt | IMAGE | — | |
| fp_pipeopt | DICT | — | |
| image_sequenceopt | DICT | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| fp_pipe | DICT | — |
| mask | MASK | — |
| bbox_size | INT | — |