Latent Upscale Advanced
A latent upscaler that respects all 16 channels — or just acts like stock
- samples
- stats_latent
- LATENT
Here's the thing most latent upscalers won't tell you: a latent isn't a picture, it's a stack of channels (16 of them, for most modern VAEs), and the standard per-channel bicubic upscale treats each one like an independent grayscale image. Latent Upscale Advanced is from the Flow Matching Upscaler pack, and it's the rare upscaler that actually lets you do something about that. It can whiten the channels against their covariance, upscale in that decorrelated space, then re-color - the "whiten → upscale → recolor" trick from the author's own upscaling.md notes, wrapped in a node.
The honest take: with covariance_mode left at none, this node is deliberately a drop-in clone of ComfyUI's built-in latent upscale. Same methods, same defaults (scale_by 2, nearest-exact). So it's not a thing you must reach for - it's a thing you reach for when you're upscaling a latent before a hi-res pass and want either extra control or genuinely different interpolation behavior.
Why you'd actually use it. In the upscaling hierarchy - more pixels vs. more detail vs. more temporal - this lives firmly in the "prepare the latent for a second-pass denoise" slot. Feed it the latent from your first pass, upscale, then run a low-denoise img2img pass on the result. That's the classic hi-res-fix shape, and the value here is that the whitening mode changes how the interpolation happens, not just how big the result is.
How the covariance mode works. It estimates the per-channel mean and covariance across the latent's pixels, diagonalizes that covariance (the code uses torch.linalg.eigh), whiten the pixel vectors, upscale, then apply the inverse transform. moment_match adds an affine correction afterward so the upscaled latent's mean and covariance match the source's. One caveat the author's own learnings flag: a global linear channel transform commutes with per-channel linear spatial upscaling, so whiten→upscale→recolor is algebraically identical to just upscaling for nearest-exact, bilinear, area, and bicubic. The mode only bites with non-linear methods like bislerp, or if you start playing with per-component kernels. That's a feature, not a bug - you can flip it on without fear of breaking your pipeline.
Inputs that actually matter:
samples- the LATENT to upscale.scale_by- 2.0 doubles the latent grid (which is 4× pixels at VAE scale, since latent dims are 8× smaller than pixels).upscale_method- keep the default unless you know why you're changing it. Thelanczosoption is a trap: ComfyUI's lanczos path is PIL-based and unsafe on LATENT tensors, so this node silently falls back tobicubic.covariance_mode-noneorwhiten; andmoment_match- the "restore the stats" toggle.per_batch_stats- on by default, which is right; it computes covariance per batch item instead of pooling everything into one estimate.
The shrinkage, epsilon, and stats_sample_pixels knobs are stabilization for when the covariance estimate gets noisy - leave them alone until you see artifacts. stats_latent lets you estimate the stats from a different latent than the one you upscale, which is niche but occasionally the exact knob you need.
Output. A single LATENT, ready for a KSampler at low denoise, a VAE Decode, or another upscale stage.
Install. This ships inside ttulttul/ComfyUI-FlowMatching-Upscaler. Easiest path is ComfyUI Manager - search "ComfyUI-FlowMatching-Upscaler" and hit install. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/ttulttul/ComfyUI-FlowMatching-Upscaler
Then restart ComfyUI. The pack's requirements are just numpy, torch, einops, and aiohttp - all already present in any working ComfyUI - and there are no model downloads. The node shows up under latent/upscaling.
Gotchas. The lanczos fallback is the main one - if you're chasing the exact ComfyUI stock behavior, know that stock also routes lanczos through PIL and is just as unsafe. The other thing: this is not a pixel upscaler. If you feed it an image and expect ESRGAN-style sharpening, you'll be disappointed; it operates in latent space and pairs with a denoise pass, not with VAE Decode straight out.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| samples | LATENT | Input latent to upscale. | |
| scale_by | FLOAT | 2.000.01–8 | Spatial scale factor applied to the latent grid (e.g., 2.0 = 2× latent resolution). |
| upscale_method | COMBO | nearest-exact | Resampling kernel for spatial upscaling. NOTE: ComfyUI's `lanczos` path uses PIL and is unsafe for LATENT tensors; this node will fall back to `bicubic` if selected. |
| crop | COMBO | disabled | Cropping behavior when target aspect ratio differs (rare when using scale_by). |
| covariance_mode | COMBO | none | Enable covariance-aware whitening (whiten→upscale→recolor). |
| moment_match | BOOLEAN | false | After upscaling (with covariance_mode=whiten), apply an affine correction so the upscaled latent matches the source mean/covariance. |
| per_batch_stats | BOOLEAN | true | Compute stats per batch element (recommended). Disable to share one covariance estimate across the batch. |
| stats_sample_pixels | INT | 00–16777216 | 0 = use all pixels for covariance estimation; otherwise randomly sample this many pixel vectors. |
| stats_seed | INT | 00–18446744073709550000 | Seed used when stats_sample_pixels > 0. |
| shrinkage | FLOAT | 0.050–1 | Shrink covariance toward its diagonal (stabilizes whitening when covariance is noisy). |
| epsilon | FLOAT | 0.00000–0.1 | Diagonal jitter added to covariance (prevents non-positive-definite matrices). |
| stats_latentopt | LATENT | Optional latent used to estimate mean/covariance (defaults to input). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |