cv2.decomposeEssentialMat
Four candidate poses, one of which is real
- E
- R1
- R2
- t
An essential matrix encodes the relative position and orientation between two calibrated views of the same static scene - no scale, just direction and rotation. cv2.decomposeEssentialMat unpacks one into its candidate rotation and translation. The catch, and the reason this node is usually not the one you want, is that the decomposition is ambiguous: it hands you two rotations and one translation, which together describe four possible poses, and it makes no attempt to tell you which is correct.
The mechanism
The essential matrix is decomposed with an SVD: E = U · diag(1, 1, 0) · Vᵀ. That factorisation determines the two candidate rotations (which differ by a 180° flip about the translation axis) and one translation up to sign. So the four poses you can assemble are (R1, t), (R1, −t), (R2, t) and (R2, −t) - and the way you choose is the cheirality check: only one of them puts the matched points in front of both cameras, with positive depth. That check needs the actual point correspondences, which is why the raw decomposition on its own can't do it.
The node has one input, E - an NPARRAY link, and only an NPARRAY, because the tooltip is explicit that this is "a data array (points / matrix), NOT an image". Feed it the 3×3 matrix that cv2.findEssentialMat returns.
Outputs
Three NPARRAY outputs: R1, R2 (the two 3×3 rotation candidates) and t (the translation direction, unit length, sign undetermined). Note what's not there - no scale, no validity flag, no inlier information. Monocular geometry can't give you metres; you get a direction and you get to figure out which of the four assemblies is physical. If you feed the wrong sign of t into a triangulation, your points land behind the camera and your reconstruction explodes, which is the classic way people discover this node's ambiguity the hard way.
The node you probably want instead
This pack ships a curated CV Recover Pose (Essential Matrix) node that estimates the essential matrix with RANSAC and then applies the cheirality check in one step, returning a single rotation and translation (still unit-length, still direction only) plus a found flag and an inlier count, and it fails gracefully on degenerate input instead of halting the graph. Its own description points at the two traps that bite people: a pure rotation with no camera translation, or a scene that's one flat plane, are both degenerate for this geometry - you need views with real depth and a camera that actually moved sideways. For visual-odometry-style work, that node plus CV Triangulate Points (Two-View) is the usable pair.
Reach for the raw cv2.decomposeEssentialMat when you're implementing your own disambiguation, when you want to see both rotations as an educational step, or when you're feeding an essential matrix that came from somewhere other than this pack's estimate - a solved one, or one you built by hand.
Install
Manager → Install Custom Nodes → ComfyUI CV (publisher bmad4ever), or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Restart ComfyUI. Python ≥ 3.12 and a recent V3-API ComfyUI; the only dependency is the contrib headless OpenCV wheel, and this node needs no downloaded model. The pack is GPL-3.0, a fork of geroldmeisinger/opencv-comfyui, largely LLM-written, and the author's disclaimer is explicit: not production-ready, no support promise. For multi-view geometry that's worth taking seriously - validate the poses you get on data you know the answer for.
Common issues
- The input link is rejected. Only an NPARRAY is accepted. Get one from
CV Find Essential Mat/CV Recover Pose, or convert a 3×3 matrix withCV Parse Matrix. (-215)about the matrix shape.Emust be 3×3 float. If your matrix came in as 4×4 or as a string literal, parse or reshape it first.- A reconstruction goes haywire downstream. You picked the wrong one of the four poses. Nothing in this node tells you which is right - that's the cheirality check's job, and it lives in
CV Recover Pose.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| E | NPARRAY | The input essential matrix. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| R1 | NPARRAY | — |
| R2 | NPARRAY | — |
| t | NPARRAY | — |