ComfyUI Node

Dino_Score

The 'do these two images show the same thing' number

By wu12023·Created 2 years ago·Updated 2 years ago· 9
Dino_Score
  • Source_Image
  • Target_Image
  • Dino_Score

CLIP answers "does the image match the prompt?" but it's a lousy judge of whether two images show the same thing. That's Dino_Score's lane. It takes a Source_Image and a Target_Image, runs both through a DINO vision transformer, and returns one number: how similar the two images are at the object-and-content level, as a cosine similarity between 0 and 1.

Why you'd reach for it: identity and consistency checks. After you've edited a character into a new pose, reframed a scene, or run an img2img pass, you want to know "did the core subject survive?" That's exactly what DINO - self-supervised, never trained on captions - learned to encode. It's the same trick people use for local image-search apps: embed everything, then rank by cosine similarity.

How it works

The node loads facebook/dino-vits16 (DINO v1, the ViT-S/16 checkpoint) from Hugging Face, resizes each image to 256 with a bicubic-ish resize, center-crops to 224, applies the standard ImageNet normalization, and pushes both through the model under torch.no_grad(). Then it takes the cosine similarity of the two [CLS] tokens - last_hidden_state[0, 0] - and returns the result as a string.

One thing worth knowing: this is a hand-rolled cosine similarity, not torchmetrics' DINOImageSimilarity. Which is fine for what it does, it just means the number is your own reference point rather than a calibrated benchmark score. And it's DINO v1, not the newer DINOv2 - the embeddings are older and a bit less refined, but perfectly usable for "same subject?" checks.

The inputs (all of them)

The whole input side is just two image slots:

  • Source_Image - your generated or edited image.
  • Target_Image - the reference.

There's exactly one output, Dino_Score, a STRING - the cosine similarity as text, roughly 0.0 to 1.0 (higher = more similar). Since it's a string, a comparison or expression node has to parse it before it can branch on it. A common pattern is to run several candidate generations against the same reference, collect the scores, and pick the highest - a poor-man's selection loop before you even look at the images.

Installation

Same pack as its sibling, Clip_Score:

cd ComfyUI/custom_nodes
git clone https://github.com/wu12023/ComfyUI-Image-Evaluation
cd ComfyUI-Image-Evaluation
pip install -r requirements.txt

Restart ComfyUI (or search ComfyUI-Image-Evaluation in ComfyUI Manager). The only extra Python dependency is torchmetrics; the rest rides on stock ComfyUI. The first run downloads facebook/dino-vits16 from Hugging Face - a ~90MB checkpoint, so the first execution hangs a beat while it pulls.

Gotchas

The same model-caching flaw from Clip_Score applies here, harder: prepare_model() is called inside execute(), so the node re-loads the DINO checkpoint from disk on every single run. On a big batch sweep that's measurable overhead, and there's no setting to avoid it. Worth knowing before you chain it across 200 images.

Also keep the semantics straight: DINO similarity responds to the subject matter of an image - object identity, layout, content - not photographic quality, lighting, or style the way a photorealistic judge would. Two renders of the same car in different lighting will score high; two renders of the same lighting with different cars will not. If that matches what you're testing, great. If you wanted style similarity, CLIP or a perceptual metric is the better tool.

CategoryImage_Evaluation

Inputs (2)

NameTypeDefaultDescription
Source_ImageIMAGE
Target_ImageIMAGE

Outputs (1)

NameTypeDescription
Dino_ScoreSTRING