Nodes/Face Processor for ComfyUI/Face Fit or Restore
ComfyUI Node

Face Fit or Restore

Give the face its own resolution, then put it back

By SykkoAtHome·Created 2 years ago·Updated 9 months ago· 20
Face Fit or Restore
  • image
  • fp_pipe
  • image_sequence
  • image
  • fp_pipe
  • mask
  • bbox_size
workflowimage
modeFit
output_modecurrent_frame
padding_percent0.00
bbox_size1024

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

  1. Fit on the original image → get a clean 512/1024/2048 face crop and an fp_pipe that remembers exactly where that face came from.
  2. 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.
  3. Restore with the edited face in image and the original fp_pipe wired 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-requires fp_pipe from an earlier Fit; it errors out otherwise.
  • workflow - image for a single picture, image_sequence to chew through a sequence. Sequence mode consumes the image_sequence DICT that ImageFeeder emits, and output_mode (current_frame vs batch_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 see None come 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.
CategoryFace Processor

Inputs (8)

NameTypeDefaultDescription
workflowCOMBOimage2 options: image, image_sequence
modeCOMBOFit2 options: Fit, Restore
output_modeCOMBOcurrent_frame2 options: current_frame, batch_sequence
padding_percentFLOAT0.000–1
bbox_sizeCOMBO10243 options: 512, 1024, 2048
imageoptIMAGE
fp_pipeoptDICT
image_sequenceoptDICT

Outputs (4)

NameTypeDescription
imageIMAGE
fp_pipeDICT
maskMASK
bbox_sizeINT