Nodes/ComfyUI CV/CV Apply Color Correction
ComfyUI Node

CV Apply Color Correction

The other half of the CCM pair — and the easy half

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Apply Color Correction
  • image
  • ccm_model
  • IMAGE

A colour correction model, in this pack's sense, is a fitted transform that maps one camera's colour rendering onto another's - or onto a reference chart's. This node applies one. It has two inputs, no settings, and no opinions: the decisions all happened upstream in CV Create CCM Model, and this is where they get executed.

Why you'd reach for it

Colour matching is the underrated move in the deterministic layer, and it's worth being blunt about why it's better than re-generating: it's instant, it's reproducible, and it doesn't reroll your composition. The usual jobs:

  • Make a batch consistent. A dozen frames from the same shoot, all drifting slightly; one fitted model applied to all of them pulls them together.
  • Match a composited element to a plate. Two different captures, one look.
  • Sit a camera's output next to a reference. This is what the classic workflow is: shoot a Macbeth chart, detect it, fit, apply.

Unlike the mean-and-standard-deviation colour transfer that most ComfyUI colour-match nodes do, a CCM is fitted against known reference values from a chart, which makes it a calibration rather than a stylistic nudge. That's the difference between "it looks closer" and "this is the transform that draws this camera's red where the reference says red goes".

How it works

The node holds a CCM_MODEL - a fitted ColorCorrectionModel from OpenCV's ccm module (contrib, class-based, which is why the pack hand-wrote the wrapper; a plain function generator can't reach create* factories). For each frame it calls the model's correctImage and re-clips the result to the input's own range: 0–255 uint8 for 8-bit frames, 0–1 float for float tensors. Then the frames are reassembled into the batch.

The maths behind it is linear at heart: a 3×3 matrix (or 4×3 for the affine variant, which adds an offset per channel), fitted least-squares against the chart's measured patches. That's why the fit node's options matter - the degree of the polynomial used when fitting is what lets it absorb a non-linear camera response, and the resulting matrix is what you're applying here.

The inputs and outputs

  • image - the frame(s) to correct. A batch is processed frame by frame.
  • ccm_model - the fitted model, wired from CV Create CCM Model. There is nothing else. No strength, no blend, no gamma.

Output: IMAGE. Same size, same batch length.

The little inspection habit worth building

Because everything lives in the model, checking the fit means looking at the model - and the pack ships the two nodes for it. CV Get CCM Matrix gives you the matrix itself: 3×3 for the linear model, 4×3 for the affine one. CV Get CCM Loss gives you the fit quality, and lower is better. Run that pair once when you build the workflow: a loss that's an order of magnitude above what you saw on a good chart means the detection or the patch sampling upstream went wrong, and no amount of staring at the corrected image will tell you that as quickly.

If you want the matrix as data rather than as a diagnostic, it's a plain NPARRAY - feed it to CV Array To Text and write it down, and that number is now a reusable calibration you could apply elsewhere or hand to someone else.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv

then restart ComfyUI, or use Manager → search ComfyUI CV. opencv-contrib-python-headless~=5.0.0.93 is required and the contrib part is non-negotiable here - ccm is a contrib module, so on a non-contrib wheel both this node and its fit sibling are simply not registered. Python 3.12+ and a ComfyUI built on the V3 node API round out the requirements.

Traps

  • Correct, then grade. A CCM maps measured colour onto reference colour. Apply it before your creative grade, or the grade and the calibration will fight.
  • Clipping triangles. Rows of the corrected matrix that sum to well over 1 will clip saturated colours and flatten them. That's a fitting problem, not an applying problem - go back to CV Create CCM Model and simplify the model or the patch set.
  • It does not fix exposure. Well, the affine model's offset does a little, but a brightness error is a brightness error; correct it first, or the fit will spend its capacity compensating for it.
  • Frame by frame means exactly that. If you want temporal consistency across a clip, that's guaranteed by construction here (same model, same transform, every frame) - which is the strongest argument for using a CCM over any model-based colour pass.
Categoryimage/CV/ccm

Inputs (2)

NameTypeDefaultDescription
imageIMAGEInput image to correct. A batch is processed frame by frame.
ccm_modelCCM_MODELFitted model from 'Create CCM Model'.

Outputs (1)

NameTypeDescription
IMAGEIMAGE—