cv2.decomposeProjectionMatrix
Pull K, R and t back out of a camera matrix
- projMatrix
- cameraMatrix
- rotMatrix
- transVect
- rotMatrixX
- rotMatrixY
- rotMatrixZ
- eulerAngles
A 3×4 projection matrix is the compressed form of "where is this camera, which way is it pointing, and what lens does it have" - every 3D program and every photogrammetry pipeline can emit one. cv2.decomposeProjectionMatrix splits it back into the pieces: intrinsics, rotation, translation, the three per-axis rotation components, and Euler angles. If you've grabbed a camera out of Blender or matched a render to a photo, this is the node that tells you what the numbers mean.
The mechanism
The projection matrix is P = K·[R|t] - intrinsics times a rigid transform. OpenCV takes the left 3×3 block, which is the product K·R, and runs an RQ decomposition on it (cv2.RQDecomp3x3), yielding an upper-triangular matrix (the intrinsics) and an orthogonal one (the rotation). The translation comes straight out of the fourth column. It's basic linear algebra on a 3×3, so it's instant, and it's the inverse operation of the classic "Build a projection matrix from K, R and t" step in camera calibration.
What comes out
Seven NPARRAY outputs, which sounds like a lot until you see the shape of it:
cameraMatrix- the 3×3 intrinsics, the focal lengths and principal point.rotMatrix- the 3×3 rotation.transVect- the camera position, in homogeneous coordinates: a 4×1 vector where the last element is the scale, not a coordinate. Divide by it before you use the first three numbers, or your camera will appear to be sitting somewhere absurd.rotMatrixX,rotMatrixY,rotMatrixZ- the three per-axis rotations whose product reconstructsrotMatrix.eulerAngles- a 3×1 vector, in degrees, for people who'd rather read angles than matrices.
The input is projMatrix: an NPARRAY-only link (the tooltip is emphatic - a data matrix, not an image), 3×4 float.
Two things to expect. First, the decomposition isn't unique: you can flip the signs of the intrinsics and the rotation together and get another valid answer, so it's not unusual to get a cameraMatrix with a negative focal length on the diagonal, or an R with determinant −1. The fix is to negate K and R together until fx and fy are positive and det(R) = +1; if you calibrate against a known camera you'll see exactly this. Second, feeding it a matrix from a different convention - row-major vs column-major, y-down vs y-up - gives a perfectly self-consistent answer for the wrong world. Sanity-check by reprojecting a known point.
The curated alternative in the same pack
There's a hand-written CV Decompose Projection Matrix (RQ) node here that exposes the RQ decomposition directly, and it's arguably the better debugging tool: it takes a 3×3 or a full 3×4 matrix, and it gives you back the 3×3 block it actually decomposed alongside R and Q, so you can verify that R @ Q reconstructs the input. Its own documentation flags the composition-order trap - OpenCV reduces M by right-multiplying the per-axis rotations, so Q = Qzᵀ @ Qyᵀ @ Qxᵀ, not Qx @ Qy @ Qz the way you'd naively assume, and the same warning applies to the rotMatrixX/Y/Z outputs of this raw node.
Use the raw cv2.decomposeProjectionMatrix when you specifically want transVect or eulerAngles - the curated node deliberately doesn't recover translation, pointing you at CV Solve PnP Pose / CV Pose To Matrix for that instead.
Install
Manager → Install Custom Nodes → ComfyUI CV, or:
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, a recent V3-API ComfyUI, the contrib headless OpenCV wheel as the only dependency, no models to download. The pack is GPL-3.0 (forked from geroldmeisinger/opencv-comfyui), mostly AI-generated, and the author says outright not to trust it in production without reviewing the code - worth repeating for geometry, where a wrong answer still looks like a plausible matrix.
Common issues
- The link won't connect.
projMatrixis NPARRAY-only. Build one withCV Parse Matrix,CV Matrix To Poseor a calibration node. - Camera position looks wrong by orders of magnitude.
transVectis homogeneous. Divide by its fourth element. - Negative focal lengths, rotation with determinant −1. The sign ambiguity above. Flip
KandRtogether. rotMatrixX @ rotMatrixY @ rotMatrixZdoesn't reconstruct the rotation. OpenCV composes them in the opposite order:Q = Qzᵀ @ Qyᵀ @ Qxᵀ.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| projMatrix | NPARRAY | 3x4 input projection matrix P. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| cameraMatrix | NPARRAY | — |
| rotMatrix | NPARRAY | — |
| transVect | NPARRAY | — |
| rotMatrixX | NPARRAY | — |
| rotMatrixY | NPARRAY | — |
| rotMatrixZ | NPARRAY | — |
| eulerAngles | NPARRAY | — |