Mask → CV Array
Get your mask out of ComfyUI's type system and into numpy
- mask
- nparray
ComfyUI's MASK type is a tensor with a specific shape and a 0–1 float range. OpenCV wants a 2-D uint8 array. Those two facts are responsible for a surprising amount of quiet confusion, because ComfyUI will happily pass a mask around for the whole graph and then the moment you touch a cv2.* node you find nothing matches.
This node is one of the pack's converters: MASK in, raw single-channel ndarray out. It exists so the ~470 generated cv2.* wrappers - and the ~200 curated nodes - can be fed something they understand.
How it works
Pick a frame with batch_index (clamped to the batch size, so an out-of-range index is safe rather than an exception), then pick a dtype:
- uint8 (0-255) - what almost every
cv2call wants. Thresholds, morphology,findContours,distanceTransform: all uint8. - float32 (0-1) - keeps the fractional values ComfyUI's mask already carries. Use it when you're doing float arithmetic and don't want a mask's soft edge quantized into 256 steps.
batch_index is a widget rather than a socket, and that's the practical catch of the node: it emits one frame. If you have a 16-frame mask batch and you want all of them in array-land, this isn't the node - use the batch-level bridges (Image Batch -> CV Batch and friends) so the batch survives as a 4-D array.
The inputs and outputs
Three inputs, one output:
mask(MASK, required) - one frame is taken.dtype(COMBO,uint8 (0-255)orfloat32 (0-1)).batch_index(INT, default 0).nparrayout - the NPARRAY socket this whole pack runs on.
That NPARRAY is what you wire into cv2_threshold, cv2_Canny, cv2_findContours' inputs, or any of the curated contour/moment nodes. Going the other way later, CV Array -> Mask brings it back (and min-max normalizes floats on the way).
Install
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
Or ComfyUI Manager → search ComfyUI CV. Restart, reload the page. Dependencies are just opencv-contrib-python-headless~=5.0.0.93 (plus numpy and torch), and the pack wants Python ≥ 3.12 on a ComfyUI recent enough to support the V3 node API. Nothing to download.
Common issues
A "black" mask that isn't. If you convert with float32 and then feed it into a node expecting a binary image, a mask whose values sit at 0.0–1.0 reads as almost entirely black to anything using a 0–255 assumption. That's not a bug in either node - it's the dtype choice. uint8 for cv2, float32 for math, and know which side of the line you're on.
Only frame 0 arrives. The single most common report-shaped confusion with converters like this one. Check batch_index.
Contrib nodes vanish after an OpenCV update. Worth knowing for every article in this pack: all four OpenCV wheels (opencv-python, opencv-python-headless, opencv-contrib-python and its headless twin) share one site-packages/cv2. Install a non-contrib wheel over a contrib one and the contrib submodules silently empty out - the contrib nodes just disappear from the menu, with no error at install time. The pack ships a diagnostic for it:
python tools/repair_opencv_contrib.py --check # diagnose
python tools/repair_opencv_contrib.py --apply # repair
People hit the plain-cv2 problem constantly in ComfyUI - the standard community advice is always the headless wheel for a backend, precisely because nothing here draws a window. This pack blacklists imshow/waitKey outright, which is why headless is the declared dependency.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | MASK to convert. One frame is taken (see batch_index). | |
| dtype | COMBO | uint8 (0-255) | uint8 for most cv2 functions; float32 (0-1) to preserve fractional mask values for downstream float math. |
| batch_index | INT | 00–4095 | Which mask of the batch to convert. Clamped to the batch size. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |