Nodes/trNodes/trColorCorrection
ComfyUI Node

trColorCorrection

Make one image borrow another image's colors

By trojblue·Created 3 years ago·Updated 2 years ago· 8
trColorCorrection
  • TARGET_IMAGE
  • reference
  • IMAGE
inverse selection

You've got a render that's technically fine but the palette is off - too cold, too saturated, just not the mood of the reference photo you're trying to match. trColorCorrection is the one-node answer: it reshuffles one image's colors to look like another's, then hands you back a version that keeps your image's shape and brightness. No ControlNet, no color-palette model, no sampler fiddling. Just two images in, one image out.

Why you'd reach for it: the classic case is palette drift. In A1111, apply_color_correction exists specifically to stop img2img from wandering off the source colors - this node is a direct port of that function (the code even links the original modules/processing.py). In ComfyUI the same need shows up when you generate something, look at it, and think "the look is right but the colors belong to that other image." Feed it your render as TARGET_IMAGE, a palette source as reference, and it re-grades the render in place. It's also handy for harmonizing a batch of images against one shared reference so they all sit in the same color family.

How it works

The actual mechanism is two steps, both inherited from the A1111 port:

  1. Both images are converted to the LAB color space, and the target's per-channel histograms are matched to the reference's using scikit-image's match_histograms (channel_axis=2). This is a global color transfer - it spreads the reference's color distribution across the target without knowing anything about where the colors sit.
  2. The result is then luminosity-blended with the original image. That's the clever part: you keep your image's brightness and detail, and only the color information comes from the reference.

Net effect: your render keeps its own lighting and edges, but wears the reference's palette. It's a proper color grade in ~10 lines of code, which is why this port keeps getting copied.

The inputs that matter

  • TARGET_IMAGE (required) - the image that gets recolored.
  • reference (required) - the image whose color look you want to copy.
  • inverse selection (False/True) - flips the direction. Default False means "make TARGET look like reference." Set it to True and it instead recolors the reference to match the target. You'll basically never touch this.

The single output is an IMAGE tensor, so it plugs into anything downstream - a VAE decode chain, a SaveImage, or another post-processing node.

Installing it

trNodes is a small repo with no model files to download; the weight is in its Python dependencies. Grab the pack:

cd ComfyUI/custom_nodes
git clone https://github.com/trojblue/trNodes

Then install the deps with ComfyUI's own Python, not your system python (the README targets the portable build, so it spells it as python_embeded/python.exe):

python_embeded/python.exe -m pip install opencv-python scikit-image blendmodes

Or install via ComfyUI Manager (search "trNodes"), then restart ComfyUI and you'll find the node under the trNodes category. One caveat: the repo has no requirements.txt, so even Manager won't install these dependencies for you - you still run the pip command once yourself.

Gotchas

Where people get burned:

  • The dependency trio is heavy. opencv-python and scikit-image are big installs and can occasionally fight an existing numpy/scipy in your environment. Install into ComfyUI's venv and expect the first run to take a while.
  • The shipped code has an input-name mismatch. In the current source, the UI exposes TARGET_IMAGE and reference, but the Python function behind it expects parameters named original_image and target_image. ComfyUI calls nodes by keyword, so a fresh clone can throw TypeError: color_correct() got an unexpected keyword argument 'TARGET_IMAGE' when the node executes. If you hit that, pull the latest commit or fix the function signature to match the input names - it's a five-second edit.
  • It's a global grade, not a spatial one. It will unify overall tint beautifully, but it can't make "just the sky bluer and the skin warmer." For targeted regrading you need masks and a proper compositing node.

Honest take: this is a niche, slightly rough tool from a small pack, and the name-vs-parameter bug is exactly the kind of thing that scares people off. But when you need "make this render's mood match that photo," it beats eyeballing CFG and samplers for an hour.

CategorytrNodes

Inputs (3)

NameTypeDefaultDescription
TARGET_IMAGEIMAGE
referenceIMAGE
inverse selectionCOMBO2 options: False, True

Outputs (1)

NameTypeDescription
IMAGEIMAGE