CV Optical Flow (Farneback)
Farneback flow, and why the raw cv2 wrapper for it is unusable
- frame_a
- frame_b
- flow
- magnitude
- angle
Farneback is the dense optical-flow algorithm every OpenCV tutorial teaches: fit a polynomial to a neighbourhood of each pixel and find the displacement that best matches the polynomial in the next frame. It's been the default for fifteen years and it's still fine. It is not the best option in this pack anymore - CV Optical Flow (DIS) beats it on both sharpness and speed - but if you're following a tutorial, comparing against published numbers, or you need the exact parameter set everyone else uses, this is the node.
The reason this node exists at all is a nice illustration of why "just wrap every cv2 function" doesn't get you a usable toolkit. The raw generated cv2_calcOpticalFlowFarneback wrapper in this pack is basically unusable: its flow argument is an in/out array, which means the generated node demands you supply the empty flow buffer you're asking it to compute, and none of the seven numeric parameters has a sensible default. This curated node passes flow=None for you and presets the parameters.
The parameters, in the order you'd actually care about
frame_a and frame_b go in as frames (IMAGE or MASK directly, frame 0 of a batch, or NPARRAY), both converted to grayscale, with frame_b resized to frame_a if they don't match. Order is time order.
Then it's the classic Farneback set:
winsize(default 15) - the averaging window. Bigger is more robust to noise and blurrier.levels(default 3) - pyramid levels. 1 means no pyramid, which means small motion only.poly_n(default 5, typically 5 or 7) andpoly_sigma(default 1.2) - the polynomial expansion neighbourhood and its Gaussian sigma. These two travel together: ~1.1 forpoly_n=5, ~1.5 forpoly_n=7. Mismatching them is the most common silent quality loss.iterations(default 3),pyr_scale(default 0.5), andwindow(box (faster)vs gaussian).
The two you'll actually touch are levels and winsize. If large motion vanishes, add pyramid levels. If the field is noisy, raise winsize.
Outputs
flow (HxWx2 float32 (dx, dy)), magnitude (pixels of motion, HxW float32), and angle (radians, HxW float32). The angle/magnitude pair feeds CV Flow To Color in its default radians mode; the flow field itself is what you'd hand to a remap or an extract-channel pair of cv2.extractChannel nodes if you want the raw dx and dy.
Because the pack standardizes those three outputs across every flow node, swapping Farneback for DIS or TV-L1 later is a two-click change.
Install
Manager → ComfyUI CV, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
cd comfyui_cv && pip install "opencv-contrib-python-headless~=5.0.0.93"
Restart. Python ≥ 3.12, V3 node API. Farneback itself is core OpenCV, but the pack declares the contrib headless wheel and is curated against 5.0.0.93.
Common issues
- Flow is garbage on a big jump between frames - Farneback's pyramid only gets you so far. Add
levels, or switch to DIS withinit_flow, which is the actual fix for video. - You want
OPTFLOW_USE_INITIAL_FLOW- that's a raw-wrapper flag, and this node doesn't expose aflagsinput; useCV Optical Flow Flagswith the generatedcv2_calcOpticalFlowFarnebacknode if you need it, and accept the in/out array pain. - Sizes not matching -
frame_bis silently resized toframe_a. Silent resizing is convenient and occasionally misleading; check you fed the frames in the right order. cv2DLL errors on Windows - the mixed-wheel issue that hits every cv2-based pack in the install, not this node specifically. The pack'stools/repair_opencv_contrib.py --checkdiagnoses it.
The pack's README is upfront that this is a personal project with heavy LLM involvement and no production promises. For flow computation specifically, that's low-risk - the algorithm is OpenCV's, and the node is mostly a sane argument-passer.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| frame_a | NPARRAY,IMAGE | First frame (earlier in time); any colour space, converted to grayscale. 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. | |
| frame_b | NPARRAY,IMAGE | Second frame; resized to frame_a if the sizes differ. 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. | |
| pyr_scale | FLOAT | 0.500.1–0.9 | Pyramid scale between levels (<1); 0.5 halves the resolution at each level. |
| levels | INT | 31–10 | Number of pyramid levels (1 = no pyramid). |
| winsize | INT | 153–101 | Averaging window size; larger = more robust to noise but blurrier flow. |
| iterations | INT | 31–20 | Iterations at each pyramid level. |
| poly_n | INT | 53–11 | Neighborhood size for the polynomial expansion (5 or 7 are typical). |
| poly_sigma | FLOAT | 1.20.3–3 | Gaussian sigma of the polynomial expansion (~1.1 for poly_n=5, ~1.5 for poly_n=7). |
| window | COMBO | box (faster) | Averaging window type; gaussian is slower but yields smoother flow. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| flow | NPARRAY | HxWx2 float32 (dx, dy) displacement per pixel. |
| magnitude | NPARRAY | HxW float32 motion magnitude in pixels. |
| angle | NPARRAY | HxW float32 motion direction in RADIANS - feed 'CV Flow To Color' in its default radians mode. |