Nodes/ComfyUI CV/CV Matrix To Pose
ComfyUI Node

CV Matrix To Pose

Turn a 4x4 back into something that can be rendered

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Matrix To Pose
  • matrix
  • rvec
  • tvec
  • rotation
  • scale
  • found

There are two ways to express "where the object is" in OpenCV, and they're not interchangeable at the plumbing level. Solvers hand you a 4x4 (or 3x4) rigid transform. Everything you'd use to draw the thing - cv2.projectPoints, CV Rasterize Mesh, CV Camera Pose To 3D View - wants rvec + tvec. This node is the adapter: matrix in, Rodrigues rotation vector and translation out.

Concretely, it's the step between "the matcher found the pose" and "I can see whether the pose is right." CV PPF Pose Estimation, CV ICP Register and CV Register Point Clouds (3D) produce matrices; this turns them into something renderable, so a recovered pose can be checked against - or composited into - the photo it came from. CV Pose To Matrix is the inverse, and the pair are designed as a round trip.

How it works

It takes the rotation block, orthonormalizes it with an SVD, and feeds the result to cv2.Rodrigues. That's not paranoia - a pose that came out of a chain of matrix multiplications is only approximately a rotation, and Rodrigues won't complain about a slightly skewed input, it'll just return a vector that no longer round-trips. Nearest-rotation-by-SVD fixes it. Reflections get caught too: if the determinant comes out negative the last singular vector is flipped, because a reflection isn't a rotation.

A 4x4 homogeneous transform, a 3x4 [R|t], or a bare 3x3 rotation are all accepted. A 3x3 gives you a zero translation.

Inputs and outputs

One required input, matrix. Outputs:

  • rvec - 3x1 Rodrigues rotation vector. This is what projectPoints and the rapid nodes want.
  • tvec - 3x1 translation, in the matrix's own units (no unit conversion happens, and none should).
  • rotation - the orthonormalized 3x3 R, if you'd rather do your own math.
  • scale - the mean singular value of the input's rotation block. This is the diagnostic output and most people don't notice it exists. 1.0 means a clean rigid transform. Anything else means your matrix carries a scale (or drift) that rvec/tvec cannot represent and that this node silently divided out. A scale of 1.02 is a solver that drifted; a scale of 100 is a unit mismatch you should fix upstream instead of hiding here.
  • found - False when the matrix was missing, the wrong shape, or non-finite.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv

Manager → ComfyUI CV. Restart. Requires Python ≥ 3.12 and a V3-API ComfyUI; dependency is opencv-contrib-python-headless~=5.0.0.93. No models, no GPU - this is arithmetic.

Common issues

A pose that renders 180° out. If the mesh and the scene normals disagree about which way is out, the recovered pose is inverted and this node can't tell you - it faithfully converts whatever rotation it was handed. The chain is: the mesh must carry sign-correct normals (CV Mesh Vertex Normals, which derives them from triangle winding, rather than a plane fit that can't tell inside from outside), and the axis convention on CV Mesh From 3D Model must match the camera's. Get those two right and this node is a no-op converter.

found=false from a matrix you're sure is there. Check the shape. A flattened 16-element vector, a 2x4, or a matrix that came out of a text parse are the usual culprits. It also returns False for a matrix containing NaN or inf, which is a gift - a diverged solver upstream would otherwise propagate silently into your render.

Rotation looks right, position is wrong. Read scale first, then check units. A mesh authored in centimetres matched against a calibration in metres gives a pose that's correct in direction and wrong in depth, which is exactly the signature of a scale mismatch - and the fix is scale on CV Mesh From 3D Model or CV 3D Object Transform, not here.

Categoryimage/CV/features

Inputs (1)

NameTypeDefaultDescription
matrixNPARRAY4x4 homogeneous or 3x4 [R|t] transform. A 3x3 rotation on its own is accepted too and gives a zero translation.

Outputs (5)

NameTypeDescription
rvecNPARRAY3x1 Rodrigues rotation vector.
tvecNPARRAY3x1 translation vector, in the matrix's own units.
rotationNPARRAYThe orthonormalized 3x3 rotation matrix R.
scaleFLOATMean singular value of the input's rotation block - 1.0 for a rigid transform. Anything else means the matrix carries a scale (or drift) that rvec/tvec CANNOT represent and that this node has divided out.
foundBOOLEANFalse when the matrix was missing, the wrong shape, or non-finite.