Nodes/ComfyUI CV/cv2.Rodrigues
ComfyUI Node

cv2.Rodrigues

Rvec to matrix and back, the conversion everything else assumes

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.Rodrigues
  • src
  • output
  • jacobian

One input, two directions

cv2.Rodrigues(src) converts between the two ways OpenCV writes a rotation: a 3×1 rotation vector (direction = axis, length = angle in radians - Rodrigues' formula, hence the name) and a 3×3 rotation matrix.

Feed it a 3-vector and it returns a matrix. Feed it a 3×3 matrix and it returns the vector. One node, both directions, no mode switch, no parameters. The output shape tells you which direction you went.

That sounds trivial until you notice how much of the OpenCV ecosystem is picky about the representation. solvePnP, solvePnPRansac, projectPoints, drawFrameAxes, composeRT and the RAPID tracker all speak rvec. Pose composition, homographies and most 3D math speak matrices. If your graph mixes the two - and any real calibration or SfM graph does - this is the adapter, and its absence is why so many hand-built chains end in a shape-mismatch error.

Inputs and outputs

  • src - NPARRAY. The node's sockets are arrays only: this is not an image operation, and the pack's tooltips for the related nodes make the distinction loud ("a matrix, not an image"). Shape it as (3,1), (1,3) or a flat 3, or as a (3,3).
  • output - the converted rotation: 3×3 if you fed a vector, 3×1 if you fed a matrix.
  • jacobian - the derivative of the output with respect to the input: 9×3 (vector → matrix) or 3×9 (matrix → vector). It exists because Rodrigues is used inside non-linear solvers, where a bundle-adjustment step needs the analytic Jacobian rather than a numerical approximation. In a ComfyUI graph you will ignore it 100% of the time. It's the one output of a CV node you can safely leave unconnected.

Where it shows up in the pack

The shipped examples use it as the glue in exactly the places you'd predict: the two-view SfM exercise pipes a recovered rotation into cv2.Rodrigues to get an rvec that the projection/drawing nodes accept; the matrix-decomposition playground uses it to move between the two forms while you poke at factorisations; the CV Transform Points (Scale, Rotate, Translate) subgraph uses it to turn authored rotations into something it can apply. That's the honest shape of this node's role: it isn't interesting, it's load-bearing.

The two conversion directions have different practical flavours. Vector → matrix is what you do when you have a pose from PnP or from cv2.recoverPose and you want to compose it with another rotation (CV Matrix Multiply), or feed it into a 4×4 transform for point-cloud work. Matrix → vector is what you do when you have a rotation from a decomposition, an ICP fit (CV ICP Register), or an authored 3×3, and need to hand it to a node that wants rvec. The angle-and-axis form is also just easier to read: a vector of magnitude 0.02 is visibly a tiny rotation; a 3×3 matrix is not.

The shape traps

It has no idea what you meant. A (3,) flat array is accepted as a vector; a (3,3) as a matrix; and anything else is a cv2 error. If your upstream node emits (3,1,1) because it was reshaped for broadcasting, that will not pass. Check with CV Array Shape - it prints exactly what you have, which is faster than guessing from the error text.

rvec values are radians, not degrees. A common source of "the model is rotated a bit more than I expected" is a solver output in radians and a hand-authored quaternion-ish angle in degrees. Rodrigues doesn't convert units for you.

Watch the compose order. Rotation matrices don't commute, so R1 @ R2 ≠ R2 @ R1. If a composed pose drifts in a way that depends on which camera moved, it's usually the multiply order, not this node.

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" by bmad4ever through ComfyUI Manager. Requires Python ≥ 3.12 and a ComfyUI recent enough to support the V3 node API - this pack registers through comfy_api.latest, so an older ComfyUI means no nodes at all rather than a broken one. Restart ComfyUI, reload the page.

Troubleshooting

Shape error on the input. Reshape upstream: the node wants a 3-vector or a 3×3 matrix and nothing else. The pack's CV Reshape Array does that.

The rotation looks inverted. You're probably not looking at the output type you think. A 3×1 out of a 3×3 in is a vector; if you wire it into something expecting a matrix, the fallback behaviour is silent nonsense. Confirm which direction you converted with CV CV Inspect.

Nothing downstream accepts the output. Both outputs are NPARRAY. Nodes wanting a CV_TUPLE, a scalar or an image will refuse - this is data-lane plumbing by design, same as the rest of the pack's array nodes.

Categoryimage/CV/low-level/cv2 R

Inputs (1)

NameTypeDefaultDescription
srcNPARRAYInput rotation vector (3x1 or 1x3) or rotation matrix (3x3). A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.

Outputs (2)

NameTypeDescription
outputNPARRAY—
jacobianNPARRAY—