CV Load Camera Params (JSON)
Calibrate once, reuse those numbers forever
- camera_matrix
- dist_coeffs
- image_width
- image_height
- rms_error
Camera calibration is the boring step that makes the interesting steps work: cv2.undistort needs the intrinsic matrix K and the distortion coefficients, solvePnP and projectPoints need K, stereo rectification needs K and dist for both cameras. You compute it once - the pack has chessboard, circle-grid and ChArUco calibration nodes for that - and then you never want to compute it again. CV Load Camera Params (JSON) reads it back from a JSON file written by the matching save node.
What you get
file is a dropdown, and the search order is worth knowing: JSON files in the output folder first, then the input folder. Output first because that's where CV Save Camera Params (JSON) writes, so the usual round trip - calibrate, save, load in the next workflow - just works. Input second so a calibration file you've filed away in your inputs still shows up.
Five outputs, and the author documents the when-it's-absent behaviour rather than hiding it: camera_matrix (3×3 float64 intrinsic K), dist_coeffs (as stored, float64), image_width, image_height, and rms_error. Those last three come back as 0 if the file didn't record them - so a zero width isn't an error, it's a file written by something that didn't store it. rms_error is the reprojection error from calibration in pixels; if it's present and it's large, your calibration is bad and everything downstream inherits that, which is the one number here you should actually look at.
dist_coeffs is passed through as stored, which means the length is whatever the writer produced - 4 or 5 for classic Brown-Conrady, more for rational models, and a fisheye calibration is a different animal entirely. Don't assume length 5 in the code that consumes it.
The one gotcha
Reload the page after saving a new file. The dropdown is built when ComfyUI fetches node definitions, so a calibration JSON you just wrote this session won't be in the list until you refresh - and then it looks like the save failed, which sends people debugging the wrong node. This is the same behaviour as the pack's other file pickers, including CV Install Example Inputs.
If you're on an unusual layout, remember these paths are ComfyUI's documented output/ and input/ folders, so a mounted or relocated outputs directory moves the first search location with it.
Install
ComfyUI Manager, search the pack title comfyui_cv (bmad4ever/comfyui_cv), or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
Restart ComfyUI. Requirements: Python ≥ 3.12 and a recent ComfyUI on the V3 node API - this pack is written as io.ComfyNode classes with io.Schema schemas and ships no NODE_CLASS_MAPPINGS at all, so an older build won't load it. Its single dependency:
pip install "opencv-contrib-python-headless~=5.0.0.93"
Pinned to the curated reference build, and it needs to be contrib - all four OpenCV wheel distributions share the same site-packages/cv2, so installing a non-contrib wheel over a contrib one silently empties the contrib submodules and contrib nodes leave the menu without an error. The pack's tools/repair_opencv_contrib.py --check / --apply exists for exactly that.
Where this fits
Undistortion of a captured clip before any of the pack's remap chains, pose estimation for augmented-reality-style overlays, and stereo work. The camera JSON sidecars also ship with the example inputs - the pack's example_inputs/ folder contains calibration .json/.yaml/.csv/.txt files alongside the photos, so the sample workflows run with real intrinsics rather than a made-up K.
One caution that spans the pack: the README states outright that it was built with heavy LLM assistance, that some workflows were tuned against specific datasets, and that it isn't production-grade without you reviewing the source. Calibration data is exactly the kind of thing where a wrong sign or swapped coefficient is invisible until your 3D overlay is subtly skewed, so if the numbers look right in one view and wrong in another, verify the JSON against the save node's own output before blaming your maths.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| file | COMBO | Saved camera-params JSON to load (output folder first, then input folder). |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| camera_matrix | NPARRAY | 3x3 float64 intrinsic matrix K. |
| dist_coeffs | NPARRAY | Distortion coefficients as stored (float64). |
| image_width | INT | Recorded image width in px, or 0 if absent. |
| image_height | INT | Recorded image height in px, or 0 if absent. |
| rms_error | FLOAT | Recorded reprojection RMS in px, or 0.0 if absent. |