Nodes/ComfyUI CV/cv2.fastAtan2
ComfyUI Node

cv2.fastAtan2

Two numbers in, degrees out (and that's the point)

By bmad4ever·Created 4 months ago·Updated 16 days ago· 1
cv2.fastAtan2
    • float
    ◄y0.0000►
    ◄x0.0000►

    A calculator node in a pack of image processors. cv2.fastAtan2 takes a y and an x as floats and returns the angle of that vector, in degrees - so it's the piece that turns "these two coordinates" into "rotate by this much", which is a step that comes up constantly once you start deriving transforms instead of dialling sliders.

    Why it exists at all

    atan2 on a GPU is expensive, so OpenCV ships a lookup-table approximation: accurate to roughly a third of a degree, several times faster than the library call. That's the "fast" in the name. You are not getting an approximation you should worry about - a third of a degree is well below what any rotation widget or resampling operation will show you - but it is worth knowing that this is not a transcendental function call with infinite precision.

    Its real value in a ComfyUI graph is unit match. OpenCV's fastAtan2 returns degrees in the range 0 to 360, and practically every node in this pack that takes a rotation - the rotate angle on CV Transform (Rotate/Scale/Shift), warp matrices you're assembling by hand - wants degrees. Core's math-expression node gives you radians, which means you're appending a conversion to every derived angle. Here you don't.

    The two inputs, and where they come from

    y and x are both required floats and both default to 0, which is a quiet trap: leave them untouched and you get atan2(0, 0), which is 0. The result will look like a legitimate angle. Always wire something in.

    Where the pair comes from is the interesting part:

    • A measured direction. Hough line endpoints, or any two points in a frame: dy = y2 - y1, dx = x2 - x1, and the angle of that line is one call. The pack's subtraction wrapper gives you the deltas as scalars if you prefer to compute them on the canvas rather than in a Python-side node.
    • A feature-match displacement. Two matched keypoints and you have a motion direction - useful for a quick "which way did this shot drift" readout, or for rotating a following operation to match the drift.
    • A straightening angle. Any two points on a horizon, a text baseline, or a rectangle edge; the negative of this angle is the rotation that levels the frame, and it feeds straight into CV Transform (Rotate/Scale/Shift).

    The y, x argument order matters and is the classic bug: this is atan2(y, x), not (x, y). Swap them and you get the angle mirrored about the 45° line - a plausible-looking number that rotates your image the wrong way by a wrong amount. When in doubt, feed your points into a tiny test graph and check that a direction you know (say, a horizontal line pointing right) gives you 0.

    Output

    One float socket, the angle in degrees. That's a scalar in ComfyUI terms, so it wires into any FLOAT input - a rotate widget, a CV Value-style primitive if you want to fan it out to several consumers, or CV Numbers To Array if you'd rather accumulate angles into an array. Because OpenCV's version wraps to 0–360 rather than −180–180, an angle that "should" be −10° arrives as 350°. For a pure rotation that's the same thing. For arithmetic - averaging an angle with another, or smoothing a trajectory - it isn't, and that's a bug that shows up as a sudden 350-degree spin at the wrap point.

    Installing it

    cd ComfyUI/custom_nodes
    git clone https://github.com/bmad4ever/comfyui_cv
    pip install "opencv-contrib-python-headless~=5.0.0.93"
    

    Or find comfyui_cv in ComfyUI Manager and restart. Python ≥ 3.12 and a recent ComfyUI built on the V3 node API. The node is under image/CV/low-level/cv2 F, in the same folder as the rest of the function wrappers.

    Traps

    Both defaults, both zero: forget to wire either input and you get a legitimate-looking 0 instead of an error. Argument order, as above. And the units - this returns degrees while most general-purpose math nodes think in radians, so if you mix this node with a hand-rolled expression, pick one convention and hold it. The approximation itself is fine; a third of a degree has never once been the reason an image came out crooked.

    Categoryimage/CV/low-level/cv2 F

    Inputs (2)

    NameTypeDefaultDescription
    yFLOAT0.0000-1e+38–1e+38y-coordinate of the vector.
    xFLOAT0.0000-1e+38–1e+38x-coordinate of the vector.

    Outputs (1)

    NameTypeDescription
    floatFLOAT—