Nodes/ComfyUI-Darkroom/Color Match (Reference)
ComfyUI Node

Color Match (Reference)

Make your image borrow another photo's color, the principled way

By jeremieLouvaert·Created 5 months ago·Updated 3 days ago· 101
Color Match (Reference)
  • image
  • reference
  • image
methodreinhard
intensity0.80
n_colors8
n_slices20
sample_size50000
seed42

You've got a shot whose colors you love - a reference - and a target image that needs to take on its character. Most people reach for a teal-and-orange slider and eyeball it. Color Match (Reference) does it for real: it shifts the target's color distribution toward the reference's, statistically, instead of guessing.

It's one of the most-used nodes in the Darkroom pack (the AKURATE/Darkroom/Grading subcategory), and it shows up a lot in colorist-style workflows where you want a specific film or cinematic look without recreating it by hand.

How it works

The match happens in LAB color space - the perceptually uniform one, where "distance between colors" means roughly what your eye means by it. Then it picks between four transfer algorithms via the method dropdown:

  • reinhard - mean/std transfer. Fast, stable, and the safe default. Best when the reference is one cohesive tone.
  • wasserstein - sliced optimal transport via iterative advection. Handles multi-modal distributions (a reference with several distinct color populations) better than reinhard.
  • forgy - K-means palette matching with Gaussian-weighted soft assignment. Builds an 8-color palette (tune with n_colors) and remaps to it. Needs sklearn, which ships with most ComfyUI installs.
  • kantorovich - closed-form Gaussian linear transport. The mathematically fanciest option, and it needs pip install POT to exist at all.

These algorithms are adapted from the MIT-licensed rajawski/gradia project, and the author keeps the attributions honest in the source.

The inputs that matter

You'll set three things and ignore the rest at first:

  • image - the target you're grading (this is the one that changes).
  • reference - the image whose color character you want.
  • method - start with reinhard; try wasserstein if the reference has multiple strong color regions.
  • intensity - the blend between original (0) and full match (1). Default is 0.8, and that's a sane place to start; a full 1.0 match often overreaches on skin.

The optional n_colors, n_slices, sample_size, and seed are per-method tuning knobs - n_colors for forgy's palette, n_slices for wasserstein's advection iterations, sample_size for how many pixels get sampled during fitting, and seed so you can reproduce a run.

Output is a single image, which wires straight into the rest of your grade.

Where people get burned

  • Kantorovich silently downgrades. If POT isn't installed, the node logs a warning and falls back to reinhard. You'll get a result either way - just not the one you asked for. Install it with pip install POT if you want that method.
  • Don't put it in a LUT bake chain. Color Match is reference- and content-adaptive, like Auto White Balance: it reads the whole image to decide the transform, so it can't be baked into a per-pixel .cube. Same reason it's absent from the README's bake-allowed list.
  • Intensity is your friend. A hard 1.0 match can blow out the target's own character. Dial back to 0.5–0.7, then stack a gentle tone curve on top.

Installing the pack

Darkroom is a 54-node suite (this node lives in it), so you install the whole thing once:

cd ComfyUI/custom_nodes
git clone https://github.com/jeremieLouvaert/ComfyUI-Darkroom.git
pip install -r ComfyUI-Darkroom/requirements.txt

Or search "Darkroom" in ComfyUI Manager and let it handle the dependencies - it needs scipy, opensimplex, rawpy, exifread, and Pillow. Restart ComfyUI and every node shows up under AKURATE/Darkroom/. No API keys, no model downloads, and it runs happily on CPU since it's pure numpy/scipy.

The classic ComfyUI dependency gotcha applies: if Manager installs it into an environment that already has conflicting scipy, you may need to re-run pip install -r by hand. But this pack is lightweight compared to most - the heavy optional dependency (POT) is only for that one color-match method.

CategoryAKURATE/Darkroom/Grading

Inputs (8)

NameTypeDefaultDescription
imageIMAGEThe image to grade (target)
referenceIMAGEThe image whose colour character to match
methodCOMBOreinhardreinhard: fast mean/std. wasserstein: multi-modal OT. forgy: palette K-means (sklearn). kantorovich: Gaussian OT (POT).
intensityFLOAT0.800–1Blend between original (0) and full match (1)
n_colorsoptINT84–16Forgy only: palette size
n_slicesoptINT204–200Wasserstein only: advection iterations
sample_sizeoptINT500005000–500000Wasserstein/Kantorovich/Forgy: pixels sampled for fitting
seedoptINT420–4294967295Random seed (determinism)

Outputs (1)

NameTypeDescription
imageIMAGE