cv2.recoverPose (4/4)
The overload that triangulates while it decomposes
- E
- points1
- points2
- cameraMatrix
- mask
- retval
- E
- R
- t
- mask
What's different about this one
Same job as the rest of the family - essential matrix in, relative camera pose out, cheirality check included - but with an extra required input: distanceThresh. It exists because this overload doesn't stop at the pose. It triangulates the inlier correspondences as part of the decomposition, and distanceThresh filters the result: points further away than that get discarded, which is a crude way of throwing out the far-away correspondences that behave like "points at infinity" and contribute nothing but noise to a two-view estimate. The OpenCV docstring the pack carries says exactly that: "threshold distance which is used to filter out far away points (i.e. infinite points)".
The other three overloads hand you a mask and let you triangulate yourself with CV Triangulate Points (Two-View). This one is the "I want both at once" path.
Inputs
- E - 3×3 essential matrix. Note you supply E and the node re-emits an E-named output; this is the overload where you should double-check what's actually in each socket (see below).
- points1, points2 - matched point sets, NPARRAY only. Not images.
- cameraMatrix - 3×3 intrinsics.
- distanceThresh - required, defaults to 0 in the widget. That default is a trap in the sense that a 0/very small threshold filters aggressively; the tooltip describes it as a filter on far points, so pick a number in whatever units your triangulation comes out in, not "0 means off".
- mask - optional inlier mask.
Outputs, and a caution
retval (inliers used), then four array slots the pack labels E, R, t, mask.
R is 3×3, t is 3×1, the mask is N×1 uint8. So when something looks wrong, check the shapes before you file a bug - the pack's naming for a five-output overload is generic, and OpenCV's own documentation for the distanceThresh flavour describes the extra array as the triangulated points (the ones that survived the distance filter), not as an essential matrix. If a downstream node rejects a socket with a shape complaint, or your "E" doesn't look like a 3×3 matrix, that's the label drifting from the content, and you're looking at the points array.
Since these wrappers are auto-generated from type stubs and the pack's own README is candid that they're uncurated ("expect to handle conversions and edge cases yourself"), reading the actual output with CV CV Inspect or CV Array Shape is the fast way to sort out which slot is which in your build. Two minutes, versus an afternoon of debugging a matrix multiply.
When it's the right tool
If you're rebuilding two-view SfM by hand and you want the triangulated cloud and the pose from one call, this is the most compact route: E from findEssentialMat, feed it here with a sensible distanceThresh, and you have R, t and a filtered point set.
If you're not rebuilding two-view SfM, use the pack's curated nodes instead. CV Recover Pose (Essential Matrix) gives you the pose with a found flag and a real inlier_mask, and CV Triangulate Points (Two-View) does the triangulation as its own explicit step, in metric units, into a shape the 3D nodes actually accept (Nx3 clouds, PLY export, CV Write PLY, CV Preview 3D (Calibrated Camera)). Splitting the operation into two nodes you can inspect is worth more than saving a wire.
Scale, one last time
Translation is a unit vector in every overload. Even here, where the node triangulates, the triangulated points are in units of the baseline you fed it - and if the baseline came from the pose estimate itself, that baseline is 1.0 by construction. So the cloud you get out of this node is shaped correctly and sized arbitrarily. Scale it with a known object size, a measured baseline, or an ICP/similarity fit against something you trust (CV ICP Register, CV Register Point Clouds (3D)).
Install
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Manager route: search "ComfyUI CV" by bmad4ever. Requirements are Python ≥ 3.12 and a ComfyUI built on the V3 node API (comfy_api.latest); the pack's node classes are all registered that way, and on older ComfyUI versions nothing loads. Restart ComfyUI when it's done.
Traps worth knowing before you run it
- Both cameras assumed identical. This overload takes one
cameraMatrix, unlike variant 1/4, which takescameraMatrix1/distCoeffs1andcameraMatrix2/distCoeffs2. Different cameras → use variant 1/4. - A pure rotation or a flat scene breaks the estimate. Same degeneracy as every sibling here: no baseline, no pose.
distanceThreshin the wrong units. It's a distance in the triangulated coordinate frame, so with unit-scaletthe numbers are small and the threshold is effectively "in baselines". Sanity-check the surviving point count rather than trusting the number.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| E | NPARRAY | The output essential matrix. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| points1 | NPARRAY | Array of N 2D points from the first image. The point coordinates should be floating-point (single or double precision). A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| points2 | NPARRAY | Array of the second image points of the same size and format as points1 . A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| cameraMatrix | NPARRAY | Camera intrinsic matrix $\cameramatrix{A}$ . Note that this function assumes that points1 and points2 are feature points from cameras with the same camera intrinsic matrix. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| distanceThresh | FLOAT | 0.0000-1e+38–1e+38 | threshold distance which is used to filter out far away points (i.e. infinite points). |
| maskopt | NPARRAY,IMAGE,MASK | Input/output mask for inliers in points1 and points2. If it is not empty, then it marks inliers in points1 and points2 for the given essential matrix E. Only these inliers will be used to recover pose. In the output mask only inliers which pass the chirality check. This function decomposes an essential matrix using and then verifies possible pose hypotheses by doing chirality check. The chirality check means that the triangulated 3D points should have positive depth. Some details can be found in . This function can be used to process the output E and mask from . In this scenario, points1 and points2 are the same input for findEssentialMat.: 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. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| retval | INT | — |
| E | NPARRAY | — |
| R | NPARRAY | — |
| t | NPARRAY | — |
| mask | NPARRAY | — |