cv2.stereoRectifyUncalibrated
Rectifying a stereo pair you never calibrated
- points1
- points2
- F
- imgSize
- retval
- H1
- H2
Two photos of the same scene from two positions, no calibration data, no idea of the lens. That's the normal situation, and stereoRectifyUncalibrated is the Hartley method for it: give OpenCV enough matched point pairs and let it derive the rectifying transformations from the geometry of the matches themselves.
The output is not the same kind of thing the calibrated version gives you. Where cv2.stereoRectify hands back rotations and projection matrices, this one hands back two 3x3 homographies - H1 and H2 - and you apply them to the pixels yourself with cv2.warpPerspective. Get that wrong and you'll spend an evening feeding homographies into initUndistortRectifyMap and wondering why nothing lines up.
One of roughly 470 auto-generated raw cv2.* wrappers in ComfyUI CV (bmad4ever/comfyui_cv); LLM-written, uncurated, per the pack's own disclaimers.
Inputs
Four required, all NPARRAY - data arrays, not images:
points1,points2- corresponding feature points, in the formatfindFundamentalMataccepts. Get them from CV Detect Features plus CV Match Features, keeping the match geometry intact.F- the 3x3 fundamental matrix, fromcv2.findFundamentalMat(CV Find Fundamental Matrix in this pack, which also returns the inlier mask you should be selecting with).imgSize- a(width, height)CV_TUPLE, the size of the pair you're rectifying.
One optional number: threshold, default 5. Points whose epipolar error exceeds it are treated as outliers and dropped before the homographies are computed. That's the whole robustness story here - if your matches are sloppy, this is the dial that saves you, and 5 pixels is a reasonable amount of slop for a first try.
Outputs
retval (BOOLEAN - did it converge), then H1 and H2. On failure you get false and two identity-ish matrices, so always branch on retval rather than trusting the homographies.
Downstream, H1 and H2 go into cv2.warpPerspective - one per image. The pack ships a curated node that does this exact job end-to-end, CV Stereo Rectify (Uncalibrated), which takes the two point sets, the fundamental matrix and a reference image for the size, and returns H1, H2 and a found flag. If you just want a rectified pair, that's the node to use; reach for cv2.stereoRectifyUncalibrated when you want the OpenCV call itself, or want to feed the homographies somewhere the curated node doesn't.
The order of operations that works
Feature points → matches → filter inliers → findFundamentalMat → this node → warpPerspective on each image → disparity or flow. Skipping the inlier filter is the classic mistake; uncalibrated rectification with outliers is a random number generator. The threshold parameter is your second line of defence, not your first.
Also worth knowing: this is the uncalibrated path. If you have intrinsics - even rough ones from a phone's EXIF or a chessboard pass - the calibrated route gives you a physically meaningful Q matrix and real depth. This one gives you rectified images and no metric scale at all, which is fine for disparity-looking demos and useless for measuring anything in metres.
Installing the pack
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
cd comfyui_cv && pip install "opencv-contrib-python-headless~=5.0.0.93"
Manager → search ComfyUI CV → install → restart works too. Python ≥ 3.12 and a ComfyUI with the V3 node API are required - on an older install these nodes don't show up at all. Use a contrib OpenCV wheel: all distributions share one site-packages/cv2, so a stray pip install opencv-python empties the contrib submodules and contrib nodes disappear; tools/repair_opencv_contrib.py --check then --apply fixes it. Behaviour is pinned to 5.0.0.93, and no support is promised for the pack.
Common issues
imgSize left at (0, 0) - the default is a placeholder, not a convenience. Points in the wrong layout: points1/points2 need the same convention findFundamentalMat produced, and a transposed array produces a plausible-looking retval: true with useless homographies. And the big one: expecting rotations. H1/H2 are projective; warp with them.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| points1 | NPARRAY | Array of feature points in the first image. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| points2 | NPARRAY | The corresponding points in the second image. The same formats as in #findFundamentalMat are supported. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| F | NPARRAY | Input fundamental matrix. It can be computed from the same set of point pairs using #findFundamentalMat . A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| imgSize | CV_TUPLE | 0,0 | Size of the image. One value with 2 components (w, h) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place. |
| thresholdopt | FLOAT | 5.0000-1e+38–1e+38 | Optional threshold used to filter out the outliers. If the parameter is greater than zero, all the point pairs that do not comply with the epipolar geometry (that is, the points for which $|\texttt{points2[i]}^T \cdot \texttt{F} \cdot \texttt{points1[i]}|>\texttt{threshold}$ ) are rejected prior to computing the homographies. Otherwise, all the points are considered inliers. The function computes the rectification transformations without knowing intrinsic parameters of the cameras and their relative position in the space, which explains the suffix "uncalibrated". Another related difference from #stereoRectify is that the function outputs not the rectification transformations in the object (3D) space, but the planar perspective transformations encoded by the homography matrices H1 and H2 . The function implements the algorithm . Preset to the OpenCV default (5.0). |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| retval | BOOLEAN | — |
| H1 | NPARRAY | — |
| H2 | NPARRAY | — |