ComfyUI Node

Similarity PM

Does this face still look like the reference? Similarity PM tells you

By THtianhao·Created 3 years ago·Updated 2 years ago· 202
Similarity PM
  • main_image
  • compare_image
  • STRING
model
result_prefix

"How close is this face to the reference?" is the question every identity workflow needs answered, and for once there's a node that answers it in numbers. Similarity PM compares two images, computes a face-recognition score, and hands it back as a string you can actually read. It's the quality gate of the ComfyUI-Portrait-Maker pack - the tool that tells you whether the face that came out of your pipeline still resembles the person you fed in, or whether you need to re-roll.

In the broader identity-preservation landscape this is the "verification" half of the story: IP-Adapter, FaceID, InstantID and friends are the generative side that produces a face, and this node is the check that grades the result. EasyPhoto's underlying pipeline uses exactly this trick - generate candidates, keep the ones whose recognition score clears the bar.

How it works

No diffusion involved. The node pulls up a ModelScope face-recognition pipeline (bubbliiiing/cv_retinafce_recognition) - a RetinaFace-detector-plus-recognizer - and extracts an identity embedding from each image. That embedding is an ArcFace-style vector encoding facial geometry rather than appearance, the same family of representation that InsightFace and every no-training identity tool use. The score is then the plain dot product of the two embeddings:

score = np.dot(embedding_main, embedding_compare)

Higher means more similar. It's rounded to two decimal places and returned as a string.

Inputs and output

  • main_image (IMAGE) - your reference, the person you want the result to match.
  • compare_image (IMAGE) - the candidate you're grading.
  • model (enum) - currently only "sim" exists, so this dropdown is decorative. It's there for future model options.
  • result_prefix (STRING, default "") - a prefix glued onto the output, so you can tell scores apart when you're comparing several candidates.

Output is a STRING: either "0.87" or "prefix_0.87" if you set a prefix. It's a leaf node for your eyes - there's no fancy gauge, you just read the number. If you want to compare a batch, set a distinct prefix per candidate and run them.

How to read the number

Two things people trip on. First, the score is a raw dot product, not a percentage - it can exceed 1, and the "perfect match" value depends on the model, so don't treat 0.9 as "90%." Use it comparatively: candidate A at 0.82 beats candidate B at 0.71. Second, feed it face crops, not full scenes. A group photo or a subject surrounded by clutter muddies the embedding; both images should be roughly the same face region, which is exactly what PM_RetinaFace's crop_image output is for.

Installing

ComfyUI Manager (search "ComfyUI-Portrait-Maker") or clone:

cd ComfyUI/custom_nodes
git clone https://github.com/THtianhao/ComfyUI-Portrait-Maker.git

then restart. The usual pack baggage applies: first launch downloads the full EasyPhoto model set, and requirements.txt brings in modelscope, tensorflow, onnxruntime, insightface and diffusers==0.18.2. The recognition weights themselves download from ModelScope on first run of the node, so the first execution can stall on a download - be patient, or run behind a proxy if you're outside China.

Common issues

Mostly: wrong inputs. Using full photos instead of crops, or comparing a face to an image that doesn't contain a clear face, gives you junk scores that mean nothing. If the node errors about face detection, one of your images genuinely doesn't have a detectable face in it. There's no visualization here, so keep a PreviewImage on your crops to confirm what you're actually feeding in.

Categoryprotrait/model

Inputs (4)

NameTypeDefaultDescription
main_imageIMAGE
compare_imageIMAGE
modelCOMBO1 options: sim
result_prefixSTRING

Outputs (1)

NameTypeDescription
STRINGSTRING