Dino_Score
The 'do these two images show the same thing' number
- 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.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| Source_Image | IMAGE | — | |
| Target_Image | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| Dino_Score | STRING | — |