Nodes/kubakub nodes/kubakub colour match
ComfyUI Node

kubakub colour match

Steal the look off a still you like, without the flicker

By kubakubkub·Created about a month ago·Updated 2 days ago· 10
kubakub colour match
  • images
  • reference
  • mask
  • images
  • lut_file
◄methodmkl►
◄strength1.00►
◄save_lut►
◄lutnone►
◄lut_path►

What it's for

Three jobs, all the same operation. You have a frame whose colours you like and you want nine generated regions to sit in it. You have an upscaled or re-rendered patch that came back a slightly different temperature and now there's a visible rectangle. Or you're building a facade show and the client's brand palette has to survive the creative pass. The temptation is to re-roll the generation. Don't - that's a seed lottery when a statistics transfer is deterministic and instant.

kubakub colour match gives your frames the colours of a reference picture. Any size, any content: a still you like, a frame of another scene, a paint chip of the facade at dusk.

The KB's read on this layer is blunt and correct - color matching is the underrated post-process, and people keep re-generating instead of matching. ComfyUI's coverage of it is patchy, which is why packs like this one keep re-implementing it.

How it works

Two methods:

  • mkl (default) - a Munsell/Korhonen-style transfer that moves colours and their mix. Richer, more characterful, will occasionally do something surprising with a saturated accent.
  • mean_std - plain per-channel mean and standard deviation, i.e. the classic Reinhard-style transfer. Boring, predictable, and the right pick when you're matching an upscaled tile back into its neighbours and want zero drama.

The detail that saves you a headache on video: the transform is fitted once, from the first, middle and last frame, and then that single transform is applied to every frame. Per-frame fitting is how you get a grade that breathes and pumps. This one can't flicker.

Inputs and outputs

  • images - the frames to grade.
  • reference - the look. Any size, any content, only its statistics are used.
  • method - mkl or mean_std.
  • strength - 0 to 1, default 1. 1 is the whole look, 0 is your frames as they are. Somewhere around 0.6 is where most "match this" work actually lives.
  • save_lut - a name with no extension. Fill it in and you get output/kubakub_luts/<name>.cube, which is a real deliverable: drop it into After Effects, Resolume, MadMapper or Resolve and the house system plays your look on the building. That pairs it directly with kubakub apply lut, which reads the same folder.
  • mask (optional) - grade only inside it. Grey is partial, and a mismatched size is resized.

Outputs are images and lut_file - the written path, or empty. Note the .cube is always the full look fitted on the whole frame-to-reference pair, even when a mask limits what happens to the frames. The KB's point about deterministic post beats generative re-rolls applies double here: this is the $0, millisecond, repeatable option.

Install

Manager → search kubakub nodes, install, restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/kubakubkub/ComfyUI_KubaNodes
python -m pip install -r ComfyUI_KubaNodes/requirements.txt

The pip line is just OpenCV headless; keep an existing OpenCV build if you have one. ComfyUI 0.37.0+ is required.

Common issues

  • The match is too strong. That's not a bug, that's strength at 1. Pull it down before you blame the method.
  • It killed your highlights. mean_std matches means and deviations, so a dark reference will drag a bright frame down and vice versa. mkl handles the mix better; try it before you start hand-grading.
  • You want it on part of the frame only. Use mask - but remember the saved .cube covers the whole frame, so what you write out won't equal what you just rendered. Grade, then save the LUT, then apply the LUT with a mask if you need both.
  • The output looks flat next to the reference. Colour statistics aren't a film emulation. If the reference's character is in its grain and halation, match the colours and add the grain separately.
Categorykubakub/2d/post

Inputs (8)

NameTypeDefaultDescription
imagesIMAGEThe frames to grade.
methodCOMBOmklreference: mkl = colours and their mix (richer); mean_std = per channel brightness and contrast.
strengthFLOAT1.000–1How much of the look: 1 = all of it, 0 = the frames as they are.
save_lutSTRINGName for a .cube file in output/kubakub_luts/ (empty = no file).
referenceoptIMAGEThe look to match (any size, any content). Nothing connected: pick a .cube in 'lut'.
maskoptMASKGrades only inside this mask (white = full, grey = partly); outside the frames stay as they are. One mask serves every frame; another size is resized.
lutoptCOMBOnoneA .cube look from input/luts, models/luts or output/kubakub_luts (none = only the reference). New files show after a refresh of the page.
lut_pathoptSTRINGAny .cube file by its path; wins over the list.

Outputs (2)

NameTypeDescription
imagesIMAGE—
lut_fileSTRINGThe written .cube (or empty).