ComfyUI Node

Probe (C2C)

Why is your generation black? Image Stats Probe (C2C) tells you in one run

By Code2Collapse·Created 8 months ago·Updated about 23 hours ago· 58
Probe (C2C)
  • images
  • mask
  • latent
  • images
  • report
  • mean
  • std
  • bright_pct
  • mask
  • coverage_mean_pct
  • coverage_min_pct
  • coverage_max_pct
  • latent
  • info_json
  • verdict
  • nan_count
  • inf_count
◄threshold0.50►
◄fail_on_corruptfalse►

Image Stats Probe (C2C) is a diagnostic that answers the most annoying question in ComfyUI: is my output actually broken, or am I imagining it? You get a black frame back, or everything's blown out white, and you can't tell whether the sampler failed, the VAE misbehaved, or the tensor is fine and just needs a different preview. This node sits in the middle of your graph, passes the image through untouched, and prints what it actually is: shape, dtype, mean, std, min, max, and the percentage of pixels brighter than 0.95.

It's one of the small utility nodes in ComfyUI-CustomNodePacks, the ~72-node umbrella pack from Code2Collapse (Likhith-24, active on r/comfyui). The C2C Helpers category is the author's own toolbox for debugging workflows - and honestly, this is the one you'll keep wired in out of laziness, because it costs nothing and saves you a lot of staring.

How it works

Pure tensor math, zero models, zero VRAM. It computes:

  • mean - if your "image" has a mean of 0.0001, it's black. A mean of 1.0, it's white. A mean around 0.5 with high std, it's a real image.
  • std - the giveaway. A low std (like 0.01) means there's no contrast anywhere; something upstream collapsed the dynamic range.
  • min/max - tells you if you're clipped. If min is exactly 0 or max exactly 1, you've lost data at one end.
  • bright_pct - the share of pixels above 0.95, as a float. Over 50% and your highlights are toast.

The report string is human-readable for the log; the separate mean, std, and bright_pct outputs are real numbers you can wire into routing logic - e.g. a Switch that picks a different path when mean drops below a threshold. And because it's a passthrough (images in → images out unchanged), you can drop it anywhere without breaking the graph.

The inputs and outputs that matter

  • images - in and out. Only input, and it comes back identical on the first output.
  • report (STRING) - the whole story in one line, logged to the console too.
  • mean / std / bright_pct (FLOAT) - the numbers, if you want to act on them.

Installing it

This ships with ComfyUI-CustomNodePacks - there's no separate repo. Manager → search "CustomNodePacks", or:

cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git

It needs nothing beyond what ComfyUI already has (it's a torch mean/std on a tensor). The pack as a whole wants opencv-python>=4.7.0 and scipy>=1.10.0 - install just those if missing, not the full requirements.txt, which can clobber ComfyUI's torch. Restart ComfyUI.

Common issues

  • The node reports a shape that's not what you expected - that's the whole point. If shape=(1, 8, 64, 64) where you expected a big RGB image, you're feeding it a latent, not an image. That's your bug, found in seconds.
  • Mean is fine but the output still looks wrong - mean/std are global; they won't catch a region-specific problem. For that you'd want a per-region check, but this node is the right first probe to rule out the whole-frame failure modes.
  • Bright_pct hovering near 100% - you're clipped. Fix the upstream exposure/gain before wasting a sampler run.

The honest verdict: it's a boring node that does one trivial thing, and that's exactly why you'll keep it. When something's broken, a number beats a vibe.

Category🐺 C2C/🧰 Core/Helpers

Inputs (5)

NameTypeDefaultDescription
imagesoptIMAGE—
maskoptMASK—
latentoptLATENTComfyUI LATENT dict (must contain 'samples').
thresholdoptFLOAT0.500–1Mask: a pixel counts as covered above this value.
fail_on_corruptoptBOOLEANfalseLatent: stop the run when it holds NaN or Inf.

Outputs (14)

NameTypeDescription
imagesIMAGEThe image, unchanged.
reportSTRINGOne line per wired input (image stats, mask coverage, latent verdict).
meanFLOATImage mean (0 when no image is wired).
stdFLOATImage standard deviation.
bright_pctFLOATPercent of image pixels brighter than 0.95.
maskMASKThe mask, unchanged.
coverage_mean_pctFLOATMean per-frame mask coverage in percent (pixels above threshold).
coverage_min_pctFLOATLowest per-frame coverage in percent.
coverage_max_pctFLOATHighest per-frame coverage in percent.
latentLATENTThe latent, unchanged.
info_jsonSTRINGLatent shape, dtype, per-channel stats, NaN / Inf counts and verdict as JSON.
verdictSTRINGLatent verdict: healthy / low_contrast / saturated / corrupt.
nan_countINTNaN elements in the latent.
inf_countINTInf elements in the latent.