Create CA Calibration
Synthesize a chromatic-aberration profile on purpose
What it's for
Chromatic aberration is what a lens does when it can't focus all three colours on the same plane: red and blue land slightly off from each other, and you get colour fringing along high-contrast edges - a red/cyan halo on the sides of a wide shot. Two directions you might want to go with that.
You might want to correct it, because you're cleaning up real footage. Or you might want to add it, because a tiny bit of lateral CA is one of the tells that separates "photo" from "render" - it's on the short list, next to grain and vignetting, in every thread about why AI output looks fake (the KB's post-processing notes collect that argument, and 233 threads on film grain alone back it up).
This node gives you the profile file both directions need. It writes a YAML calibration into ComfyUI/input/calib/ describing a uniform, constant displacement for the red and blue channels, and that same file is accepted by CV Apply Chromatic Aberration (to simulate fringing) and CV Chromatic Aberration Correction (to remove it).
How it works
Under the hood it's OpenCV's FileStorage writing a small YAML: an image_width / image_height, then red_channel and blue_channel blocks, each with coeffs_x and coeffs_y. The polynomial is degree 1 - three coefficients - and only the first one is populated, which is why the displacement comes out constant across the frame instead of growing toward the corners. An rms field is written as 0.0, the file being authored rather than fitted.
That constant-ness is the thing to hold in your head. Real lateral CA is radial: zero at the optical centre, growing outward. A uniform shift moves the whole red channel the same amount in the same direction, so it approximates fringing well in the middle of the frame and overshoots or undershoots toward the edges. For simulation and for testing a correction chain, that's fine. For fixing a real lens, it's an approximation, and you'll see residual colour on the outer thirds.
The inputs that matter
Four displacement values, all floats from -500 to 500 in 0.5-pixel steps:
- red_dx, red_dy - horizontal and vertical shift of the red channel; positive x is right, positive y is down.
- blue_dx, blue_dy - same for blue.
Then calib_width and calib_height (default 512×512), which record the reference resolution the coefficients are normalized against - set them to the size you'll actually be correcting. And filename (default ca_synth.yaml), written into input/calib/. It overwrites silently if the name already exists; the node strips any directory part of the path before writing, so you can't accidentally write outside the folder.
There are no outputs. It's an output node: it runs when you hit Run, and reports the saved path and the four offsets as a text preview on the node.
The default is 0, 0, 0, 0, which produces a perfectly valid calibration file that does nothing. That's not a bug - it's the zero point you dial from.
Install
ComfyUI Manager, search ComfyUI CV. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
Restart, and install the contrib wheel if the pack didn't:
pip install "opencv-contrib-python-headless~=5.0.0.93"
Python ≥ 3.12, plus a ComfyUI new enough for the V3 node API.
Where people get burned
The downstream dropdown doesn't show your new file. Run the node, then set the calibration filename in CV Apply Chromatic Aberration or CV Chromatic Aberration Correction - and if it isn't in the list, reload the ComfyUI page. Dropdowns are built when node definitions are fetched, so files created during a session aren't always visible until a refresh. Same rule the pack's own example-input installer warns about.
You ran it and nothing happened. Nothing is exactly what's supposed to happen: no outputs, no image, just a file. Check the node's text preview for the path it wrote, and check you picked the same filename downstream.
"My correction isn't working." Compare sign conventions before you blame the node. A constant shift fixes fringing on one side of the frame and worsens it on the opposite side, because the real error is radial. If the picture gets better on the left and worse on the right, this is the wrong model for that lens.
Half-pixel steps are there for a reason. At 0.5 px granularity you can dial in subtle fringing; at 5 px you're doing a bad 3D-glasses gag. Start at 1–2 px for a visible simulation, and around 0.5 for "just enough to sell it".
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| red_dx | FLOAT | 0.0-500–500 | Horizontal displacement of the red channel in pixels (positive = red shifts right). |
| red_dy | FLOAT | 0.0-500–500 | Vertical displacement of the red channel in pixels (positive = red shifts down). |
| blue_dx | FLOAT | 0.0-500–500 | Horizontal displacement of the blue channel in pixels (positive = blue shifts right). |
| blue_dy | FLOAT | 0.0-500–500 | Vertical displacement of the blue channel in pixels (positive = blue shifts down). |
| calib_width | INT | 5121–100000 | Calibration image width in pixels (used to normalise the polynomial coordinate system). |
| calib_height | INT | 5121–100000 | Calibration image height in pixels. |
| filename | STRING | ca_synth.yaml | Output filename. Saved to input/calib/. Overwrites if it already exists. |
Outputs (0)
No outputs