Image Harmonizer
Image Harmonizer color-matches a cutout to its new scene
- composite_image
- mask_image
- harmonized_image
You cut a subject out of one photo, dropped it into another scene, and it's the most obvious photoshop you've ever made. The shape is right, the edges are clean, but the light and color give it away: it's a picture of a person sitting in the picture, not a person in the room. This node is the quick fix for exactly that moment.
The Image Harmonizer is a one-trick port of ZHKKKe's Harmonizer, a classic deep image harmonization model. You feed it a composite (subject pasted onto a new background) plus the mask of the pasted region, and it adjusts the color and lighting inside that mask so the subject reads as part of the scene. Crucially, it never touches the background - only the masked pixels change, so nothing else in your frame moves. That "bit-identical everywhere else" property is the same reason masked inpainting still survives in an era of whole-image edit models: for a straight compositing fix you want the background left alone, and this node guarantees it.
What it actually does under the hood
The code is the academic Harmonizer architecture, nothing hidden: an EfficientNet-B0 backbone looks at the composite and mask (shrunk to 256×256 just for the analysis), a cascade regressor predicts six numbers, and a set of learned filters applies them. Those six arguments are color temperature, brightness, contrast, saturation, highlight, and shadow, each clamped to [-1, 1]. Each filter is applied as filtered * mask + original * (1 - mask), so only the masked region is ever modified. The nice detail: the argument prediction runs at low resolution, but the filtering itself happens at your full input resolution, so the output isn't blurry where it matters.
The weights are a ~19 MB harmonizer.pth bundled directly in the repo - no separate model download, no license dance. It runs on CUDA if you have it and quietly falls back to CPU if you don't.
The inputs and the one output
There are exactly two inputs, both plain IMAGE tensors:
- composite_image - the already-pasted image (subject on its new background).
- mask_image - a mask of the pasted region. White where the subject is, black everywhere else.
And one output, harmonized_image, which you wire straight into whatever's next in your graph - VAE encode for another pass, upscale, save. The mask should match the composited region or it'll harmonize the wrong pixels; a sloppy feather is fine, a whole-background mask is not.
Installing it
ComfyUI Manager is the easy path - search for "Image Harmonizer" (pack title sweetndata/ComfyUI-Image-Harmonizer) and install. Or do it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/sweetndata/ComfyUI-Image-Harmonizer
Then restart ComfyUI. No model files to fetch - the weights are already in the repo.
Where people get burned
The repo's declared dependencies are a mess, and this is the one real trap. requirements.txt lists httpx, h2, and - bizarrely - googletrans-py, a leftover that has nothing to do with image harmonization. Meanwhile the code actually import kornia and import cv2 at node registration. ComfyUI ships torch and torchvision, so those are fine, but on a clean install kornia (and sometimes opencv) is missing and you'll get ModuleNotFoundError: No module named 'kornia' the moment the graph loads. Fix it once:
cd ComfyUI/custom_nodes/ComfyUI-Image-Harmonizer
../venv/bin/python -m pip install kornia opencv-python
Also set expectations: this is a 2021-era method with zero knobs - no strength slider, no mode toggle. When it nails it, it's great; when it's off, your only dial is the mask. For tough cases the generative route (an inpainting pass over the seam, or an instruction-edit model) still wins, but for a fast automatic color-match this is the one you reach for.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| composite_image | IMAGE | — | |
| mask_image | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| harmonized_image | IMAGE | — |