Radial Avg Amplitude Spectrum
The node that graphs your image's frequency content — a blur and artifact detector you didn't know you needed
- image
- spectrum_image
What it actually is
Radial Avg Amplitude Spectrum is a one-trick analysis node: feed it any image and it hands you back a matplotlib plot of that image's radial average amplitude spectrum - a 1D curve showing how much energy sits at each spatial frequency, drawn on a log-log axis. If that sounds like a lab instrument living inside your node graph, it kind of is.
It's the ComfyUI-native way to produce the FFT plots people post when comparing models - you've seen the "FFT analysis of artifacts" threads where someone shows model A has a clean spectrum and model B has diagonal spikes in the hair. This is that curve, without leaving ComfyUI.
The name is honest in one direction and a lie in another: it calls no API, downloads no model, and doesn't even need the GPU. But it's also not a magic "is my image good" meter. It's a diagnostic - and a pretty niche one at that.
Why you'd reach for it
The real use cases are the boring, useful ones:
- Is that output actually soft, or am I imagining it? A smooth, low-frequency-dominant image shows a steeply negative slope. A flat or slowly decaying curve means lots of high-frequency content - sharp edges, fine texture, or straight-up noise. One look at the slope settles it.
- Comparing upscalers or checkpoints. Run the same source through two upscalers and stack the plots. The one that preserves high-frequency energy out to a larger radius is adding real detail rather than just smoothing - a more objective take than eyeballing two 4x outputs side by side.
- Checking a hires-fix or denoise pass for introduced artifacts, in the same spirit as the community's artifact-via-FFT debugging.
When you're stuck on "why does everything I generate look mushy," a single curve can settle an argument faster than a screenshot comparison. And when you're not stuck, you'll forget this node exists. That's okay.
How it works
Standard signal processing, and the code is short enough to read in one sitting. It converts the image to grayscale with Rec. 709 luminance weights (0.2126 R + 0.7152 G + 0.0722 B), runs a 2D FFT, shifts the DC component to the center, takes the magnitude |FFT|, then averages all amplitudes at each integer radial distance from center. The DC bin (frequency 0) is dropped so log scaling doesn't blow up, and non-positive values are floored to 1e-12. Matplotlib (backend forced to Agg, so it's safe headless) renders the curve, the PNG is resized to your requested plot size, and it comes back as a normal IMAGE tensor.
The inputs that matter
Only one input carries content: image, any IMAGE tensor, RGB or grayscale, any resolution. It'll also process each frame of a batch and return one plot per frame.
The rest are cosmetics:
log_x/log_y(both defaulttrue) - log axes are basically always what you want for a spectrum. Leave them on.line_color(defaultred) - a matplotlib color string, and a quiet trap: it isn't validated, so a typo or a name matplotlib doesn't know raises an error at runtime. Stick to "red", "blue", or a hex like#ff8800.plot_width/plot_height(default 512, range 256–2048, step 64) - output plot resolution.
The single output, spectrum_image (IMAGE), wires into any preview or Save Image node. One honest catch: the output is a picture of a graph, not the numbers. If you want the raw data for further analysis, this node won't hand it to you - the values live and die inside the plot.
Installing it
Via ComfyUI Manager, search for "Radial Average Amplitude Spectrum". Or clone it straight in:
cd ComfyUI/custom_nodes
git clone https://github.com/bemoregt/ComfyUI_RadialAverageAmplitudeSpectrum.git
Then restart ComfyUI - the node appears under the analysis category. No model files, no requirements.txt, no extra pip installs: it only uses numpy, matplotlib, Pillow, and torch, all of which a standard ComfyUI install already ships. It's MIT licensed.
Common issues
- Invalid
line_coloris the most likely runtime failure, for the reason above. - Slow on big inputs. Everything runs on CPU via
img.cpu().numpy(), so a 4K image takes a moment. Not a bug, just physics - downsample if it's painful. - The README's clone URL literally says
your-repo, a copy-paste leftover. Use the real URL above, and don't copy the README's install snippet verbatim.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| plot_width | INT | 512256–2048 | — |
| plot_height | INT | 512256–2048 | — |
| line_color | STRING | red | — |
| log_x | BOOLEAN | true | — |
| log_y | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| spectrum_image | IMAGE | — |