Nodes/ComfyUI CV/cv2.omnidir.undistortPoints
ComfyUI Node

cv2.omnidir.undistortPoints

The raw wrapper exists, and it's still not the node you want

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.omnidir.undistortPoints
  • distorted
  • K
  • D
  • xi
  • R
  • nparray

Short version: this is cv2.omnidir.undistortPoints, the point-set sibling of cv2.omnidir.undistortImage. You feed it pixel coordinates in a 360 mirror-rig frame, plus the camera, and you get the same coordinates in ideal form. And the pack's own documentation says the honest route through the same problem is a different node - CV Omnidir Undistort, described in its catalog as doing "closed-form CMei inversion instead of the wrong undistortPoints". That's the author, not me, calling the wrapped function the wrong tool.

Why you'd want points undistorted at all

The pixel version hands you a prettier picture. The point version hands you measurements. If you detected corners, ArUco markers, keypoints or a tracked feature on a 360 frame and you intend to do anything geometric with them - solvePnP, triangulation, a homography, feeding landmarks to a pose estimator - those coordinates are in the distorted image and have to be put back into ideal coordinates first. That's this function's job, and it's the same job cv2.undistortPoints does for a pinhole lens and cv2.fisheye.undistortPoints does for a fisheye.

What the wrapper gives you

Five required NPARRAY sockets, five outputs - wait, no, one output, and that IS the shape of the problem:

  • distorted - the point set. (N, 1, 2) floats, exactly the layout CV Contour To Points, CV Points, CV Detect Features and the ArUco detector emit.
  • K - 3x3 intrinsics (NPARRAY; CV Camera Matrix or Parse Matrix builds it, or take it off CV Omnidir Calibrate (Chessboard)).
  • D - the four omnidir coefficients (k1, k2, p1, p2). Five is the pinhole set and it is not what this function wants.
  • xi - CMei's mirror parameter, as an array (a 1x1 float, so type 0.8 into Parse Matrix).
  • R - the rotation to apply to the points after undistorting, or the identity. Required here, where the C++ signature makes it optional.

One output, nparray: the corrected points as (N, 1, 2). From there they wire into anything that eats a point set - CV Solve PnP (Pose), CV Triangulate Points (Two-View), CV Find Homography (RANSAC), CV Draw Points, or CV Perspective Transform if you already have the matrix that does the job.

Notice there is no P (the output camera matrix) in the schema. In the C++ API you can pass one and get points in a chosen camera; here you get whatever the function's internal normalization produces, which is one more reason the curated node, which handles that side itself, is the one to build on.

Where this bites

It's a contrib function, like everything in this pack's omnidir corner. With a core-only OpenCV build, the node isn't skipped-with-an-error - the registry generator only creates wrappers for functions your installed cv2 actually exposes, so it silently never appears in the Add Node menu. omnidir ships in the contrib wheel, so:

pip install "opencv-contrib-python-headless~=5.0.0.93"
python ComfyUI/custom_nodes/comfyui_cv/tools/repair_opencv_contrib.py --check

That second command is the pack's own diagnostic for the classic failure - installing plain opencv-python (or opencv-python-headless) over a contrib install, which overwrites the shared site-packages/cv2 and empties every contrib submodule.

Point arrays are NPARRAY-only sockets. This node's inputs reject an IMAGE or MASK link outright - deliberately, since a picture is not a point set - so if you have coordinates baked into a mask you have to get them out as points first (CV Contour To Points, or CV Detect Corners / CV Detect Features for detected ones).

Shape and dtype errors are loud and unhelpful. cv2 wants (N, 1, 2) float32/float64. An (N, 2) array or an int32 one gets you an opaque "Overload resolution failed" from the Python binding. CV Points and CV Contour To Points emit the right layout; hand-rolled arrays usually don't.

Install, briefly

ComfyUI Manager → ComfyUI CV → Install → restart, or:

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

Python ≥ 3.12, a recent ComfyUI (V3 node API), OpenCV 5.0.0.93 pinned as the curated reference. No models.

So which do you use

If you want the points behind a rectified image, use CV Omnidir Undistort - it does the closed-form inversion and hands back the camera matrix the result is expressed in, so the picture and the geometry agree. Reach for this raw wrapper when you want to see what the underlying cv2 call does, or when you're building a pipeline the curated node's parameter set doesn't fit. Grading on results, the curated node is the answer; that's what the pack's own docs say, and I've got no reason to argue with them.

Categoryimage/CV/low-level/omnidir

Inputs (5)

NameTypeDefaultDescription
distortedNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
KNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
DNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
xiNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
RNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.

Outputs (1)

NameTypeDescription
nparrayNPARRAY—