Nodes/ComfyUI CV/cv2.findNonZero
ComfyUI Node

cv2.findNonZero

Cv2.findNonZero

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.findNonZero
  • src
  • nparray

One input, one output, no parameters. cv2.findNonZero takes a single-channel array and returns the coordinates of every non-zero pixel as an Nx1x2 array. That's it - and that's exactly why it's useful: a mask is how you know something in ComfyUI, and a point list is how you measure it.

The pack's own clock-reading exercise is the model use case. The hands get reduced to a one-pixel-wide skeleton by CV Skeletonize, and then cv2.findNonZero - the node is literally titled "Skeleton pixels as a point set" on that canvas - converts that skeleton into coordinates, which CV Filter Points By Distance then clusters into hand tips. Try doing that with a mask directly and you're writing your own pixel loop.

Inputs and outputs

src is a single-channel array and it is a data socket: NPARRAY only, no IMAGE or MASK links, as the input's tooltip states. That's the practical first thing to internalise. If your mask is a ComfyUI MASK, run it through Mask → CV Array (or Image → CV Array) first - one extra box, and it keeps the types honest. Multi-channel input won't do what you want either: the function is defined for a single channel, so collapse with cv2_cvtColor if you're coming from colour.

The output nparray is the list of (x, y) coordinates of the non-zero pixels, Nx1x2, in scan order. Sparse by construction - it only contains what was lit. Feed it to CV DrawPoints to see it, to CV Point Cloud Nearest Distance, CV Fit Points To Box or the filter/distance nodes for measurement, or to CV Sample Array At Points if you want to read pixel values at those locations.

The behaviour worth planning for

A mask with nothing set in it has nothing to report. Expect an empty result - and don't wire that straight into a node that assumes at least one point, because "no points" is a legitimate outcome and a downstream min/max or fit is going to be unhappy about it. Checking the count first (Inspect CV Data prints shape and statistics) is cheap insurance, and if you're building a loop over video frames, that's the branch you gate on: silent hand-detection failure is exactly the failure the clock exercise checks for.

Second thing: this is not a contour finder. findNonZero gives you every pixel, so a full-frame binary mask gives you a very large array, and while it's linear work, the point count is the point count. When you want shapes - areas, bounding boxes, per-blob identity - you want CV Find Contours or CV Connected Components (Split Mask) instead. findNonZero is the right tool when the geometry is thin (skeleton, single-pixel curve, sparse markers) or when you genuinely need per-pixel coordinates.

Install

Ships with the pack; nothing extra to download.

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

ComfyUI Manager: search "ComfyUI CV", install, restart. Needs Python ≥ 3.12 and a ComfyUI on the V3 node API - an older core simply won't load the pack.

Common issues

"Only an NPARRAY link is accepted." You connected an IMAGE or MASK. Convert it first; the socket is deliberately narrow because a picture and a coordinate list are different things, and letting one masquerade as the other makes graphs incomprehensible.

Empty output, node runs fine. Nothing in the input was non-zero. Check upstream - threshold direction, a morphology step that ate the feature, an ROI mask that shifted.

Wrong coordinates. Remember the array is in the (x, y) order cv2 uses, which is the opposite of how numpy shapes usually read. If your points land transposed relative to the image, this is why, and CV Permute Axes is the honest fix rather than swapping widgets somewhere downstream.

Nodes from the pack's contrib areas went missing. A non-contrib opencv-python wheel installed over the contrib one empties the contrib submodules - all OpenCV Python wheels share one site-packages/cv2. The pack ships tools/repair_opencv_contrib.py: --check to diagnose, --apply to fix.

Categoryimage/CV/low-level/cv2 F

Inputs (1)

NameTypeDefaultDescription
srcNPARRAYsingle-channel array A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.

Outputs (1)

NameTypeDescription
nparrayNPARRAY—