Context-Anchored Tile Refine
Tile refine that hides seams by conditioning, not by guessing
- image
- guider
- sampler
- sigmas
- vae
- noise
- mask
- IMAGE
Ever upscaled something to 4K, run Ultimate SD Upscale over it, and watched the tiles disagree with each other like siblings in a backseat? That's the problem this node exists to kill. Context-Anchored Tile Refine takes an image you've already upscaled and re-diffuses it one tile at a time, with the tiles held together so tightly that the seams are hard to find even if you go looking.
The author, blakeem, got here honestly. His launch post explains the whole backstory: he started from a fork of Ultimate SD Upscale (he wanted a guider input), kept adding quality fixes, got fed up with its fixed tile sizes and legacy seam machinery, and finally rewrote it from scratch. What he ended up with is deliberately less fiddly. Instead of asking you to pick a tile size, you give it the biggest image your GPU can comfortably denoise and it solves the grid for you - every crop lands on an 8-pixel boundary and tiles are extracted, sampled, and pasted back at their native pixel size, so nothing gets resized and quality isn't lost.
How the seams stay invisible
The secret is that seams are prevented by conditioning, not covered up. Each tile is sampled oversized, with two rings around it. context_overlap is a band shared with the neighboring tiles, diffused from both sides and blended. context_anchor is pure context beyond that - it shows the tile its already-refined neighbors as frozen pixels, so the tile continues them instead of drifting away. Tiles are processed in raster order, so by the time a tile is sampled its top and left neighbors are done.
The remaining differences get a genuinely clever cleanup: a directional feather whose midpoint bends along a minimum-error path (from the classic Image Quilting paper), plus a brightness-and-color match per seam that's a variant of panorama gain compensation. It sounds academic, but it's why the blends land at zero slope instead of leaving a visible line.
The inputs that matter
The info_schema makes it clear what a beginner actually touches:
max_tile_width/max_tile_height- hard cap on what the model sees per crop, including both rings. Set these to the largest size your model handles well. This is the "give me your GPU budget" knob, and it's the one you'll tune.context_overlap- the shared band. Zero gives hard seams. Smooth gradients want more, detailed scenes want less. 32 is a sane start.context_anchor- the frozen context ring. Keep it above 0 if you're using a mask, because it's also the frozen background the region refines against.- Everything else -
guider,sampler,sigmas,vae,noise- is wired from the same nodes you already use for normal sampling, and the optionalmasklets you refine only part of the image while leaving the rest untouched.
Two gotchas worth knowing. The base node accepts every sampler, and it works with any guider including NAG for models without negative support. ControlNet works here too - the hint is cropped per tile, so build it at the same size as your input image. And the mask has to match the image dimensions exactly; the node refuses to resample a mismatched mask rather than silently misalign your region.
Install
Search "Context-Anchored Tile Refine" in ComfyUI Manager, or clone it:
cd ComfyUI/custom_nodes
git clone https://github.com/Blakeem/ComfyUI-ContextAnchoredTileRefine
Then restart ComfyUI. The pack has zero pip dependencies and downloads no model files - it runs on the models you already have, which is a nice change from most upscale packs. It needs ComfyUI 0.3.45+ and is GPLv3 licensed. Before you burn GPU time guessing at layouts, there's a tile simulator on the project page that shows exactly how your image will be tiled and blended.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | The image to refine. Upscale it before this node. | |
| guider | GUIDER | The guider that denoises each tile. | |
| sampler | SAMPLER | The sampler used to denoise each tile. | |
| sigmas | SIGMAS | The sigma schedule used when sampling each tile. | |
| vae | VAE | The VAE that encodes and decodes each tile. | |
| noise | NOISE | Noise is drawn once for the entire image and then sliced for each tile. | |
| max_tile_width | INT | 1024256–16384 | Hard cap on the width the model ever sees per sampled crop, including the context_overlap and context_anchor rings. Set to the largest width the model supports. |
| max_tile_height | INT | 1024256–16384 | Hard cap on the height the model ever sees per sampled crop, including the context_overlap and context_anchor rings. Set to the largest height the model supports. |
| context_anchor | INT | 320–512 | Pixels around each tile that are frozen and shown to the model as context, then cropped away. With a mask it is also the frozen background the region is refined against, so keep it above 0. |
| context_overlap | INT | 320–512 | Overlapped context that is diffused from both sides and then blended. It anchors the tiles to each other, like context_anchor anchors each tile to its surroundings. |
| maskopt | MASK | Only the masked region is refined and the rest is left untouched. Feed an inverted mask for a second pass. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |