Nodes/ComfyUI CV/cv2.findEssentialMat (1/3)
ComfyUI Node

cv2.findEssentialMat (1/3)

Cv2.findEssentialMat (1/3), the One That Wants Your Camera Matrix

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.findEssentialMat (1/3)
  • points1
  • points2
  • cameraMatrix
  • mask
  • E
  • mask
◄methodRANSAC►
◄prob0.9990►
◄threshold1.0000►
◄maxIters1000►

If you googled cv2.findEssentialMat and found three ComfyUI nodes with the same name, that's not a bug. cv2's Python binding exposes findEssentialMat as several overloads taking different ways of describing your camera, and this pack generates one node per overload. This is overload one, the plainest: you supply the full 3×3 intrinsic matrix.

First, why you'd care. Essential matrix E is the calibrated cousin of the fundamental matrix. It encodes the relative motion between two views of a scene - rotation and the direction of translation - and it's the front half of structure-from-motion, visual odometry and stereo pose recovery in ComfyUI. Knowing K is what makes E the right tool: with intrinsics, the geometry comes out in units of real camera rotation instead of an arbitrary projective frame.

Inputs

points1 and points2 are your matched correspondences, N points each, floating point, and they must come from the same matching step - CV Match Features produces exactly this layout. Both are data sockets: NPARRAY only. The pack's tooltips say so explicitly, because wiring a picture into a socket that wants Nx1x2 coordinates fails in confusing ways. OpenCV requires at least five points; fewer and the five-point solver has nothing to work with.

cameraMatrix is the 3×3 K, built with CV Camera Matrix (fx, fy, cx, cy) or handed over by CV Calibrate Camera (Chessboard). It's a data array too. If your two views don't share intrinsics, this isn't your overload - that's (3/3).

Three optional knobs actually get used: method (RANSAC by default, LMEDS available), threshold - the RANSAC inlier threshold in pixels, default 1.0, and the one you'll adjust, 1–3 being the sane band for real feature matches - and prob, the confidence, default 0.999. maxIters (1000) is there for the pathological case. There's also an optional mask input; ignore it. It exists because the C++ signature has an output buffer there, and cv2 ignores whatever you pass. The mask you want is the output.

Outputs

E is the 3×3 essential matrix (float64). mask is the Nx1 uint8 inlier mask - 1 for the points RANSAC kept, 0 for the outliers it rejected. That mask is the honest quality signal: an E built from 40 points where 6 are inliers is noise dressed as geometry. Feed it to CV Draw Matches to see which correspondences survived.

From there E goes into CV Recover Pose (Essential Matrix), which does the decomposition with a cheirality check and gives you rotation R and a unit translation - direction only, because monocular geometry has no scale. Or cv2_decomposeEssentialMat if you want the four candidate decompositions yourself. Inlier points plus R and t into CV Triangulate Points (Two-View) and you've got a sparse cloud.

One honest warning

E is estimated from point geometry, so it inherits geometry's failure modes: a scene that's effectively a single plane, or a camera that only rotated without translating, is degenerate and you'll get garbage that still looks numerically plausible. Translate the camera, keep depth in the frame, and branch on the inlier mask. The failure-tolerant curated nodes (CV Recover Pose, CV Find Fundamental Matrix) exist because the raw wrappers hand you the bad matrix with a straight face.

Install

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

Or install "ComfyUI CV" from ComfyUI Manager and restart. Python ≥ 3.12 and a V3-API ComfyUI.

Common issues

"Overload resolution failed" or a type error in cv2. Almost always the points: they must be float (single or double), shaped Nx1x2 or Nx2, and points1 and points2 must have the same length. Coordinates from an integer array will be rejected or silently mangled.

Everything runs, E looks like junk. Fewer than five valid matches, or matches that are mostly wrong. Look at the inlier count from the mask before believing E. A cheap diagnostic: CV Draw Matches with the mask will show you scattered nonsense immediately.

The node disappears, or cv2 loses whole submodules. A non-contrib opencv-python wheel installed over the contrib build empties the contrib submodules - all the OpenCV wheels share one site-packages/cv2. Dependency collisions like that are a common ComfyUI injury. tools/repair_opencv_contrib.py --check in the pack dir, then --apply.

Categoryimage/CV/low-level/cv2 F

Inputs (8)

NameTypeDefaultDescription
points1NPARRAYArray of N (N >= 5) 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.
points2NPARRAYArray 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.
cameraMatrixNPARRAYCamera intrinsic matrix $\cameramatrix{A}$ . Note that this function assumes that points1 and points2 are feature points from cameras with the same camera intrinsic matrix. If this assumption does not hold for your use case, use another function overload or #undistortPoints with `P = cv::NoArray()` for both cameras to transform image points to normalized image coordinates, which are valid for the identity camera intrinsic matrix. When passing these coordinates, pass the identity matrix for this parameter. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.
methodoptCOMBORANSACMethod for computing an essential matrix. - for the RANSAC algorithm. - for the LMedS algorithm.
proboptFLOAT0.9990-1e+38–1e+38Parameter used for the RANSAC or LMedS methods only. It specifies a desirable level of confidence (probability) that the estimated matrix is correct. Preset to the OpenCV default (0.999).
thresholdoptFLOAT1.0000-1e+38–1e+38Parameter used for RANSAC. It is the maximum distance from a point to an epipolar line in pixels, beyond which the point is considered an outlier and is not used for computing the final fundamental matrix. It can be set to something like 1-3, depending on the accuracy of the point localization, image resolution, and the image noise. Preset to the OpenCV default (1.0).
maxItersoptINT1000-2147483648–2147483647The maximum number of robust method iterations. This function estimates essential matrix based on the five-point algorithm solver in . Preset to the OpenCV default (1000).
maskoptNPARRAY,IMAGE,MASKOutput array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in the RANSAC and LMedS methods. 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 (2)

NameTypeDescription
ENPARRAY—
maskNPARRAY—