Nodes/ComfyUI CV/CV Stereo Rectify (Uncalibrated)
ComfyUI Node

CV Stereo Rectify (Uncalibrated)

Rectify Two Cameras Without Calibrating Either One

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
CV Stereo Rectify (Uncalibrated)
  • points_a
  • points_b
  • fundamental
  • image
  • H1
  • H2
  • found
◄threshold5.0►

Disparity matching only works when a scene point lands on the same image row in both views. That's what rectification buys you, and normally you pay for it with a full calibration: intrinsics per camera, distortion, a chessboard waved around the room.

This node is the shortcut. Given matched points and the fundamental matrix between two views, it computes two rectifying homographies - no intrinsics, no board, no idea what lens you're using. It's the Hartley method, and it's the right tool when you have two photos of the same scene (or two frames from a moving camera) and no way to calibrate the rig.

How it works

cv2.stereoRectifyUncalibrated takes corresponding points from both images plus the fundamental matrix F (the 3×3 relation between the two views that doesn't care about intrinsics), and returns H1 and H2. Warp the left image with H1 and the right with H2 and the epipolar lines become horizontal.

Two practical details decide whether you get a stable result:

Feed it inliers, not raw matches. CV Find Fundamental Matrix gives you an inlier_mask alongside F and a found flag; filter points_a and points_b with OpenCV Filter Points By Mask before wiring them here. RANSAC outliers are exactly the points that will bend your homographies into something useless.

Warp with a constant border. Apply H1/H2 with cv2_warpPerspective and borderMode=BORDER_CONSTANT. The default reflection border smears the edge of your image into the areas the warp pulls in from outside the frame.

The threshold input (default 5 px) drops points sitting further than that from their own epipolar line before solving - a cheap second cleanup pass. Set it to 0 to keep everything.

image supplies the rectification size: only its width and height are read, so pass either frame of the pair. It accepts a ComfyUI IMAGE, MASK or an NPARRAY.

Outputs: H1 (3×3 float64, for the LEFT image), H2 (for the RIGHT), and found.

Where it bites

The failure mode is well handled and therefore easy to miss. Fewer than 8 points, a degenerate configuration, or an all-zero fundamental matrix (i.e. CV Find Fundamental Matrix didn't find one) returns found=false with two identity homographies. Warping with an identity changes nothing, so the graph keeps running and your disparity stage silently produces a useless map on an unrectified pair.

Wire found into a branch and treat false as a hard stop, or at minimum print it. This is the node in the pack where ignoring a boolean costs you an afternoon.

The other caveat is intrinsic to the method, not the implementation: uncalibrated rectification gives you a consistent geometry, not a metric one. There's a residual projective ambiguity the calibration would have pinned down. For matching along scanlines that's fine. For measuring anything in millimetres, go back and use CV Stereo Calibrate (Chessboard).

Install

ComfyUI Manager → search ComfyUI CV (publisher bmad4ever), or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Restart after. Python ≥ 3.12 and a recent V3-API ComfyUI build. Keep the contrib wheel - a plain opencv-python install shares site-packages/cv2 and silently empties the contrib submodules. tools/repair_opencv_contrib.py --check / --apply handles the repair.

workflows/exercise_stereo_rectification.json is the whole chain end to end: load a pair, detect and match features, find F, filter inliers, rectify here, warp, then SGBM. Run workflows/01_install_example_inputs.json once and reload the page to get the sample stereo pairs in your input folder.

A quick sanity check on the wider pack

This node wraps one OpenCV call cleanly - but bmad4ever's README is candid that the project is a personal, heavily LLM-assisted effort, updates aren't planned, some nodes are curated compositions overfitted to particular datasets, and nothing here is production-ready without your own review. That's a fair description of the workflows. For a node like this one, where you can read the inputs and check the output yourself, it's not much of a worry.

Categoryimage/CV/features

Inputs (5)

NameTypeDefaultDescription
points_aNPARRAYMatched points in the left image, Nx1x2 (inliers from 'CV Filter Points By Mask').
points_bNPARRAYCorresponding points in the right image, Nx1x2.
fundamentalNPARRAY3x3 fundamental matrix from 'CV Find Fundamental Matrix' (all zeros -> found=false here).
imageNPARRAY,IMAGE,MASKEither rectified-pair frame; only its width/height are read (the rectification image size). Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
thresholdoptFLOAT5.00–100Points farther than this (px) from their epipolar line are dropped before solving. 0 keeps all points.

Outputs (3)

NameTypeDescription
H1NPARRAY3x3 float64 homography for the LEFT image (identity if not found).
H2NPARRAY3x3 float64 homography for the RIGHT image (identity if not found).
foundBOOLEAN—