ComfyUI Node

Moisan Decomposition

Kill the cross in your FFT the mathematically honest way

By EdoardoGuerriero·Created 2 months ago·Updated 2 months ago· 0
Moisan Decomposition
  • image
  • periodic_u
  • smooth_v
strength1.00

Look at the FFT of almost any image and you'll see the same thing: a bright horizontal line and a bright vertical line crossing through the center, forming a cross. It's in every spectrum you've ever seen, and it's an artifact, not content. It comes from the image not being periodic - the left edge doesn't flow into the right edge, the top doesn't wrap to the bottom, and that discontinuity at the borders smears energy along the frequency axes. Every other node in ComfyUI-Spectral-Preprocessing-Nodes then has to work around that cross. This node is the one that removes it properly.

MoisanDecomposition is the newest addition to the pack - the most recent commit is literally "fixed bug in moisan decomposition" - and it's the node the README's older text doesn't even mention yet. It implements Moisan's periodic-plus-smooth decomposition, which is the correct, exact way to separate an image into:

  • periodic_u - the periodic component, with a spectrally clean FFT and no cross artifact.
  • smooth_v - the smooth boundary-discontinuity field, i.e. everything the non-periodicity injected.

The naive alternative you'll see in image-processing tutorials is just windowing (tapering the borders with a Hann window) to fake periodicity - which throws away real border content and blurs edges. Moisan's decomposition doesn't discard anything; it moves the discontinuity into a separate component you can discard or re-add. It's exact and deterministic, with no learned parameters.

How to use it

The source recommends this as the first node in any FFT preprocessing chain, precisely because every downstream node sees a cleaner spectrum without that cross contaminating their statistics. The only control is strength (default 1.0): at 1.0 the output is pure periodic_u, fully removing the cross artifact; below that it blends back toward the original image, partially subtracting the smooth component.

The two outputs are where it gets interesting:

  • periodic_u - wire this into the rest of your spectral chain.
  • smooth_v - keep it around. The documented recipe for a full pipeline is to process periodic_u with your other nodes and then add smooth_v back afterward:
result = SpectralNodes(periodic_u) + smooth_v

That way you get the clean-spectrum preprocessing and you don't lose the boundary information the decomposition set aside. If you just discard smooth_v entirely, expect a slight softening of what was at the image edges - usually fine, but worth knowing.

Installing it

Part of the single ComfyUI-Spectral-Preprocessing-Nodes pack. ComfyUI Manager (search "ComfyUI-Spectral-Preprocessing-Nodes") or:

cd ComfyUI/custom_nodes
git clone https://github.com/EdoardoGuerriero/ComfyUI-Spectral-Preprocessing-Nodes

Restart, and it appears under Spectral Preprocessing. Dependencies: numpy, scipy - both already in a standard ComfyUI install. Nothing to download.

Where people get burned

Two things trip people up. First, the FFT cross is so universal that beginners see it in the FFT Spectrum Visualizer and panic - but here's the thing, it's also what the cross in any spectral analysis looks like on a healthy image. This node is the cure for that specific, universal artifact, which is why the pack is honest that it should sit first in the chain. Second, if you wire periodic_u through your whole pipeline and then don't re-add smooth_v, you may chase a subtle edge-softening that's actually the missing smooth component, not a tuning problem. Keep that second output, do the recombination at the end, and the rest of the pack's nodes get to work on a spectrum that's finally clean.

CategorySpectral Preprocessing

Inputs (2)

NameTypeDefaultDescription
imageIMAGEInput image to decompose.
strengthFLOAT1.000–11.0 = output pure periodic component u (fully removes cross artifact). 0.0 = output original image unchanged. Values between 0 and 1 partially subtract the smooth component.

Outputs (2)

NameTypeDescription
periodic_uIMAGE
smooth_vIMAGE