FaceCompare
The tiny 'is this the same face?' node — and why its score can lie
- image1
- image2
- scores
Most face tooling in ComfyUI exists to generate faces - IP-Adapter FaceID, InstantID, PuLID, the whole identity-preservation shelf. FaceCompare is the opposite animal: it does nothing but ask "are these the same person?" and hand you a number. You feed it two images, it compares the faces, and a scores output tells you how close they are. That's the entire pack - one node, one dependency, one job.
Why you'd reach for it
It's a QA and selection node, not a generator. Say you batch twenty generations of the same character and want to keep the one that actually looks like the reference: wire the reference into image1, your candidates into image2, and read the scores. Same idea if you're building a consistency loop and want a pass/fail gate before an image moves downstream. Worth being honest about the division of labor, though: if your goal is "make the face match," this is the measurement end of the pipeline, not the thing doing the matching. Pair it with an identity adapter and use it to check their work.
How the score actually works
Under the hood it's the face_recognition Python package - dlib wearing a friendlier API. For each input image it detects a face (HOG detector), aligns it, and runs it through dlib's ResNet embedding to get a 128-number vector. Then it compares vectors with Euclidean distance. That's the same "embed, then measure distance" pattern ArcFace/InsightFace uses everywhere else in this space, just with dlib's older, permissively-licensed stack (Boost/MIT) instead of the non-commercial ArcFace models. Bonus: no model files to download. The ResNet weights ship inside the pip package, so there's no "download this .dat to the models folder" step at all.
Here's the part that trips people: scores is a distance, not a similarity. Smaller is better. Below roughly 0.6 = same person (the classic face_recognition cutoff), 0.3 or under = very close, above ~0.6 = different people. The node is named "FaceCompare" and calls its output "scores," so your instinct will be that higher means more alike. It means the opposite, and the node doesn't invert it for you.
The inputs that matter
image1 and image2 are plain IMAGE tensors - from Load Image or anything else that outputs IMAGE. The only thing you actually set is process:
all- every face inimage1is compared against every face inimage2. Output is a list of lists (one inner list perimage1entry).first- only the first image of each batch gets used, and the output is a flat list. This is the "just give me one number" mode.
Output is scores, a FLOAT list. It wires into whatever consumes floats - a text/display node if you just want to read it, or logic further down a workflow if you're gating on the result.
Install
ComfyUI Manager has it - search for "Face Compare" (the pack is czcz1024/Comfyui-FaceCompare). Or do it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/czcz1024/Comfyui-FaceCompare
Then restart ComfyUI. The real install pain is the dependency: requirements.txt is only numpy and face_recognition, but face_recognition drags in dlib, and dlib often builds from source. That means CMake and a C++ compiler, and the recurring community complaint is pip picking up a broken CMake and the build failing silently mid-install - the same failure mode that plagues InsightFace installs. On Windows, a prebuilt dlib wheel for your Python version usually saves you; on Linux you may need sudo apt install cmake g++ first. If Manager misses it, run pip install -r requirements.txt inside the node folder.
Gotchas worth knowing
The source is about 65 lines, and its edges are visible. Only the first detected face per image is compared - multi-face scenes silently ignore everyone but index 0. It's CPU-only and not fast, a chunk of a second per face. And the no-face fallback is a lie in disguise: if detection finds nothing, the node returns 1.0, which reads as "definitely different people" even though no comparison happened. It's a sentinel, not a measurement - if you see a 1.0, check the input for an actual face before trusting it.
Small pack from a small author, zero community footprint, and one dependency that's awkward to install. But for a zero-model-download "is this the same person?" check in the middle of a workflow, it does the job - as long as you remember which end of 0.6 is good.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image1 | IMAGE | — | |
| image2 | IMAGE | — | |
| process | COMBO | 2 options: all, first |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| scores | FLOAT | — |