Nodes/ComfyUI CV/cv2.patchNaNs
ComfyUI Node

cv2.patchNaNs

The one-line fix for the NaN that just ate your depth map

By bmad4ever·Created 4 months ago·Updated 14 days ago· 1
cv2.patchNaNs
  • a
  • nparray
◄val0.0000►

You know the shape of this bug. Something divided by zero, or a depth value had no measurement behind it, and now there's a NaN sitting in your float array. You pass it to a blur, and the blur is NaN. You pass that to a normalise, and it's still NaN, and eventually a black frame, a black latent, or a node that raises with a message about non-finite values. NaN is contagious and it never announces itself.

cv2.patchNaNs is the mop. It walks the array and replaces every NaN with a number you choose - 0 by default. That's it. No sibling features, no flags. That's why the node is three lines of UI.

Where your NaN came from

The usual suspects in this pack's corner of the graph are the geometric and depth ones: unprojection (CV Depth to 3D Points), triangulation, disparity maps that were filtered or interpolated, warps and remaps reading out of bounds - and the pack's own rescaleDepth wrapper, whose documented behaviour is that "zeros become NaN" when it turns millimetre depth into metres. Any of those can hand you an array with holes represented as NaN instead of as a sentinel.

If you want to know whether a NaN is present before deciding to patch, the pack has a few other things: the CV Array Statistic node (a mean or min of NaN is NaN - the text output tells you in words), and finiteMask from cv2 5.0, which returns 255 where every channel is finite and 0 wherever a NaN or Inf appears, described by the pack as "the standard guard in front of a cv2 op that would propagate them".

Input, output, and the one knob

a is the array. NPARRAY, IMAGE or MASK all link, but a ComfyUI IMAGE resolves to an 8-bit BGR array, and an integer type cannot hold a NaN - so if you're feeding this an image you're feeding it an array with nothing to patch. It's a float-array tool; you'll use it on the NPARRAY output of a cv2 call, and CV Cast Array is there if something upstream left you in the wrong dtype, since cv2 wants CV_32F or CV_64F.

val is what NaNs become. It comes preset to 0.0 and it's an advanced input, so it's hidden until you open "show advanced inputs" in the node's context menu. Zero is right for "make the arithmetic stop failing". It is not right if this array is a depth map you intend to measure - zero is a legitimate depth, and you've just declared that every hole is at the camera. For that case, patch to something the downstream node recognises as invalid (a large sentinel), or fill the holes properly first with CV Disparity Interpolate (Edge-Aware).

Output is a single nparray. Note what that means: even if you link an IMAGE in, this wrapper is not in the pack's type-preserving list, so the result comes back on an NPARRAY socket. Bridge to pixels with CV Array → Image, or preview with Preview CV Array.

Two behaviours worth knowing

cv2 patches in place; this wrapper doesn't touch your input. cv2.patchNaNs writes into the Mat you hand it, and a mutated array here would be another node's cached output - so the pack hands cv2 a private copy and returns the patched result. Your upstream array stays as it was, which is what you want if you're branching: one branch patched, one left raw.

It patches NaN, and only NaN. Inf is a different value and stays put. If an array can contain both - and overflow in a float pipeline can produce Inf just as easily as a divide-by-zero produces NaN - patch, then check again with finiteMask rather than assuming it's clean.

There's also no per-frame batch handling in this one: an IMAGE batch gives you frame 0. If you're cleaning a clip, that's a per-frame loop or a curated batch node, not this.

Installing

ComfyUI Manager → search ComfyUI CV → Install → restart. Or by hand:

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

Python ≥ 3.12, a recent ComfyUI (the pack is built on the V3 node API), OpenCV untouched-by-sibling-packages. patchNaNs is a core cv2 function, so unlike the contrib nodes in this pack it survives a non-contrib wheel - but don't test that theory, because half the pack won't.

In the menu under: image/CV/low-level/cv2 P, display name cv2.patchNaNs.

Categoryimage/CV/low-level/cv2 P

Inputs (2)

NameTypeDefaultDescription
aNPARRAY,IMAGE,MASKInput/output matrix (CV_32F or CV_64F type). 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.
valoptFLOAT0.0000-1e+38–1e+38Value used to replace NaNs (defaults to 0). Preset to the OpenCV default (0.0).

Outputs (1)

NameTypeDescription
nparrayNPARRAY—