Poisson Blend (Seamless Clone)
Paste without the seam — Poisson cloning inside ComfyUI
- background
- source
- source_mask
- image
- used_mask
Anyone who's pasted a subject onto a new background knows the tell: a hard edge, a colour cast, a bright rim where the old photo's lighting bleeds through. ComfyUI has a dozen "paste and pray" compositing tricks, but the honest fix is Poisson image editing - the same math Photoshop's "seamless clone" uses. Poisson Blend wraps OpenCV's seamlessClone (Pérez et al., 2003) into a proper ComfyUI node, so you can clone one image into another through a mask and get a blend that actually matches the destination's tone.
It's the newest node in the Eric_Composer_Studio pack - you won't find it in the pack README yet, and it sits under its own Eric_Composer_Studio/compose category rather than the main one. Worth knowing, because the canvas composer nodes in this pack are for layout, and this is the one that makes the pasted pixels believe they belong.
How it works
Instead of just overlaying pixels, Poisson editing solves a small gradient field: the pasted region keeps its own gradients (shape, texture, internal shading) while its overall colour and brightness drift toward the destination's local tone. That's why a bright subject can land on a dim background without looking composited. The node gives you three modes, each mapping to an OpenCV flag:
normal(NORMAL_CLONE) - full colour/luminance match. Best for opaque objects.mixed(MIXED_CLONE) - at each pixel the stronger gradient wins. Best for transparent, wispy or textured things: foliage, smoke, hair.monochrome(MONOCHROME_TRANSFER) - the source contributes only luminance; hue and saturation come from the destination.
Inputs and outputs
Three required: background (destination canvas; the output matches its size), source (the image with the object to clone), and source_mask (which pixels are in - anything above 0.5 counts; soft masks get binarised because OpenCV needs a hard mask).
The optional list is where the craftsmanship lives:
mode- one of the three above.auto_fit- on by default; resizes source and mask to background size first. Off, a size mismatch is an error.center_x/center_y- where the mask centroid lands on the destination;-1uses the source mask's own centroid (i.e. no movement).offset_x/offset_y- nudges applied after centering.mask_shrink_px- erodes the mask before cloning. The default of 1 is there for a reason (see below).post_feather_px- a feathered re-mix of the result over the background, to soften jagged mask edges without breaking the gradient match.strength- blends the Poisson result with the original background; 1.0 is full Poisson.
Outputs are image and used_mask (the mask actually applied, post-erosion - handy for debugging).
Installing it
Same as the pack: ComfyUI Manager → search Eric Composer Studio → install → restart, or git clone https://github.com/EricRollei/Eric_Composer_Studio.git into custom_nodes and pip install -r requirements.txt. The dependency that matters here is opencv-python, which is in the requirements.
Where people get burned
- Black borders / outright failure. OpenCV's
seamlessClonethrows a fit if the mask touches the image border. The node auto-pads when it detects that, but you should still keepmask_shrink_px >= 1- it erodes away fringe artefacts at sharp matte edges too. - "The paste didn't move." If you set
center_x/y, remember they position the mask centroid andoffset_x/ystack on top - and the node clamps so the mask's bounding box stays inside the destination. If your subject is already exactly where you want it, leave centering at-1. - Source size mismatch. If
auto_fitis off and dimensions differ, it's a hard error by design. Crop or pad the source to background size first, or just leaveauto_fiton.
One honest caveat: Poisson blending is great at tone-matching, but it can't fix a subject whose geometry says "I was lit from the left" landing in a scene lit from the right. That's a lighting problem, not a seams problem - no solver in OpenCV will save you there.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| background | IMAGE | Destination canvas. The output is the same size as this. | |
| source | IMAGE | Image containing the object to clone in. Must be the SAME SIZE as background (crop/pad the source to background size first if needed; centre + offset_x/y are then applied to the mask only). For a different-sized source, see the auto_fit toggle below. | |
| source_mask | MASK | Hard mask over source: which pixels to clone in. Anything > 0.5 is IN. Soft masks are binarised — OpenCV requires a binary mask. | |
| mode | COMBO | normal | normal (NORMAL_CLONE): standard Poisson, full colour/luminance match. Best for opaque objects. mixed (MIXED_CLONE): per-pixel stronger gradient wins. Best for transparent / wispy / textured things (foliage, smoke, hair). monochrome (MONOCHROME_TRANSFER): source contributes only luminance; hue/saturation come from the destination. |
| auto_fitopt | BOOLEAN | true | If source is a different size than background, automatically resize source and source_mask to background size BEFORE blending. With auto_fit OFF a size mismatch is an error. |
| center_xopt | INT | -1-1–16384 | Destination x-coordinate where the mask centroid lands (in pixels). -1 = use the source mask's own centroid (no movement). |
| center_yopt | INT | -1-1–16384 | Destination y-coordinate where the mask centroid lands. -1 = auto. |
| offset_xopt | INT | 0-16384–16384 | Additional x-shift applied AFTER center_x (lets you nudge without overriding the centroid). |
| offset_yopt | INT | 0-16384–16384 | Additional y-shift applied AFTER center_y. |
| mask_shrink_pxopt | INT | 10–64 | Erode mask by N pixels before cloning. Recommended >= 1 because OpenCV's seamlessClone fails / produces black borders if the mask touches the image border. Also reduces fringe artefacts at sharp matte edges. |
| post_feather_pxopt | INT | 00–128 | After Poisson blending, re-mix the result over the original background using a feathered version of the mask (Gaussian blur). 0 disables. Use this to soften the very edge of the cloned region without breaking the gradient match (the Poisson result is already seamless; this only helps if your mask edge is jagged). |
| strengthopt | FLOAT | 1.000–1 | Linearly blend (1-s)*background + s*poisson_result inside the mask. 1.0 = full Poisson. <1.0 lets some of the original (unmodified) source show through (only meaningful if source was already pre-pasted at the same coords as the mask). |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| used_mask | MASK | — |