Nodes/ComfyUI CV/cv2.convertPointsToHomogeneous
ComfyUI Node

cv2.convertPointsToHomogeneous

Put the 1 on the end so matrices can act on your points

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.convertPointsToHomogeneous
  • src
  • nparray
◄dtypesame as input►

What and why

cv2.convertPointsToHomogeneous appends a 1 to every point. That's the entire function. (x, y) becomes (x, y, 1), and (x, y, z) becomes (x, y, z, 1), which is the form a homography, a projection matrix or a fundamental matrix can multiply. Six hours of projective geometry courses compressed into "add a one".

You need it because raw pixel coordinates can't be transformed by a 3×3. Multiply (x, y) by a homography and you've got two numbers out of a matrix that expects three - the results are meaningless, and worse, they're shaped right, so nothing errors. Homogenising first is what makes the multiplication legal; dividing the result back through is what makes it a pixel again, and that's cv2.convertPointsFromHomogeneous's job.

It's a raw wrapper from ComfyUI CV (bmad4ever/comfyui_cv), category image/CV/low-level/cv2 C.

How it works

For each point (x1, x2, …, xn) it returns (x1, x2, …, xn, 1). So an (N,2) set of pixel points becomes (N,3); an (N,3) cloud becomes (N,4). The dtype widget sets the output depth and defaults to "same as input", which is the wrapper's rendering of OpenCV's -1 sentinel ("use CV_32F or CV_64F to match the input"). Unless you have a specific reason, leave it.

That's the mechanism, but the shape consequence is the part that bites: this node changes the dimensionality of your data. A downstream node expecting (N,2) points will now receive (N,3) and either fail or silently treat the appended 1 as a third coordinate. In the pack, where nodes freely mix 2D point sets, 3D clouds and matrices, that's the practical hazard.

Inputs and outputs that matter

  • src - required, NPARRAY only. The author's tooltip is direct about it: a data array, not an image, so an IMAGE or MASK link is refused.
  • dtype - optional COMBO, default same as input; CV_32F / CV_64F are the ones OpenCV supports here.
  • nparray - the homogenised points.

The pattern it belongs to

It's one leg of a four-step pipeline that shows up all over this pack's geometry nodes:

  1. Get pixel points - CV Contour To Points, CV Annotate Points, a feature node, findNonZero.
  2. Homogenise - this node (or a function that already hands you homogeneous data: triangulatePoints returns homogeneous 4×N points, solvePnP's inputs are 3D object points).
  3. Transform - CV Matrix Multiply with your 3×3 homography or 3×4 projection, or a raw cv2.perspectiveTransform.
  4. Dehomogenise - cv2.convertPointsFromHomogeneous (or cv2.perspectiveTransform, which does the divide for you and is why it exists).

If you're using cv2.perspectiveTransform you generally don't need either conversion node - it takes 2D points and returns 2D points, dividing internally. The pair here is for when you're multiplying matrices yourself in NPARRAY space, which is what the pack's plumbing encourages (comfyui-node-plumbing.md is the wider map of that layer and why it's worth understanding).

Installing the pack

Manager → search ComfyUI CV, or:

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

Restart ComfyUI. Python ≥ 3.12 plus a ComfyUI on the V3 node API, and opencv-contrib-python-headless~=5.0.0.93 as the only real dependency.

Where people get burned

  • Feeding the output straight to a 2D consumer. The extra column isn't flagged anywhere. If a draw node is suddenly drawing at bizarre coordinates, check whether an (N,3) sneaked in.
  • Shape, again. OpenCV wants N×1×C or N×C. CV Reshape Array is the pack's fix for flat or squeezed inputs, and its docs call out (3,) rows specifically.
  • dtype on mixed input. "same as input" is usually right, but if you're chaining several conversions and want float32 throughout, be explicit rather than inheriting twice.
  • Round-tripping without a reason. To and from, with nothing in between, is a no-op that just costs a pass - the interesting thing always happens in step 3.
  • Trust calibration, once per pack. The README is candid: heavily LLM-assisted development, a documented case of test-driven overfitting, no planned updates, and "not recommended in production" without independent review. Also worth knowing: the pack's registry is generated from whatever OpenCV build is installed, so the menu can list functions your particular wheel doesn't implement. There's no Reddit corpus for this pack - a search returns nothing - so an odd result here has no existing answer waiting for it. Sanity check with something you can do in your head: (100, 200) should come out as (100, 200, 1).
Categoryimage/CV/low-level/cv2 C

Inputs (2)

NameTypeDefaultDescription
srcNPARRAYInput vector of N-dimensional points. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.
dtypeoptCOMBOsame as inputThe desired output array depth (either CV_32F or CV_64F are currently supported). If it's -1, then it's set automatically to CV_32F or CV_64F, depending on the input depth. The function converts points from Euclidean to homogeneous space by appending 1's to the tuple of point coordinates. That is, each point (x1, x2, ..., xn) is converted to (x1, x2, ..., xn, 1).

Outputs (1)

NameTypeDescription
nparrayNPARRAY—