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

cv2.fisheye.undistortPoints

Fix the coordinates, not the pixels

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.fisheye.undistortPoints
  • distorted
  • K
  • D
  • nparray
◄criteria_typemax count or epsilon (whichever first)►
◄criteria_max_count30►
◄criteria_epsilon0.00►

If you have a handful of coordinates in a wide-angle frame - clicked points, detected corners, a tiny point cloud of correspondences - you don't need to resample a 4K image to fix them. cv2.fisheye.undistortPoints runs the inverse lens model on the points themselves. Milliseconds, no interpolation, no lost detail, and it doesn't matter how big the source image was.

It's a raw wrapper in ComfyUI CV (bmad4ever), the pack that turns OpenCV 5.0 into ComfyUI nodes - ~470 generated cv2.* wrappers plus a curated layer. The generated ones are one cv2 call each with NPARRAY sockets, and this is exactly that.

How it works

Points arrive in pixel coordinates of the distorted image. cv2 solves for where each ray actually points under the equidistant fisheye model, using K and the four distortion coefficients k1..k4, and returns undistorted coordinates. That's the whole function - no image, no map, no remap.

Two consequences worth flagging before you wire it up. First, the wrapper exposes distorted, K, D and the optional criteria, and nothing else - no R, no P socket. In OpenCV, fisheye.undistortPoints returns normalized image coordinates when no new projection matrix is given: the points divide through by the focal length, so they land on the z = 1 plane rather than in pixels. If you're comparing against pixel positions in a straightened image, you have to scale by the new K yourself (or undistort the image and detect in that, where the coordinates already mean what you want). This is the single most common confusion with the node.

Second, points behind the camera or outside the lens's field of view are meaningless to invert - you get back whatever the math produces, not a flag. Filter for sanity before you trust a point that was near a frame edge.

Inputs and outputs

  • distorted - an NPARRAY of 2D points in pixel coordinates. In practice you get NPARRAYs from CV Contour To Points, CV Annotate Points, a feature-matching pipeline, or CV Points if you're typing coordinates in.
  • K - the 3×3 intrinsics from CV Fisheye Calibrate (Chessboard) (or CV Camera Matrix if you're authoring fx/fy/cx/cy directly).
  • D - exactly four coefficients. Five pinhole coefficients are the classic mistake; they'll run and give you wrong answers rather than an error.
  • criteria_type / criteria_max_count / criteria_epsilon - optional, with sensible presets (max count or epsilon, 30 iterations, 1e-3). This is the iteration stop condition of the inverse solve. Nobody's ever needed to touch it; leave the defaults.

One output: nparray, the undistorted point set. Feed it into a pinhole solver (cv2.solvePnP, or the pack's curated CV Solve PnP family), into CV Draw Points to eyeball it, or into CV Polar To Points / CV Filter Points By Distance if you're reasoning about radial position.

Install

ComfyUI Manager → ComfyUI CV (the pack's registry title), or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install -r comfyui_cv/requirements.txt

Python ≥3.12, a recent ComfyUI built on the V3 node API, restart when done. Only real dependency is opencv-contrib-python-headless~=5.0.0.93 - plus the contrib caveat: if you installed opencv-python over the contrib wheel, the whole fisheye category silently disappears, because all the pip distributions share one site-packages/cv2. tools/repair_opencv_contrib.py --check then --apply sorts it out.

Common issues

Your undistorted points look tiny. That's the normalized-coordinate thing above. Values around ±1 mean "z = 1 plane", values in the hundreds mean pixels. If you got the former and wanted the latter, either pass your new K (which this wrapper has no socket for) or undistort the image with cv2.fisheye.undistortImage and do your detection there.

Points scatter towards the edges. Wide lens, points near the frame border, and a slightly wrong K. Fisheye inversion is much more sensitive at high radius than at the centre, so calibration error shows up at the edges first.

Points count mismatch downstream. The output preserves order and count, so a mismatch means something else in the chain - usually an upstream filter that dropped points without telling you. CV Filter Points By Mask and CV Filter Points By Distance both keep a mask or selection you can inspect for exactly this reason.

Categoryimage/CV/low-level/fisheye

Inputs (6)

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.
criteria_typeoptCOMBOmax count or epsilon (whichever first)When to stop iterating: after max_count iterations, when the change drops below epsilon, or whichever comes first.
criteria_max_countoptINT301–2147483647Maximum iterations (ignored when 'epsilon only').
criteria_epsilonoptFLOAT0.000–1e+38Target accuracy / smallest change worth continuing for (ignored when 'max count only').

Outputs (1)

NameTypeDescription
nparrayNPARRAY—