pyiqa NR Score
Rate a picture with nothing to compare it against
- model
- image
- score
No-reference scoring is the version of image quality that works on pictures you didn't shoot. You have 300 generated images, no originals, no ground truth - just a folder and a nagging feeling that a third of them are mush. An NR metric looks at each one alone and hands back a number. It's the only kind of scoring that works when the image is the only thing you have.
This node is the generic NR scorer for the whole pyiqa registry: pick the metric on (Down)load pyiqa Model, wire it in here, get per-image floats.
The three inputs
image takes the batch and scores it per image - no resizing widget, no crop setting, the node adapts the picture to what the architecture needs and scores it. model comes from the loader and must be a variant labelled NR; an FR variant gets refused with a message pointing at the node that would have taken it.
memory_management is the one worth understanding. Default is unload model (VRAM + RAM): after scoring, the metric is gone, next score reloads it from disk. On a small metric that reload is a second or two; on Q-ReAlign Pro it's closer to thirty. keep loaded keeps it on the GPU for fast re-scoring. The trap is multiple score nodes sharing one loader - if each one unloads, you're reloading between them. Set keep loaded on all but the last, or drop a single Unload Pyiqa Models at the end of the graph.
Output is one score socket, emitted as a list, so a scalar consumer downstream runs once per image.
Which metric, though
The honest answer: pyiqa ships a hundred of them because they disagree, and no single one is "correct". What you should actually do is pick one and never change it mid-project, because these numbers are only comparable within the same metric.
Good places to start, all reachable from the loader's variant list:
- TOPIQ (CFANet) - solid general quality,
~0-1higher better, FR and NR variants. The pack author's first recommendation. - MUSIQ - trained on AVA, has a 1-10 aesthetic-ish head and
~0-100quality heads. Widely used, older, still fine. - CLIP-IQA / QualiCLIP - 0-1, higher better, cheap and stable.
- LAION Aesthetic -
~1-10, and this is the taste metric: the same lineage as the aesthetic predictor that picked LAION-Aesthetics out of LAION-5B, i.e. a small model trained to predict how much humans would like a picture. That's why the number feels like a vibe score rather than a quality score. - ARNIQA - one regressor per training set (KonIQ-10k, LIVE, CSIQ, TID2013…). Same model, several different opinions.
Two rules that save you from bad conclusions. First, read the label for direction - MUSIQ AVA is 1-10 and higher-better, A-FINE NR is lower-better and runs ~-2..2, and CLIP-IQA is 0-1. Never compare a 0.71 from one metric to a 0.71 from another. Second, these models mostly learned from distortion datasets (blur, noise, JPEG), so they reward sharpness and bite. A slightly over-sharpened, grainy image will often outscore a clean soft one. If your taste says otherwise, trust your taste.
Where it actually earns its keep
Culling. Run a batch through NR score, sort, look at the bottom ten instead of all three hundred. It's also how you sanity-check a LoRA across checkpoints without opening an image viewer - score the same prompts at step 500, 1000, 2000 and see whether the curve goes anywhere. Flawed metric, useful signal, and much faster than a compare slider.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/AnsteinHuynh/ComfyUI-pyiqa-toolbox
python -m pip install -r ComfyUI-pyiqa-toolbox/requirements.txt
Or ComfyUI Manager → search pyiqa-toolbox. Restart, then look under pyiqa/Generic. There's a ready-made NR example under Workflow → Browse Templates → ComfyUI-pyiqa-toolbox if you'd rather start from a working graph.
Weights download on first score into ComfyUI/models/pyiqa. Be aware the install also resolves transformers>=5 through pyiqa - that's the known ComfyUI dependency hazard, and it's not specific to this pack.
Common issues
"This model is FR" style refusal. You wired a full-reference variant into the NR node. Swap the variant on the loader or use pyiqa FR Score.
Scores clustered suspiciously tight. Normal for many NR metrics on generated images - they were trained on camera distortions, not diffusion artifacts. Try a different architecture before concluding your images are all equally good.
Unwired score nodes still load their model. ComfyUI runs nodes whose outputs nothing consumes, so a score node sitting unused on the canvas is still doing work. Delete or bypass it.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| model | PYIQA_ANY | From the matching Loader node. This input (and the loader feeding it) is evaluated LAZILY - only once this node's image inputs exist - so a generation-only run never loads the metric model. | |
| image | IMAGE | Image(s) to score; batch is scored per-image. Lazy: the generator/decoder feeding this runs before the metric model is loaded. | |
| memory_management | COMBO | unload model (VRAM + RAM) | What happens to this metric after it scores. 'unload model (VRAM + RAM)': the metric is fully unloaded - gone from VRAM and RAM, only the file on disk remains; the next score reloads it (seconds for small models, ~30s for Q-ReAlign Pro). Re-queueing just works: a previously-unloaded model handed back by ComfyUI's output cache is rebuilt transparently. 'keep loaded': stays on the GPU, fastest to re-score, holds its VRAM between runs. With several score nodes sharing one loader, unload only on the LAST one - earlier nodes should 'keep loaded' or you pay a reload between them. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| score | FLOAT | Per-image quality score computed by the selected registry metric. Higher- or lower-better depends on the metric (the variant label says which). |