Ensemble Super-Resolution (HDR)
Run your upscaler N times and fuse the good parts
- image
- upscale_model
- image_float
- image_clamped
- image16
The name sounds like marketing, but it's literal. Camera makers do "pixel shift" by nudging the sensor by sub-pixel amounts, stacking the shots, and recovering detail that sat between pixels. This node does the same thing to an AI upscaler: instead of trusting one upscale pass, it runs the model you give it several times on shifted and flipped copies, realigns them, and fuses the results. The output is a 32-bit float "digital RAW" master, values above 1.0 intact, ready for real color grading.
Know what it isn't, though, because the upscaling world is full of category confusion. This is the more pixels rung, not the more detail rung. It doesn't invent content the way SeedVR2 or SUPIR do - it makes whatever ESRGAN/SwinIR model you already own behave better. The README says it plainly: "this node will not correct AI image hallucinations." Feed it a good, finished image (it suggests 2000/3000px and an X2 or X4 model) as the last pass, not a broken render you're hoping to rescue.
How it works
The mechanism, from the source: every pass randomly shifts the image by up to translate_pixels in X and Y, optionally flips it, upscales through ComfyUI's standard upscale path (the same ImageUpscaleWithModel that powers plain upscaling - that's why it accepts a normal UPSCALE_MODEL), then un-flips and translates back scaled by the upscale factor so every pass lines up pixel-for-pixel. The aligned stack gets fused, sharpened with an unsharp mask that's deliberately not clamped, and split into three outputs.
That "not clamped" bit is the whole point. Mean/average fusion plus unsharp can push highlights past 1.0, which is exactly what you want before grading and exactly what a normal node will throw away.
The inputs that matter
image and upscale_model are obvious. The rest you actually set:
passes(default 8, 2–32) - the quality/CPU knob. More passes = better noise and artifact removal, but each one is a full upscale run. 6–12 is the sweet spot; below 4 the benefits vanish, above 16 the gains shrink while the render time climbs.use_translate(default true) - this is the pixel-shift. Leave it on; without it you're just averaging N identical upscales.translate_pixels(default 1.5) - max shift distance. 0.75–1.5 is the sensible band; above 3.0 you start getting realignment problems at the borders.fusion_mode/mix_weight-MEANkills random noise,MEDIANkills outlier artifacts,MIXblends both. Leave it onMIXat 0.5.use_flip(true),unsharp_amount(0.3),seed+randomize_each_run(leaverandomizefalse unless you want a different result every queue even with a fixed seed).
One quiet trap: interpolation defaults to BICUBIC, but the source falls back to BILINEAR automatically when BICUBIC isn't supported on the Tensor backend - and the README recommends BILINEAR anyway. So if you set BICUBIC and notice soft output, that fallback is probably why.
Outputs
Three IMAGE sockets: image_float (the unclamped float32 master - values can exceed 1.0), image_clamped (same thing forced to 0–1, for previews and standard nodes), and image16 (16-bit quantized from the clamped version, ready for a plain PNG). Wire image_float into the pack's Save Image Advanced node and you have a real grading pipeline.
Model choice actually matters
The node orchestrates; the model sets the character. ESRGAN derivatives (4x-UltraSharp, Remacri) are sharp and can hallucinate texture - the ensemble averaging is genuinely good at taming that. SwinIR is cleaner and more faithful but softer; the unsharp pass is welcome there. Anime models work too - the multi-pass fusion tends to clean up flat-color banding and compression artifacts.
Install and gotchas
ComfyUI Manager, search "Orion4D Pixel-Shift", or:
cd ComfyUI/custom_nodes
git clone https://github.com/orion4d/Orion4D_pixelshift
Then the part that bites: the pack ships no requirements.txt, so Manager won't install its deps for you. You need them for the save node, but they're harmless here:
pip install imageio tifffile opencv-python-headless
Restart after. No models to download - you load your upscaler with the normal UpscaleModelLoader. The real cost is time: 8 passes is roughly 8x a single upscale. Budget accordingly, and don't judge the node by the clamped preview alone - the float master is the point.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| upscale_model | UPSCALE_MODEL | — | |
| use_flip | BOOLEAN | true | — |
| use_translate | BOOLEAN | true | — |
| randomize_each_run | BOOLEAN | false | — |
| use_unsharp | BOOLEAN | true | — |
| passes | INT | 82–32 | — |
| translate_pixels | FLOAT | 1.500–8 | — |
| interpolation | COMBO | 3 options: BICUBIC, BILINEAR, NEAREST | |
| fusion_mode | COMBO | 3 options: MIX, MEAN, MEDIAN | |
| mix_weight | FLOAT | 0.500–1 | — |
| seed | INT | 00–2147483647 | — |
| unsharp_amount | FLOAT | 0.300–2 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image_float | IMAGE | — |
| image_clamped | IMAGE | — |
| image16 | IMAGE | — |