Nyquist Notch (2px VAE grid fix)
Kill Qwen-Image's VAE grid before you sharpen
- image
- image
Zoom into a freshly decoded Qwen-Image generation sometime and you'll see it: a faint 2-pixel repeating grid, like the image was stamped with a fine checkerboard. Sharpen it and the thing turns into an ugly mesh. That's the Qwen-Image VAE leaving a pixel-alternating flicker in the decode, and this node exists to strip it. It's called Nyquist Notch because it targets a specific spatial frequency - the 2px-period component - and knocks it out, nothing else.
Where this comes from
The Qwen-Image VAE is Wan-2.1's architecture - the tech report says it freezes Wan's encoder and fine-tunes only the image decoder, to make small text legible. That decoder is what over-smooths faces and also what stamps in this faint grid, and the Wan-2.1 VAE does it more subtly too. The artifact is old news to anyone who's sharpened Qwen-Image output; the 2px checkerboard after a sharpen is one of those "why does my image look like graph paper" posts that keeps coming back. The usual workarounds are blurring (which kills detail you wanted) or ignoring it (which doesn't work). A notch filter is the surgical option: it subtracts exactly the repeating component rather than softening everything.
How it works
The math is small and honest. It's a 7-tap separable binomial notch kernel, [-1, 6, -15, 20, -15, 6, -1] / 64, applied in both directions as (I − Hx)(I − Hy). In practice: it detects the 2px-period component of the image and subtracts it, then clamps to 0–1. It runs as a few depthwise convolutions in PyTorch - no model, no VRAM pressure, milliseconds on a normal batch. The author ported it straight from his own GLSL shader, so the math is identical to the version people have been using in image editors.
Wire it immediately after VAE Decode, before any sharpening or filtering. That's the whole trick - sharpen first and the notch has to fight an amplified grid; notch first and the sharpen has clean pixels to work on.
Inputs and outputs
Delightfully boring:
- image (required) - the decoded
IMAGEtensor. - strength (optional, default 1.0, 0–1) - the tooltip says it plainly: 0 = original, 1 = fully de-gridded. Dial it down if you want to preserve a hint of the original texture, or if the effect reads too aggressive on a particular image.
Output: image, the de-gridded tensor, same shape and dtype it came in. It's not an output node, so chain it into whatever's next.
Installing
Same pack as the rest: ComfyUI-DioBrando-Nodes. ComfyUI Manager → search the pack name → install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/DanielBartolic/ComfyUI-DioBrando-Nodes
cd ComfyUI-DioBrando-Nodes && pip install -r requirements.txt
Requirements are just Pillow, numpy, torch - nothing extra, no model downloads. It shows up under image/postprocessing.
Common issues
- "It did nothing" - if your source isn't a Qwen-Image or Wan decode, there's no 2px grid to remove, and the filter correctly finds almost nothing. Don't expect magic on an SDXL image.
- Everything looks slightly softened - that's usually over-application, not breakage. Drop
strengthto 0.5–0.7 and re-run; the notch only targets the 2px component, so the collateral is small, but blending at less than full strength is the safe play. - Order matters - if you've already sharpened, the grid is amplified and the notch is working against an uphill battle. Move it ahead of the sharpen step.
It's a one-job node for a one-job problem, and if you generate with Qwen-Image or Wan and you sharpen anything, it quietly earns its place in the graph.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| strengthopt | FLOAT | 1.000–1 | 0 = original, 1 = fully de-gridded. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |