Nodes/ikki Pack/Color Matching Studio 🖼️
ComfyUI Node

Color Matching Studio 🖼️

Match a generation to a reference image without re-rolling the dice

By RedsAnalysis·Created 2 months ago·Updated about a month ago· 0
Color Matching Studio 🖼️
  • reference_image
  • generated_image
  • mask
  • matched_image
  • heatmap_image
  • active_mask
model_choiceAuto
mask_modeAuto
diff_threshold5.0
mask_dilation15
composite_bgtrue
local_refinementfalse

The "Studio" in the display name oversells it a little - there's no render farm here, no AI model, and nothing to download. IkkiColorMatching is a pixel math node that takes a reference image and a generated image, learns a color transformation between them, and applies it so your generation ends up in the reference's palette. If you've ever re-rolled a batch because "the colors are off," or fought to make an outpainted region agree with the original, this is the kind of fix that runs in milliseconds instead of another diffusion pass.

The reason a statistics-based color match is worth having is that color correction is not a diffusion job. The KB's post-processing essay puts it bluntly: doing color correction with img2img is the classic failure mode, because a re-gen also rewrites faces and content. A color transfer is deterministic and instant. This node is the fancy end of that family - instead of the usual mean/std (Reinhard) transfer you get from simple nodes, it actually fits a color model to the reference.

How it works

The pipeline behind the node does a few distinct things, roughly in order:

  1. Aligns the generated image to the reference using ECC (Enhanced Correlation Coefficient) affine alignment from OpenCV, so it's not thrown off by slight shifts in framing.
  2. Masks where the two images genuinely differ - in LAB space, pixels whose difference exceeds diff_threshold are treated as foreground to ignore while fitting, so the background's color relationship drives the model.
  3. Fits and selects a transformation: a linear 3×3 matrix plus bias, a polynomial, or a 3D LUT. In Auto mode it fits all three and picks the one with the best ΔE2000 score on a held-out validation split.
  4. Applies the transform, and optionally pastes the exact reference pixels back over unchanged background (composite_bg), feathering the boundary so the subject blends rather than floats.

Inputs that matter

  • reference_image and generated_image - the reference goes first. Batches are handled; a single reference can grade a whole batch.
  • model_choice - Auto, Linear, Polynomial, or 3D LUT. Auto is a solid default; LUT is the most flexible but slowest.
  • mask_mode - Auto, Manual, or Combine. The neat behavior: wire a mask into the optional mask input while it's set to Auto and it silently switches to Manual. Connect a mask from IkkiMaskEditor to scope the match to a subject.
  • diff_threshold (5) and mask_dilation (15) - control how aggressive the auto foreground/background split is. Raise the threshold if the whole frame keeps getting treated as "different."
  • local_refinement (off) - enable for a second, spatially-aware pass; only turn it on if global matching leaves patches obviously off.

Outputs are matched_image, heatmap_image (a colorized ΔE2000 difference map so you can see exactly where the match failed), and active_mask - the mask the node actually used, which is handy for debugging.

Installing it

Install the whole pack through ComfyUI Manager (search "ikki") or clone it:

cd ComfyUI/custom_nodes
git clone https://github.com/RedsAnalysis/comfyui-ikki-pack
# restart ComfyUI

The honest gotcha: the pack's pyproject.toml declares no dependencies, but this node imports OpenCV, scipy, and scikit-learn at module level. OpenCV ships with ComfyUI, but scipy and scikit-learn probably don't. If the node fails to import, install them manually:

pip install scikit-learn scipy

Common issues

  • Import error at startup - almost always the missing scipy/scikit-learn above. The node doesn't fail gracefully here; the whole pack fails to register. Install the two packages and restart.
  • Nothing appears to change - the match is subtle when the palette is already close; check the heatmap output to confirm the transform actually moved pixels.
  • The whole image is treated as foreground - your diff_threshold is too low relative to the actual difference, or the two images are too different to align. Consider cropping to the region that matters.

This node is the one I'd actually reach for when a batch needs to look like it was shot under the same light. Just be aware it's the heaviest dependency of the pack - and the author is brand new (one commit at the time of writing), so treat the first run as a quick smoke test.

Categoryikki-pack/color

Inputs (9)

NameTypeDefaultDescription
reference_imageIMAGE
generated_imageIMAGE
model_choiceCOMBOAuto4 options: Auto, Linear, Polynomial, 3D LUT
mask_modeCOMBOAuto3 options: Auto, Manual, Combine
diff_thresholdFLOAT5.01–30
mask_dilationINT151–51
composite_bgBOOLEANtrue
local_refinementBOOLEANfalse
maskoptMASK

Outputs (3)

NameTypeDescription
matched_imageIMAGE
heatmap_imageIMAGE
active_maskMASK