Mean Curvature Blur (GEGL-like)
An edge-preserving blur that doesn't wreck the lines
- image
- image
A plain Gaussian blur doesn't care about edges - it smears everything equally, which is why heavy blur makes portraits look like wax. Mean Curvature Blur (GEGL-like) is the opposite philosophy: it smooths flat areas aggressively while leaving structural edges mostly alone. It's a port of GIMP's gegl:mean-curvature-blur, and it's the tool you reach for when you want to kill noise or smooth gradients without losing the linework - think skin smoothing that doesn't dissolve the jawline, or cleaning up banding in a sky.
The mechanism is mean curvature flow, a geometry idea: imagine the image as a surface where brightness is height. "Mean curvature" measures how bent that surface is. Each iteration nudges the surface so its local bending decreases - and the clever part is that flat regions (low curvature) flatten fast, while sharp edges (high curvature) barely move. The result is an edge-preserving blur driven by actual image structure, not a fixed kernel radius.
How it works
Under the hood it's a short numerical simulation, fully vectorized in torch: central finite differences estimate the gradient, the gradient is normalized to get the edge direction, and the divergence of that normalized gradient is the curvature. Each iteration is one explicit Euler step (dt = 0.2), then the result is clamped. Run it for N iterations and flat areas converge to smooth while edges survive. The linear toggle (on by default) does the whole thing in linear RGB after an sRGB↔linear conversion, which gives more radiometrically correct results - worth leaving on unless you want the punchier look of working in gamma space.
The inputs that matter
iterations(0–500, default 20) - the only real control. More iterations = smoother, at a linear cost in compute. 20 is a reasonable baseline; 100+ gets very painterly.linear(boolean, default true) - work in linear RGB. Leave it on unless you have a reason.
One image output; alpha is passed through untouched.
Where it fits
This is a finishing-chain workhorse. Run it on a render before adding grain, use it as a gentler alternative to heavy blur for backgrounds, or stack a low-iteration pass (5–10) to knock out sensor-style noise without the "plastic" look of Bilateral blur. It also plays well with the pack's noise nodes: blur first, then add LCH or RGB grain on top for a filmic finish.
Install
ComfyUI Manager → search AnotherUtils, or:
cd ComfyUI/custom_nodes
git clone https://github.com/marcoc2/ComfyUI-AnotherUtils.git
Restart ComfyUI. Pure torch, no weights, no extra pip packages.
Common issues
The biggest gotcha is expectations: "blur" usually means "radius", and this node has no radius - only iterations. If you need a fat, heavy blur, this isn't the node; grab a Gaussian. If things come out too smooth or too crunchy, tune iterations in steps of 5–10 rather than jumping. On large images each iteration costs real compute, so 500 iterations on a 4K image is a patience test - start small, scale up. And since it's deterministic and batch-capable, it runs identically across a whole batch, which is exactly what you want when cleaning up a dataset.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| iterations | INT | 200–500 | — |
| linear | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |