Nodes/ComfyUI CV/Create CA Calibration
ComfyUI Node

Create CA Calibration

Synthesize a chromatic-aberration profile on purpose

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
Create CA Calibration
      ◄red_dx0.0►
      ◄red_dy0.0►
      ◄blue_dx0.0►
      ◄blue_dy0.0►
      ◄calib_width512►
      ◄calib_height512►
      ◄filenameca_synth.yaml►

      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".

      Categoryimage/CV

      Inputs (7)

      NameTypeDefaultDescription
      red_dxFLOAT0.0-500–500Horizontal displacement of the red channel in pixels (positive = red shifts right).
      red_dyFLOAT0.0-500–500Vertical displacement of the red channel in pixels (positive = red shifts down).
      blue_dxFLOAT0.0-500–500Horizontal displacement of the blue channel in pixels (positive = blue shifts right).
      blue_dyFLOAT0.0-500–500Vertical displacement of the blue channel in pixels (positive = blue shifts down).
      calib_widthINT5121–100000Calibration image width in pixels (used to normalise the polynomial coordinate system).
      calib_heightINT5121–100000Calibration image height in pixels.
      filenameSTRINGca_synth.yamlOutput filename. Saved to input/calib/. Overwrites if it already exists.

      Outputs (0)

      No outputs