ComfyUI Node

Face Filter

Sort your images by 'does this contain the person I want?'

By Kidev·Created 11 months ago·Updated 11 months ago· 2
Face Filter
  • ref_images
  • candidate_images
  • MATCHING
  • REJECTED
  • DEBUG
threshold0.30
on_empty_matching
on_empty_rejected
debugfalse
model_name
providers
detector_size256
resize_mode

The name sounds like a beauty filter, but FaceFilterNode is actually a bouncer. Feed it a batch of candidate images plus a few reference photos of a person, and it splits the batch into MATCHING and REJECTED based on whether each image contains a face resembling one of your references. No training, no LoRA, no API key. It just tells people apart and sorts them.

Why you'd reach for it: the flagship job is gating a face swap. The pack's example workflows (FaceFilter-Faceswap.json, FaceFilter-Faceswap-Video.json) wire this node in front of ReActor so that only frames containing the target person get swapped, and everyone else passes through untouched. No indices, no per-frame masks, no "which person is at position X" guessing - identity only. It's just as good for dataset triage: you've got a thousand scraped images and you want only the ones with person A in them. And in a video pipeline it doubles as a frame selector - feed it extracted frames and you get back just the shots of your subject.

How it works, the short version: it uses InsightFace - the same ArcFace backbone underneath IP-Adapter FaceID, InstantID, PuLID, and ReActor - to detect faces and turn each one into an embedding: a vector that encodes facial geometry rather than appearance. Each reference image contributes one or more embeddings, they get L2-normalized, and every candidate's face is compared against the whole reference set by cosine similarity. Accept if any reference clears your threshold. A candidate with no detectable face at all goes straight to REJECTED.

The inputs that actually matter:

  • ref_images - the identity set. Any face matching any of these passes.
  • candidate_images - what you're filtering.
  • threshold (default 0.30) - how strict. In cosine-similarity terms 0.3 is lenient, 0.5 is "same person, good lighting" territory. Tune it; the right value depends on your model pack and your people.
  • on_empty_matching / on_empty_rejected - what happens when a side comes up empty: black_512 (a single 512px black frame, keeps downstream graphs valid), return_empty, or pass_through (first frame). The pack's examples use black_512 on both, then let the sibling MergeImageBatches node fill the black slots with originals.
  • debug - flips the third output, DEBUG, into a multi-line dump of face counts and best-similarity scores per image. Turn it on while tuning, off once it's working.

Everything else you can leave alone. model_name is auto-discovered from your installed packs, providers=auto(cuda+cpu) is right on a CUDA machine, detector_size defaults to 256 (the README's recommended balance between speed and recall), and resize_mode just decides how images are scaled before detection.

Outputs: MATCHING (IMAGE), REJECTED (IMAGE), DEBUG (STRING).

Install and the model trap. Install via ComfyUI Manager (search "ComfyUI-FaceFilter"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/Kidev/ComfyUI-FaceFilter.git
pip install -r ComfyUI-FaceFilter/requirements.txt

That pulls insightface, onnxruntime-gpu, opencv-python, and numpy - the infamous InsightFace install, which used to mean Visual Studio build tools on Windows but has been painless since the 1.0 release dropped the C++ requirement.

Then the model pack, which is where people get burned. The node reads packs from ~/.insightface/models/<pack> or <repo>/models/insightface/<pack>. Its default, antelopev2, is not auto-downloaded by InsightFace - you have to fetch it from a Google Drive link and unzip it into one of those paths. (buffalo_l is the one InsightFace downloads itself.) Miss this step and the node either errors on first run or quietly rejects everything because there's nothing to compare against. The README's python install.py helper only creates the two folder paths so you know where to drop the pack; it downloads nothing.

Two things worth knowing beyond the README. First, InsightFace's model weights are non-commercial - fine for personal and portfolio work, not fine for anything you plan to sell. Second, this node does recognition only. It will confidently tell you whether two faces are the same person, but it won't generate or swap anything on its own. Pair it with ReActor for the actual pixel swap, or with an IP-Adapter FaceID branch if you want a generative take on the same identity.

Categoryimage/face

Inputs (10)

NameTypeDefaultDescription
ref_imagesIMAGE
candidate_imagesIMAGE
thresholdFLOAT0.300–1
on_empty_matchingCOMBO3 options: black_512, return_empty, pass_through
on_empty_rejectedCOMBO3 options: black_512, return_empty, pass_through
debugBOOLEANfalse
model_nameCOMBO1 options: antelopev2
providersCOMBO2 options: auto(cuda+cpu), cpu_only
detector_sizeINT25632–2048
resize_modeCOMBO2 options: fit_min_side, fit_longest_side

Outputs (3)

NameTypeDescription
MATCHINGIMAGE
REJECTEDIMAGE
DEBUGSTRING