Fourier Domain Adaptation (FDA)
Steal Any Image's Color Grade in One Node (Without Redrawing It)
- target_image
- reference_image
- adapted_image
Want your generation to carry the exact color mood of a reference photo - golden-hour warmth, cold clinical grade, that faded film palette - without re-running the sampler? That's the whole job of Fourier Domain Adaptation (FDA). It's a post-processing node that transplants the global color and tone of one image into another while leaving the structure (edges, shapes, detail) of the target completely alone. Structure stays, color goes.
Where it fits: the very end of your workflow. Pipe your finished image into target_image, feed a photo whose look you covet into reference_image, and out comes your image wearing the reference's colors. People reach for it to unify a batch of outputs to a single grade, to make an inpainted or outpainted patch sit in the same light as the rest of the frame, or to nudge a render toward a real photo's palette. It's a one-trick node, but the trick is genuinely useful - closer to the color-correction bag in WAS Node Suite than to something like IPAdapter, which reshapes the whole generation. FDA only changes color statistics, and only global ones.
How it actually works
The name is scarier than the math. The node FFTs each channel of both images (a Fourier transform - the image as a map of frequencies), then splits each spectrum into amplitude and phase. Here's the insight from the paper this is based on (Yang & Soatto, FDA: Fourier Domain Adaptation for Semantic Segmentation, CVPR 2020): phase carries structure, amplitude carries color and tone statistics. So FDA takes the target's phase - its shape - and splices in the reference's low-frequency amplitude - its broad color. Inverse FFT, done.
You never touch any of that, obviously. It's one node with three inputs, and the only one you'll actually fiddle with is beta, the size of that low-frequency window as a fraction of the image dimensions. The default, 0.01, is subtle: a whisper of the reference's tone. Around 0.05–0.2 the palette gets properly reshaped, and past 0.2 you're asking for visible artifacts, because you're replacing more of the spectrum than "color" actually occupies.
The inputs (that's all there is)
- target_image - the one whose structure you keep. That's your generated image.
- reference_image - the one whose colors you borrow.
- beta - the dial above: FLOAT,
0.001–0.5, default0.01. Move it in0.01steps; there's a big gap between "subtle" and "the reference's palette smeared over everything."
The single output, adapted_image (an IMAGE tensor), wires straight into a Save Image or a VAE decode. Same dimensions and batch size as the target.
Installing it
ComfyUI Manager: search "ComfyUI_FourierDomainAdaptation", install, restart. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/bemoregt/ComfyUI_FourierDomainAdaptation
Then restart ComfyUI. No extra dependencies, no model downloads, no API keys - the whole thing is pure numpy/torch FFT math, so it installs clean on any existing ComfyUI. One README gotcha: it tells you to copy a folder called ComfyUI_FDA, which doesn't match the repo name at all. Ignore that - clone the repo as named and you're fine.
Gotchas worth knowing
- Artifacts at high beta. Above roughly
0.2you can get banding or halos around high-contrast edges. Stay under0.1unless the aggressive look is the point. - Too-low beta looks broken. At
0.001the change is nearly invisible. It's working; the window is just tiny. - Whole image only. This is global color transfer. It won't match one region to another or do selective grading - for per-region work you're in histogram-match or manual correction territory.
- CPU-bound numpy. The node shuffles tensors to numpy and FFTs per channel, so it's fine for a handful of images but not the thing to pipe a 2,000-frame render through. It does auto-resize a mismatched reference to the target and cycles reference frames if the batch sizes differ, which covers most real usage.
One thing worth trying: matching against a mildly graded reference and layering two FDA passes at different betas often reads more natural than one aggressive pass - a hard reference grade can look painted-on. But honestly, start at the default 0.01 and see what it does to your image. It's one node and a slider; you'll know in a second whether it's your jam.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| target_image | IMAGE | — | |
| reference_image | IMAGE | — | |
| beta | FLOAT | 0.0100.001–0.5 | Low-frequency window size as a fraction of image dimensions. Larger values transfer more global style; smaller values are subtler. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| adapted_image | IMAGE | — |