Mask AI Fingerprint
Every AI Image Has a Fingerprint — This Node Tries to Erase It
- image
- cleaned_image
- anomaly_mask
- fft_heatmap
The name promises "masking AI fingerprints," and that's roughly what the node does - just not the way you'd expect. Diffusion models leave a periodic, grid-like pattern in the frequency domain: a tell-tale that shows up as sharp peaks in the image's FFT spectrum. It's how AI-image detectors (and people who know what a clean spectrum should look like) tell a render from a photograph. MaskAIFingerprint finds those peaks, knocks them down, and then re-degrades the result to look like it came out of a camera instead of a sampler.
Here's the honest framing up front: the "cleaned" output is not a faithful restoration. It's the input with spectral peaks suppressed and a whole camera-simulation pipeline dumped on top - sensor noise, lens distortion, JPEG recompression - so the result reads as "photographed." The point is obfuscation, not cleanup. If you were hoping for a magic "make my upscale sharper" node, this isn't it.
How it works
Under the hood it's classic spectral filtering. Per color channel, the node takes the FFT, shifts the DC component to the center, and looks at the log-magnitude. Anything above mean + peak_threshold * std counts as a fingerprint peak, gets multiplied by suppression_factor to shrink it, and the phase gets a little random noise to break up whatever structure survives. Then it inverse-transforms back to pixels.
The catch that will absolutely trip you up: suppression_factor defaults to 1.0, which multiplies the peaks by 1 - i.e. does nothing. The default settings barely suppress anything. The spec says "still need improvement," and this is the most visible sign. You want it around 0.1–0.3 to actually flatten peaks. Meanwhile peak_threshold (default 0.7) controls how aggressive the detector is: lower it to catch more, raise it to leave fine detail alone.
The outputs are straightforward: cleaned_image (IMAGE), anomaly_mask (MASK - the difference between input and cleaned, blended with a uniformity mask), and fft_heatmap (IMAGE - the normalized log-magnitude spectrum, which is the fingerprint made visible). The heatmap is genuinely useful for debugging: feed it to a preview and you'll literally see the bullseye pattern the model is trying to erase.
The defaults are not your friend
Beyond suppression_factor, the rest of the ~25 inputs are a camera-emulation playground: noise_strength, grain_strength, poisson_scale, prnu_strength, chromatic_aberration_strength, vignette_strength, lens_distortion_k, and so on. A handful matter before you touch the rest:
resize_factor(default 0.5) - the image is downscaled, processed, then upscaled back. Even at default this softens things noticeably.jpeg_quality(default 60) andjpeg_iterations(default 5) - five round-trips through a q60 JPEG recompression. That's heavy, and it's the main way the node simulates "uploaded to social media" degradation. Drop iterations to 1 (or quality to 95) if you want to see what the FFT part alone does.posterize_levels(default 50) - banding risk if you leave it where it is.
If you want the pure fingerprint suppression without the "photographed" disguise, set suppression_factor to ~0.2 and push jpeg_quality up and resize_factor to 1.0.
Install
Install is refreshingly boring, which is a compliment in this ecosystem. The pack has an empty requirements.txt - no hidden heavy dependencies. It only uses torch, torchvision, PIL, and numpy, all of which ComfyUI already ships. Either search "MaskAIFingerprint" in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/FearL0rd/ComfyUI-MaskAIFingerprint
Then restart ComfyUI. No model downloads, no venv surgery.
Common issues
- "It didn't change anything."
suppression_factoris 1.0 by default. That's not a bug, exactly, but it's the single most likely reason the node seems inert. Also confirm the heatmap actually shows peaks before you expect visible change. - Output looks soft or banded. That's the defaults (resize 0.5, q60 JPEG ×5, posterize 50) working as intended. Turn them toward neutral and the "cleaned" image gets closer to the input.
- Expectation mismatch. This is a one-commit experiment with zero community adoption, not a polished tool. If your actual goal is stripping a specific visible watermark (the Flux family's C2PA/invisible marks), the community's known-good path is image-editing models like Kontext, not spectral surgery. MaskAIFingerprint is the DIY route - fine for curiosity, useful for learning what an FFT fingerprint actually looks like, but treat it as a science project with real teeth in only one setting:
suppression_factorbelow 1.
Inputs (26)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| peak_threshold | FLOAT | 0.70–10 | — |
| suppression_factor | FLOAT | 1.00–1 | — |
| phase_noise_strength | FLOAT | 0.0100–0.1 | — |
| freq_noise_strength | FLOAT | 0.0050–0.05 | — |
| noise_strength | FLOAT | 0.0150–0.1 | — |
| grain_strength | FLOAT | 0.0200–0.1 | — |
| salt_pepper_prob | FLOAT | 0.00010–0.05 | — |
| poisson_scale | FLOAT | 3001–10000 | — |
| read_noise_strength | FLOAT | 0.0050–0.05 | — |
| prnu_strength | FLOAT | 0.0100–0.1 | — |
| blur_sigma | FLOAT | 0.50–5 | — |
| motion_blur_strength | FLOAT | 0.00–10 | — |
| chromatic_aberration_strength | FLOAT | 1.00–5 | — |
| vignette_strength | FLOAT | 0.000–1 | — |
| lens_distortion_k | FLOAT | 0.07-1–1 | — |
| uniformity_threshold | FLOAT | 0.000–1 | — |
| brightness | FLOAT | 0.00-1–1 | — |
| contrast | FLOAT | 1.000–2 | — |
| saturation | FLOAT | 1.000–2 | — |
| hue | FLOAT | 0.00-0.5–0.5 | — |
| sharpen_amount | FLOAT | 1.00–2 | — |
| posterize_levels | INT | 502–256 | — |
| resize_factor | FLOAT | 0.500.5–1.5 | — |
| jpeg_quality | INT | 6050–100 | — |
| jpeg_iterations | INT | 51–5 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| cleaned_image | IMAGE | — |
| anomaly_mask | MASK | — |
| fft_heatmap | IMAGE | — |