Image Infill Gaussian Mixture Layer
Texture inpainting for people who miss the math
- image
- mask
- infilled_image
- texton_viz
Some holes are made of texture, not structure. A patch of grass with a rock removed, water with a boat painted out, a fabric weave missing a swatch - these don't need lines extended, they need the statistics of the texture reproduced so the fill is indistinguishable from the surrounding grain. Image Infill Gaussian Mixture Layer is the specialized tool for that: it fits a stationary Gaussian model to the known pixels of the texture and samples the hole from it via FFT-based conditional simulation. It's the Galerne-Leclaire (2017) approach, and it's the exact opposite of the pack's smeary boundary fill - this one is about statistical correctness.
It's niche, and it knows it. The brief is upfront: best for homogeneous microtextures. If your hole crosses a wall edge or a horizon, this is the wrong tool and the wrong tool badly. But for repeating, stationary texture, patch-based fills (which copy actual patches) leave visible repeats and seams, and this method can be scarily seamless.
How it works
The idea: model the source texture as a stationary Gaussian random field - mean, covariance (via the power spectrum), estimated from the source pixels. Then conditionally simulate: draw a sample of the field that exactly matches the known pixels at the hole boundary and is statistically consistent with the source texture inside the hole. The "conditional" part is what keeps the seam from showing - the sample has to agree with everything outside the hole. The heavy lifting is an iterative conjugate-gradient solve, which is why the node exposes cg_max_iterations (default 100) and cg_tolerance (1e-6).
The inputs that matter:
image+mask- the usual pair.add_innovation/innovation_strength- whether to add fresh randomness to the sampled field. Off, you get the statistically "best" (smoothest) fill; on (default, strength 1.0), you get a fill with realistic grain.regularization(0.001) - stabilizes the covariance estimate; raise it if you get numerical noise, lower it for sharper texture.detrend_sigma- removes low-frequency drift from the source before fitting; useful if your "texture" has a subtle brightness gradient. 0 means off.clamp_to_source_gamut(default on) - clamps the sample's colors to the source's range so the fill can't produce out-of-range artifacts.seed- reproducibility.
Outputs: infilled_image and texton_viz - a visualization of the fitted texture model.
Installing it
Part of CorvaeOboro's ComfyUI_illumorae (CC0, no model files - NumPy/SciPy math). ComfyUI Manager → search illumorae, or:
cd ComfyUI/custom_nodes
git clone https://github.com/CorvaeOboro/ComfyUI_illumorae
It uses SciPy, so if you cloned manually make sure it's installed (pip install scipy if a node import fails).
Common issues
- Overkill for general object removal - for typical "delete the thing" jobs, use PatchMatch. This node is for texture-grade fills where repeats would give it away.
- Fill is too smooth / waxy -
add_innovationoff, orinnovation_strengthtoo low. Crank it up. - Numerical artifacts / blotches - raise
regularization; the covariance estimate is unstable on small or heterogeneous source regions. - Slow on big holes - the conjugate-gradient solve scales with hole size and
cg_max_iterations. Shrink the mask or cap iterations; this is a tool for precision, not throughput.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask | MASK | — | |
| cg_max_iterationsopt | INT | 1001–2000 | — |
| cg_toleranceopt | FLOAT | 0.00001e-12–0.1 | — |
| add_innovationopt | BOOLEAN | true | — |
| innovation_strengthopt | FLOAT | 1.000–4 | — |
| regularizationopt | FLOAT | 0.00101e-8–1 | — |
| seedopt | INT | 00–4294967295 | — |
| detrend_sigmaopt | FLOAT | 0-1–256 | — |
| clamp_to_source_gamutopt | BOOLEAN | true | — |
| debug_printsopt | BOOLEAN | false | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| infilled_image | IMAGE | — |
| texton_viz | IMAGE | — |