Flux Kontext Diff Merge
Flux Kontext Diff Merge
- original_image
- edited_image
- manual_mask
- merged_image
- difference_mask
- preview_diff
Here's the thing nobody tells you about Flux Kontext (and Qwen-Image-Edit, and every other instruction-editing model): they don't edit, they re-render. Ask Kontext to change the shirt and you get a new image where the shirt changed - and the background subtly re-rendered, the skin texture drifted, a seam you didn't touch moved a millimeter. The model doesn't take a mask, so you can't tell it "only touch this."
That's the problem this node was built for. It takes the original image and the edited one, figures out what actually changed, and merges only those changed regions back onto the pristine original. Everything else stays exactly as it left your earlier pipeline. It's the "bolt a mask on after the fact" fix, made automatic.
How it works
Two stages, both visible in the source. First, a detection method builds a rough mask of differences between original and edited:
- adaptive (default) - LAB color-space difference with a
global_thresholdthat compensates for global shifts in brightness. Most robust. - color_diff - plain RGB max-channel difference. Cheapest, crudest.
- ssim - structural similarity based; needs
scikit-image. - combined - adaptive OR'd with an edge-aware (Canny) mask, so texture changes that color diff misses still get caught.
Then that raw mask gets cleaned up: min_change_area drops specks below a pixel count, and the refine pass closes, opens, dilates by mask_expand, Gaussian-blurs by mask_blur, and feathers the edges. That refined mask is your difference_mask output - worth wiring to a viewer before you trust it.
Finally, a blend method pastes the edited pixels back: poisson (default, OpenCV seamlessClone, the best seam-killer), alpha (simple weighted mix, always available), multiband (Laplacian pyramid), gaussian (distance-transform weighted). The three outputs are merged_image, difference_mask, and preview_diff - a red-tinted overlay showing exactly what got merged.
The settings you'll actually touch
- threshold (default 0.02) - change sensitivity. Lower catches subtler edits; raise it if the whole frame keeps getting flagged.
- blend_method - poisson is right 90% of the time. Switch to alpha if poisson produces artifacts at mask edges.
- manual_mask (optional) - override auto-detection entirely. If the diff keeps grabbing the wrong thing, paint your own mask and feed it in.
The dependency trap - read this before installing
The pack has no requirements.txt and pyproject.toml declares zero dependencies. The README calls OpenCV and scikit-image "optional," and they genuinely are - the node falls back gracefully. But that fallback is silent. Without opencv-python you don't get poisson, multiband, or gaussian blending at all; the default blend becomes plain alpha, and the only hint is a warning in the console. That's the number one "why does my merge look bad" complaint. Install the extras in ComfyUI's Python environment:
pip install opencv-python scikit-image
The node itself comes from the pack via ComfyUI Manager (search "MGnodes") or git clone https://github.com/meanin2/comfyui-MGnodes.git into custom_nodes/, then restart.
Common issues
- Nothing got merged -
thresholdtoo high, so no difference was detected; or the two images are near-identical. Lower the threshold. - Everything got merged - threshold too low or
global_thresholdoverwhelmed by a global shift (Kontext brightening the whole frame). Raisethreshold, or switch detection tocolor_diff. - Missing poisson - see the dependency trap above.
- Resolution mismatch - the node resizes the edited image to match the original, so feeding wildly different resolutions produces mushy merges. Keep both at the same resolution; the canonical workflow is to crop tight to the region you're editing (Kontext quality degrades at full-body scale anyway), edit, then merge back into the full-res original.
For the crop-and-stitch editing workflows that are standard around Kontext and Qwen-Image-Edit, this node is the missing seam. It's rough around the edges - it's a personal pack, expect to tune threshold per image - but it does the one thing the edit models refuse to: leave the rest of your image alone.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| original_image | IMAGE | — | |
| edited_image | IMAGE | — | |
| threshold | FLOAT | 0.020.01–1 | Sensitivity of change detection; lower values detect more subtle changes |
| detection_method | COMBO | adaptive | Algorithm used to build the initial mask of differences |
| blend_method | COMBO | poisson | How to merge the edited pixels back onto the original |
| mask_blur | INT | 151–100 | Gaussian blur radius (in pixels) applied to the mask to soften edges |
| mask_expand | INT | 80–50 | Dilate the detected mask by this many pixels before blurring |
| edge_feather | INT | 150–50 | Additional feathering (fine Gaussian) after the main blur |
| min_change_area | INT | 2500–5000 | Ignore change blobs smaller than this area (pixel²) |
| global_threshold | FLOAT | 0.150.01–0.5 | Controls how aggressively the adaptive detector compensates for global shifts |
| manual_maskopt | MASK | User-supplied 1-channel mask (black/white) to override automatic detection |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| merged_image | IMAGE | — |
| difference_mask | MASK | — |
| preview_diff | IMAGE | — |