Nodes/ComfyUI_CineStyle/CS Color Match
ComfyUI Node

CS Color Match

Steal one reference's look and paint it over your whole clip

By chflame163·Created 14 days ago·Updated a day ago· 59
CS Color Match
  • image
  • reference_image
  • IMAGE
methodOptimal Transport
color_spaceOKLab
match_strength0.75
preserve_luminance1.00
preserve_contrast1.00
preserve_saturation0.00
hue_strength1.00
chroma_strength1.00

The problem CS Color Match solves is the one you hit the day your generated video comes out with a flat, blue-ish, unmistakably-AI look and you think "I wish it looked like that still I saved." You drop in one reference image - a film still, a graded plate, a frame from a clip you actually like - and the node drags that reference's overall mood across your entire IMAGE batch. No model weights, no prompt, no re-rolling the generation and hoping. It's a deterministic color transform, milliseconds-to-seconds per clip, and it's the honest fix for "the colors are off" that post-processing exists for.

It ships in chflame163's ComfyUI_CineStyle, a set of lightweight video-workflow nodes. Real talk: this is not DaVinci Resolve. It's a batch of targeted video fixes - load/save, subtitle, grade, segment - and Color Match is among the most useful.

How it works

The node samples pixels from your source batch and from the reference, converts them into a perceptual color space, and fits a single transfer that reshapes the source's color statistics toward the reference's. Then it applies that transform point-wise to every frame. Two things make it video-safe rather than a per-frame gamble:

  • One transform for the whole clip. Statistics are gathered across up to 24 evenly spaced frames of the batch, not frame 1. Because the fitted transform doesn't change between frames, you don't get the temporal flicker a naive frame-by-frame match would give you.
  • It never blurs or resamples. No spatial filtering, so edges and texture stay exactly as the sampler produced them.

Color matching happens in Lab or OKLab (default). OKLab separates lightness from hue and chroma in a way that tracks human perception - that's why it's the recommended default and why the "preserve" controls below can exist at all. The transfer is fit in Cartesian a/b coordinates, but the strength knobs act in polar hue/chroma, which is what lets you match the mood without wrecking exposure. Out-of-gamut output gets chroma-compressed rather than hard-clipped, and frames are processed in GPU-sized chunks with an automatic halving of the batch if you OOM.

The inputs that matter

Only two inputs are non-negotiable: image (your IMAGE batch) and reference_image (only the first image is used - wire in a single still). The rest are controls you'll actually touch:

  • method - the color transfer algorithm, defaulting to Optimal Transport. The short version:
    • Reinhard - matches per-channel mean and standard deviation. Conservative and fast; the classic.
    • LHM - linear match via covariance. Good for an overall color-style shift.
    • PCCM - matches principal-component axes. More aggressive, more dramatic.
    • Optimal Transport - regularized Gaussian OT. The default, and the best all-rounder.
    • PDF - distribution matching via multiple projections. Handles complex, multi-peak palettes, and is noticeably slower.
  • match_strength (default 0.75) - how far you go from source toward the reference target. 0 is a pass-through.
  • preserve_luminance (default 1) - keep your source's exposure; match color, not light. For video you usually leave this at 1, since you don't want a clip darkening/flickering in brightness.
  • preserve_contrast (default 1) - restore the source's own contrast distribution.
  • preserve_saturation (default 0) - hold source chroma. Turn it up if the match oversaturates.
  • hue_strength / chroma_strength - finer knobs on hue and chroma matching. Note hue changes are automatically damped in low-chroma regions, which is what stops neutral areas from picking up a color cast.

Output is a single IMAGE - the matched RGB frames, same size, ready to feed straight into a CS Save Video or any downstream node.

Install

ComfyUI Manager, search ComfyUI_CineStyle, install, restart. Or the manual route:

cd ComfyUI/custom_nodes
git clone https://github.com/chflame163/ComfyUI_CineStyle.git

Then restart ComfyUI. One thing worth knowing: this pack is written against ComfyUI's newer extension API (ComfyExtension / comfy_entrypoint), not the classic NODE_CLASS_MAPPINGS style - so it needs a reasonably recent ComfyUI. If the nodes don't appear after restart, update ComfyUI first. The requirements.txt lists a scary pile of ML dependencies (transformers, accelerate, timm, av…), but those serve the video-segmentation nodes - CS Color Match itself only needs torch, which ComfyUI already provides. The pack loads each module independently and skips the ones that fail, so even on a machine where the heavy stuff won't install, Color Match shows up fine.

Gotchas

  • The reference should be one strong, representative image. If you feed it a frame whose color is off, you're transferring the problem, not the look.
  • Because the match is global-statistics, it fixes an overall cast - it can't do localized grading or match one object against the reference.
  • match_strength at 1 with default preserve knobs will push chroma hard; the sane starting recipe is Optimal Transport + OKLab, strength 0.75, and preserve-luminance on, exactly the defaults. Adjust from there.
Category😺dzNodes/CineStyle

Inputs (10)

NameTypeDefaultDescription
imageIMAGESource IMAGE batch; a batch is processed in its original frame order.
reference_imageIMAGEReference IMAGE; only the first image is used.
methodCOMBOOptimal TransportGlobal color transfer method.
color_spaceCOMBOOKLabColor space used for statistics and transfer.
match_strengthFLOAT0.750–1Overall interpolation from the source to the matched lightness, hue, and chroma target.
preserve_luminanceFLOAT1.000–10 to 1, where 1 keeps source perceptual lightness.
preserve_contrastFLOAT1.000–10 to 1, where 1 restores source luminance contrast.
preserve_saturationFLOAT0.000–10 to 1, where 1 keeps source chroma.
hue_strengthFLOAT1.000–1
chroma_strengthFLOAT1.000–1

Outputs (1)

NameTypeDescription
IMAGEIMAGE