Nodes/BrainDead Nodes/BD Compare Images
ComfyUI Node

BD Compare Images

Stop eyeballing whether your rebuild actually matches

By BizaNator·Created 9 months ago·Updated 21 days ago· 15
BD Compare Images
  • reference
  • candidate
  • region
  • difference
  • side_by_side
  • score
◄gain3.0►
◄threshold40►
◄label►

What it's for

You spent a while chopping a character head into layers, rebuilt it, and it looks fine. "Looks fine" is not a measurement, and the whole BrainDead head chain - layers, plates, engine stack - is only worth anything if the rebuild is faithful to the source it came from. This node is the yardstick.

Give it a reference and a candidate and you get three things back: a red-zone heat image, a labelled three-panel comparison, and a score string with actual numbers in it. Feed it the visible-layer composite against the original headshot, or the assembled engine stack against the plate source, and it will tell you the rebuild is 4.2 levels off on average with 3% of the region more than 40 levels out. That is a sentence you can act on.

It also fits the rule the whole deterministic pixel-op layer exists for: measure with a lookup table, not another diffusion pass. A diff costs milliseconds and has no seed. Our KB's post-processing doc makes the same argument at length - pick the cheap deterministic primitive before the expensive generative one.

Honest caveat, because it matters when you're judging: this is a plain per-pixel mean absolute difference over RGB. There's no SSIM, no LPIPS, no perceptual weighting. It's excellent at "this layer is the wrong colour or 30 levels too dark" and blunt about "this layer is structurally wrong but locally close".

How it works

Both images are converted to uint8. A candidate with an alpha channel is composited over white first, so RGBA plates compare against flat source images cleanly. If the candidate is a different size it gets resampled to the reference - quietly, which is worth remembering (see the traps below).

The difference is mean(|reference - candidate|) across RGB, in 0–255 levels. The heat image puts difference × gain into the red channel and tints the measured region teal, so you see both how far off and where you're measuring. The score is JSON: diff_on_region, share_over_40, region_px, max_diff.

The inputs and outputs that matter

  • reference - what the candidate should reproduce.
  • candidate - the result being judged.
  • gain (default 3, 0.5–20) - cosmetic. The author's own note: at gain 3, 85 levels off is full red. It changes the picture, not the score.
  • threshold (default 40) - how many levels off counts as "off" for the share figure.
  • region (optional MASK) - where to measure. Leave it empty and you measure every pixel that isn't white in either image, which is a decent head shot on a white background.
  • label (optional) - printed on the panel so your saved comparisons are self-describing.

Outputs are difference (IMAGE), side_by_side (IMAGE, reference | candidate | difference with the score line underneath), and score (STRING). Wire the images to a Preview or Save Image and the score to Preview Any, or save it next to the PSD so you keep the number with the asset.

Installing it

ComfyUI Manager → search "BrainDead" → install → restart. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/BizaNator/ComfyUI-BrainDead
cd ComfyUI-BrainDead && pip install -r requirements.txt

This is a ~110-node pack built on ComfyUI's V3 node API, so you want a reasonably current ComfyUI. The pack's requirements.txt pulls git-sourced deps (MoGe, utils3d, natten) for its image-to-3D nodes - none of that is needed for Compare Images, but it does have to install before the pack imports.

Where people get burned

Different sizes get resized, not flagged. A 2048 plate compared against a 1024 source is downscaled to 1024 before measurement, so a scale error scores better than it should. Normalise size upstream if scale correctness is what you're checking.

The default region isn't stable across odd inputs. If your candidate was cut onto white and the reference wasn't (or worse, both are mostly white), the implicit "not white in either image" region shrinks or moves and the numbers won't compare run to run. Wire a real mask - the Plates matte, or a head mask - and your scores become a series instead of one-off vibes.

Threshold 40 is tuned for this pipeline's hard-edged low-poly renders. On photographic or noisy input the noise floor alone will push the share number up. Raising threshold isn't cheating, it's calibration.

A geometrically shifted layer reads as catastrophic. Two pixels of hair offset scores terribly against a plain L1 diff even though a human wouldn't notice. That's the metric being honest about a different question than the one you asked: it measures fidelity, not quality.

Category🧠BrainDead/Segmentation

Inputs (6)

NameTypeDefaultDescription
referenceIMAGEWhat the candidate should reproduce.
candidateIMAGEThe result being judged.
gainFLOAT3.00.5–20Red = difference x gain (3: 85 levels off is full red).
thresholdINT401–255Levels off that count as 'off' in the score.
regionoptMASKWhere to measure (1 = measure). None: pixels that are not white in either image.
labeloptSTRINGShown on the side_by_side panel.

Outputs (3)

NameTypeDescription
differenceIMAGE—
side_by_sideIMAGE—
scoreSTRING—