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

cv2.findEssentialMat (2/3)

Cv2.findEssentialMat (2/3)

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

Three nodes in this pack are called cv2.findEssentialMat, because cv2's Python binding has three overloads of the function and the pack generates one node per overload. The first wants a full 3×3 camera matrix. This one - (2/3) - asks for the camera in the laziest form that still counts as calibrated: one focal length, one principal point.

That's a surprisingly common situation. You know your lens is a 26 mm-equivalent phone camera, you can eyeball the principal point as the image centre, and you have no calibration session and no chessboard. This overload takes what you've got.

Inputs

points1 and points2 are the matched correspondences from a single matching pass (CV Match Features), floating point, Nx1x2-shaped, at least five points. Both are NPARRAY-only data sockets - the pack refuses images here on purpose, since a picture in a geometry socket is a silent type lie.

focal is a single float: the focal length in pixels. pp is a two-component Point - the principal point, (x, y) - which travels as one value, so you type the pair or wire it from CV Tuple. Note the asymmetry: one focal for both axes, so this overload assumes square pixels (fx = fy). It also assumes both views came from the same camera, and that the points are in pixel coordinates.

The interesting corner case is worth spelling out, because OpenCV's own docs point at it: if you normalise your points first - undistort them against P = NoArray(), i.e. shift them into ideal normalized image coordinates - then the correct intrinsics are the identity, so focal = 1 with pp = (0, 0) is exactly right, and that's also what the widget defaults are set to. In that configuration E and F are the same matrix, and you're really estimating either one.

Then the robust-estimation knobs: method (RANSAC, or LMEDS), threshold (default 1.0, in pixels - 1 to 3 is the realistic band, and it's the knob that decides how many of your matches count as inliers), prob (0.999 confidence) and maxIters (1000). There's an optional mask input sitting there; it's the C++ output-buffer parameter and passing something to it achieves nothing. The inliers you want are on the output side.

Outputs

E, the 3×3 essential matrix, and mask, the Nx1 uint8 inlier mask. Look at the mask before you trust E: if your 200 matches yield 9 inliers, the geometry is fiction. From there E goes to CV Recover Pose (Essential Matrix) for rotation and unit translation with a cheirality check, or to cv2_decomposeEssentialMat if you want all four candidate decompositions to disambiguate yourself. CV Draw Matches with the mask shows you which correspondences survived, and it's the fastest sanity check in the pack.

Which overload do you actually want

  • Full K? Use (1/3), or the curated CV Recover Pose (Essential Matrix) which does the whole thing.
  • Just a focal length and an image centre? This node.
  • Two different cameras, each with its own distortion? (3/3).

Same function underneath, so the failure modes are shared: a single plane or a pure camera rotation is degenerate, and matched points that are largely wrong give you a self-consistent-looking matrix over noise. Keep depth in the frame, translate the camera, and read the inlier count.

Install

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

ComfyUI Manager: search "ComfyUI CV", install, restart. Needs Python ≥ 3.12 and a ComfyUI on the V3 node API. The pack pins that contrib wheel because its behaviour is curated against it, and pinning matters: a non-contrib OpenCV wheel dropped in by another pack empties the contrib submodules and takes nodes with it (tools/repair_opencv_contrib.py --check diagnoses that).

Common issues

cv2 complains about the points. They must be float arrays of matching length, Nx1x2 or Nx2. Integer arrays from a mask-derived list will bite you here; route through CV Cast Array first.

Few inliers, and E is unstable. Raise threshold a little (2–3) and try LMEDS; if that doesn't move it, your matches are the problem, not the estimator. CV Filter Keypoints before matching is the usual fix.

pp won't accept your image centre. It's a typed Point, not two loose numbers: CV Tuple with count = 2 and dtype = float emits it properly, and one instance can drive several nodes.

Categoryimage/CV/low-level/cv2 F

Inputs (9)

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.
focaloptFLOAT1.0000-1e+38–1e+38focal length of the camera. Note that this function assumes that points1 and points2 are feature points from cameras with same focal length and principal point. Preset to the OpenCV default (1.0).
ppoptCV_TUPLE0,0principal point of the camera. One value with 2 components (x, y) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place.
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—