Image Postprocess (NOVA NODES)
One Node to Make AI Images Look Captured, Not Generated
- image
- Cam_Opt
- NS_Opt
- awb_ref_image
- fft_ref_image
- IMAGE
- EXIF
Image Postprocess (NOVA NODES) is the heart of this pack - the node that actually does something. You'll slot it in right after VAE decode, before Save Image, and it runs a whole post-processing chain that makes a generated image look like it left a real camera's sensor. This is the pack's flagship, and it's worth knowing exactly what you're turning on, because half of it is off by default for a reason.
Quick background so the inputs make sense: this is the ComfyUI version of the community "Image Detection Bypass Utility" - a research tool that got a lot of traction on r/StableDiffusion for studying how AI-image detectors work (the original threads pulled +400 and +117 upvotes; u/Race88 wrote the first ComfyUI wrapper, and the Aloukik21 repo is that same code re-shipped as NovaNoiser). What that means in practice: it's a photography-pipeline simulator plus some Fourier tricks, all aimed at scrubbing the "generated" look off an image.
How it works. The source is unambiguous about the order: the node writes your image to a temp file and runs the pack's process_image() pipeline - non-semantic attack (if enabled) → CLAHE local contrast → FFT spectral matching → GLCM texture matching → LBP texture matching → Gaussian noise → random pixel perturbation → camera simulator → auto white balance → LUT grade → fake EXIF. Then it loads the result back into a tensor. You're not getting one effect; you're getting a stack, and the stack order is fixed.
The inputs that matter.
- image - your IMAGE tensor. Only the first frame of a batch is processed.
- Cam_Opt and NS_Opt - the custom-type plugs for the pack's two settings nodes. Leave them empty and NovaNodes falls back on sensible defaults, so the main node works even bare.
- noise_std_frac - the Gaussian noise level, 0.02 default. Keep it low; more noise means more "camera" but also more destruction.
- apply_fourier_o / fourier_strength / fourier_mode - the FFT spectral matcher, the most distinctive thing here. It reshapes your image's frequency spectrum to match a reference (
ref), a math model (model), or an automatic choice (auto). - seed - -1 means fully random each run; any other value makes the whole chain reproducible. If you're iterating on settings, set it.
- apply_exif_o - stamps random but plausible camera EXIF (Canon, Nikon, Sony…) into the output.
The two outputs: IMAGE, which is your processed tensor and the only thing you save; and EXIF, a string containing the fake EXIF blob in case you want to persist it separately.
Troubleshooting, from the people who actually ran it. The author's own note applies here: default parameters will not instantly work - expect to tune. Where people get burned:
- FFT reference + seed cause a lot of variability. Two runs with the same settings but a random seed can look very different. Nail your seed early.
- The LUT path is a placeholder by default.
lutships asX://insert/path/here(.png/.npy/.cube)- withenable_luton, the pack tries to load it, fails, and prints a warning to the console every run. It's harmless, but that warning is not an error. - GLCM helps Flux generators; LBP "works occasionally - use last." Both are slow texture-statistics matchers (they pull in scikit-image), and the maintainer's own advice is to enable LBP only after everything else.
- The non-semantic attack is the slow one. It's an LPIPS-based optimizer and needs
lpips+ torch installed; on CPU, 500 iterations will crawl. If you're not using it, leave it off (it's controlled via NSOptionsNode).
Install - shared with the pack: ComfyUI Manager → search ComfyUI-NovaNoiser, or
cd ComfyUI/custom_nodes
git clone https://github.com/Aloukik21/ComfyUI-NovaNoiser
cd ComfyUI-NovaNoiser
pip install -r requirements.txt
then restart. Watch the pinned torch==2.8.0+cu126 in requirements.txt - it can try to replace your existing torch. Also ignore the README's GUI instructions (run.py, run.sh, PyQt5): that's the standalone app that ships in the repo, and the nodes here don't touch it.
Inputs (35)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| Cam_Opt | CAMERAOPT | — | |
| NS_Opt | NONSEMANTICOP | — | |
| apply_noise_o | BOOLEAN | true | — |
| noise_std_frac | FLOAT | 0.0200–0.1 | — |
| apply_clahe_o | BOOLEAN | true | — |
| clahe_clip | FLOAT | 2.00.5–10 | — |
| clahe_grid | INT | 82–32 | — |
| fourier_cutoff | FLOAT | 0.250–1 | — |
| apply_fourier_o | BOOLEAN | true | — |
| fourier_strength | FLOAT | 0.900–1 | — |
| fourier_randomness | FLOAT | 0.050–0.5 | — |
| fourier_phase_perturb | FLOAT | 0.080–0.5 | — |
| fourier_radial_smooth | INT | 50–50 | — |
| fourier_mode | COMBO | auto | 3 options: auto, ref, model |
| fourier_alpha | FLOAT | 1.00.1–4 | — |
| perturb_mag_frac | FLOAT | 0.0100–0.05 | — |
| enable_awb | BOOLEAN | true | — |
| enable_lut | BOOLEAN | true | — |
| lut | STRING | X://insert/path/here(.png/.npy/.cube) | — |
| lut_strength | FLOAT | 1.000–1 | — |
| glcm | BOOLEAN | false | — |
| glcm_distances | STRING | 1 | — |
| glcm_angles | STRING | 0,0.7853981633974483,1.5707963267948966,2.356194490192345 | — |
| glcm_levels | INT | 2562–65536 | — |
| glcm_strength | FLOAT | 0.900–1 | — |
| lbp | BOOLEAN | false | — |
| lbp_radius | INT | 31–50 | — |
| lbp_n_points | INT | 241–512 | — |
| lbp_method | COMBO | uniform | 4 options: default, ror, uniform, var |
| lbp_strength | FLOAT | 0.900–1 | — |
| seed | INT | -1-1–2147483647 | — |
| apply_exif_o | BOOLEAN | true | — |
| awb_ref_imageopt | IMAGE | — | |
| fft_ref_imageopt | IMAGE | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| EXIF | STRING | — |