Unblend Sequential Refine (per-char img2img)
Per-character img2img without the twins problem
- model
- clip
- vae
- image
- char_masks
- image
- mask_preview
- info
The Dynamic Sampler gets the two characters separated in the first place, but separation alone isn't detail. A face that occupies fifty pixels of a 1024px frame is a smear no matter how clean the region is, and if you run a plain second KSampler over the whole image, you're back to leaking features everywhere. UnblendSequentialRefine is the second pass of the pack's pipeline, and its whole trick is that it redraws one character at a time with only that character's prompt.
Why one at a time matters
When you refine CHAR1, the prompt it samples with is built from the shared context ([QUALITY], [STYLE], [SCENE], [CAMERA]) plus only CHAR1's tokens - no neighbor, no [INTERACT]. Zero foreign tokens in the pass means zero feature leak: the other character's hair color literally cannot bleed into this one, because it isn't in the conditioning at all. Pose and composition are held by the noise_mask and a low denoise, not by re-prompting.
There's an ordering rule the author is explicit about: run this after the joint draft pass. Interaction - hugs, leaning, contact - emerges from the two characters co-generating in the Dynamic Sampler. This node only refines what's already there.
The passes inside one node
It's three img2img passes in sequence, each with its own denoise knob:
refine_denoise(default 0.45) - the per-character repaint. Lower holds pose better, higher scrubs features and clothing harder.background_denoise(default 0.3) - a background pass with a scene-only prompt (no characters at all). Set to 0 to skip. This is the pass that stops characters from duplicating onto in-scene paintings and decor.harmonize_denoise(default 0.18) - a final unmasked pass that blends seams and lighting where the regions meet. Set to 0 to skip.
Then there are the two quality flags worth knowing about. per_char_upscale (off by default) crops each character by its mask, upscales the crop to detail_size (default 1024), and repaints there, then pastes back with a feathered seam - so a small hero on a wide canvas gets a face that actually has resolution. This is the same crop-detail loop ADetailer/FaceDetailer users know from the detailing world, applied per character with only that character's prompt. bg_tiled splits the background into native-resolution tiles for bg_tile_size canvas-wide detail. mask_feather (default 4) softens the mask edges so the seams don't show.
The inputs that matter
The plumbing is straightforward: image (your decoded Dynamic Sampler output), char_masks (the ordered stack from Unblend Assign Masks), plus model/clip/vae and the usual sampler settings. Wire the patched model output from the Dynamic Sampler here if you want the region constraints to carry through consistently. Outputs are image (the finished refine), mask_preview (the regions it worked on), and an info string that logs each pass.
Install & gotchas
cd ComfyUI/custom_nodes
git clone https://github.com/LatentDesireAI/ComfyUI-Unblend
pip install -r ComfyUI-Unblend/requirements.txt
Manager users just search "Unblend" and install. SDXL / Illustrious only, like the rest of the pack - it runs the same SDXL check. It does not need an external SAM node itself; SAM is only needed upstream, at Assign Masks time.
When things go wrong
Read info: CHAR1: empty mask - skip means Assign Masks handed you nothing for that character, so go fix the points upstream. If poses drift, refine_denoise is too high - drop toward 0.35. If seams are visible at region boundaries, raise mask_feather or nudge harmonize_denoise. If your small character's face is still mushy, that's what per_char_upscale is for - the full-frame masked pass literally cannot give a 50px face detail, no matter how many steps you throw at it.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| clip | CLIP | — | |
| vae | VAE | — | |
| image | IMAGE | — | |
| char_masks | MASK | — | |
| prompt | STRING | [QUALITY] masterpiece, best quality [STYLE] anime style [SCENE] simple background [CHAR1] columbina (genshin impact), black hair, white dress [CHAR2] fischl (genshin impact), blonde hair, eyepatch [BODY] slim body | — |
| negative_prompt | STRING | lowres, worst quality, low quality, bad anatomy, bad hands | — |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 244–200 | — |
| cfg | FLOAT | 5.50.5–20 | — |
| sampler_name | COMBO | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 | |
| scheduler | COMBO | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 | |
| refine_denoise | FLOAT | 0.450.1–0.95 | — |
| background_denoise | FLOAT | 0.300–0.8 | — |
| harmonize_denoise | FLOAT | 0.180–0.6 | — |
| mask_feather | INT | 40–32 | — |
| subject_word | STRING | girl | Booru count word. One word = all characters (e.g. 'girl'). Comma list for a mixed cast: 'girl, boy' -> CHAR1 girl, CHAR2 boy (padded with the last). |
| per_char_upscale | BOOLEAN | false | — |
| detail_size | INT | 1024512–2048 | — |
| crop_factor | FLOAT | 1.41–3 | — |
| bg_tiled | BOOLEAN | false | — |
| bg_tile_size | INT | 1024512–2048 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask_preview | IMAGE | — |
| info | STRING | — |