NAI Face Detailer
ADetailer-style face fixing, but the inpaint runs on NovelAI
- image
- bbox_detector
- sam_model
- segm_detector
- eye_bbox_detector
- characterPrompts
- tagger
- image
- mask_visualization
- matching_report
Small faces are the structural failure of image generation: a face occupying 70 pixels of a 1024px frame has almost no latent budget, so it renders as a smear no matter how good the model is. The fix has been settled for years - detect the face, crop it, re-render the crop at proper resolution, paste it back. NAIFaceDetailerNode runs that whole loop, except the re-render step happens on NovelAI's cloud inpainting instead of a local checkpoint.
So think of it as ADetailer's pipeline wearing this pack's cloud-model coat: YOLO detects the first face, SAM segments it, NAI inpaints the region, and the result is composited back onto your original. It's the node you reach for when a V5 or V4.5 generation came back with a broken face and you want NAI's own model to fix it rather than round-tripping to a local SDXL.
How it works
The pipeline, from the source:
- Detect - your
bbox_detector(a YOLO, e.g.face_yolov8m.pt) runs over the image and finds faces. Only the first detected face is processed per run. - Crop and upscale - the face's crop region is cut out and scaled so its longest side is 1024px (multiples of 64), giving the model real resolution to work with.
- Segment - SAM (
sam_model) turns the detected box into a precise mask of the face. If you also connect asegm_detector, its detections add extra SAM input boxes and the resulting masks are unioned; SAM always produces the final mask. - Grid-ify - the mask is converted to 32px grid boxes on an 8px stride (that's the
thresholdinput - higher means a box must be more confidently inside the face). - Re-render - the crop and mask go to NovelAI's infill endpoint with your prompt, strength, sampler, steps, and CFG.
- Paste back - the inpaint result is downscaled to the original crop size and pasted directly over the crop region.
If no face is detected at all, the node returns your original image on both outputs and moves on. Results autosave under output/<date>/NAI_autosave/face/ with the NAI metadata preserved.
The inputs that matter
bbox_detectorandsam_model- the load-bearing ones, and the reason this node needs the Impact packs (see below).BBOX_DETECTORandSAM_MODELare Impact types; the detectors themselves (likeface_yolov8m.pt) come from Impact Subpack.prompt/negative_prompt- what you want the inpaint to do. Defaults aresmiling face, highly detailed/lowres, bad anatomy; tune for the expression you want.strength- inpainting denoise (default 0.55). Lower = closer to the original face.bbox_threshold- YOLO confidence;dilation- bbox padding in pixels;crop_factor- zoom around the face.- Optional:
segm_detector(additive extra SAM boxes),eye_bbox_detector(adds eye-region boxes to the mask - handy for fixing eyes specifically),limit_opus_free.
Two outputs: image (the composited result) and mask_visualization (a grayscale image of where it masked - genuinely useful for debugging seams).
Install
The pack via ComfyUI Manager (search ComfyUI_RS_NAI_API_Request) or clone into custom_nodes, then install requirements. But this node has two extra mandatory dependencies the other pack nodes don't:
# ComfyUI-Impact-Pack and ComfyUI-Impact-Subpack (both by ltdrdata)
# install through ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/ltdrdata/ComfyUI-Impact-Pack.git
git clone https://github.com/ltdrdata/ComfyUI-Impact-Subpack.git
The BBOX_DETECTOR and SAM_MODEL types come from Impact; the Subpack provides the bbox loading. You'll also need a YOLO detector file (e.g. face_yolov8m.pt) and a SAM checkpoint in place, and the token in .env (NAI_ACCESS_TOKEN=...) before any generation.
Gotchas
Only the first face is processed - a crowd of twelve becomes one fixed face. And every run is a cloud inpaint call, so it costs Anlas and your image leaves the machine; don't use it as a per-frame batch tool unless you enjoy bills. The mask_visualization output is there for a reason - if the seam shows, look at what it actually masked before blaming the node.
Inputs (28)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| bbox_detector | BBOX_DETECTOR | — | |
| sam_model | SAM_MODEL | — | |
| prompt | STRING | smiling face, highly detailed | — |
| negative_prompt | STRING | lowres, bad anatomy | — |
| model | COMBO | NAI Diffusion V5 Curated | 8 options: NAI Diffusion V5 Curated, NAI Diffusion V5 Full, NAI Diffusion V4.5 Curated, NAI Diffusion V4.5 Full, NAI Diffusion V4 Full, NAI Diffusion V4 Curated Preview, +2 |
| strength | FLOAT | 0.550–1 | — |
| threshold | FLOAT | 0.300–1 | — |
| sampler | COMBO | k_euler | 7 options: k_dpmpp_2m, k_dpmpp_sde, k_dpmpp_2m_sde, k_dpmpp_2s_ancestral, k_euler_ancestral, k_euler, +1 |
| steps | INT | 281–50 | — |
| cfg_scale | FLOAT | 6.00–30 | — |
| bbox_threshold | FLOAT | 0.500–1 | — |
| dilation | INT | 40–64 | — |
| crop_factor | FLOAT | 3.01–10 | — |
| scheduler | COMBO | karras | 4 options: native, karras, exponential, polyexponential |
| seed | INT | -1-1–4294967295 | — |
| segm_detectoropt | SEGM_DETECTOR | — | |
| eye_bbox_detectoropt | BBOX_DETECTOR | — | |
| limit_opus_freeopt | BOOLEAN | true | — |
| detail_modeopt | COMBO | first | 2 options: first, all |
| matching_modeopt | COMBO | shared | 2 options: shared, wd14 |
| characterPromptsopt | LIST | — | |
| taggeropt | RS_WD_TAGGER | — | |
| match_min_scoreopt | FLOAT | 0.250.01–1 | — |
| match_min_marginopt | FLOAT | 0.080.01–1 | — |
| match_crop_factoropt | FLOAT | 2.01–5 | — |
| max_regionsopt | INT | 161–64 | — |
| preview_onlyopt | BOOLEAN | false | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask_visualization | IMAGE | — |
| matching_report | STRING | — |