ComfyUI Node

pyiqa NR Score

Rate a picture with nothing to compare it against

By AnsteinHuynh·Created 7 days ago·Updated 6 days ago· 0
pyiqa NR Score
  • model
  • image
  • score
◄memory_managementunload model (VRAM + RAM)►

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-1 higher better, FR and NR variants. The pack author's first recommendation.
  • MUSIQ - trained on AVA, has a 1-10 aesthetic-ish head and ~0-100 quality 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.

Categorypyiqa/Generic

Inputs (3)

NameTypeDefaultDescription
modelPYIQA_ANYFrom 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.
imageIMAGEImage(s) to score; batch is scored per-image. Lazy: the generator/decoder feeding this runs before the metric model is loaded.
memory_managementCOMBOunload 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)

NameTypeDescription
scoreFLOATPer-image quality score computed by the selected registry metric. Higher- or lower-better depends on the metric (the variant label says which).