cv2.CV_8UC
The decoder ring for OpenCV's type codes
- int
This node does not make an image. It returns a single integer - the OpenCV type code for an 8-bit unsigned matrix with the channel count you name - and that number is how you read half of the errors this pack will throw at you. (-215:Assertion failed) type == CV_8UC1 stops being cryptic once you know CV_8UC1 is 0 and CV_8UC3 is 16.
What it actually computes
The raw wrapper is a straight call to cv2.CV_8UC(channels), which is OpenCV's <depth>C(n) form of CV_MAKETYPE. The code packs the depth into the low bits and the channel count into the high bits:
type_code = depth + ((channels - 1) << 3)
With CV_8U == 0 that gives CV_8UC(1) == 0, CV_8UC(3) == 16, CV_8UC(4) == 24. This is worth internalising because it explains two things people get wrong constantly: a three-channel 8-bit image is not type 3, and CV_8U and CV_8UC1 are the same value.
You can confirm the whole thing outside ComfyUI in one line - this is literally what the node calls:
python3 -c "import cv2; print(cv2.CV_8UC(1), cv2.CV_8UC(3), cv2.CV_8UC(4))"
# 0 16 24
The one input that matters
channels is an INT and it is the channel count: 1 for a mask or a Bayer plane, 3 for BGR, 4 for BGRA. Set it before you run. The auto-generated default is 0, which is not a valid channel count, and a raw wrapper does not validate your arguments - you'll get a nonsense code ((0 - 1) << 3 is not a type anything accepts downstream) rather than a friendly error.
The output is a single int. Wire it into anything that takes an INT - most usefully cv2.CV_MAKETYPE's depth input, which wants exactly this kind of depth code, or any other INT parameter in the pack that takes a raw type number.
Where this is actually the right node
Honestly? Two places. One is diagnostics: when a cv2 call rejects your array, the assertion names a type constant, and this is the node that turns that name into a number you can compare against. The other is the type-code chain - cv2.CV_8UC(1) gives you the plain CV_8U depth code that CV_MAKETYPE composes with a channel count.
The pack's curated depth inputs (ddepth, dtype, mtype and friends) are dropdowns with named options like CV_8U or same as input, and they resolve the name themselves. You don't wire a number into those, so don't go looking for a slot to plug this into there - reaching for the dropdown label is the right move.
Install
ComfyUI Manager → Install Custom Nodes → search ComfyUI CV (published by bmad4ever). Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Then restart ComfyUI. This pack needs Python ≥ 3.12 and a recent ComfyUI built on the V3 node API; the contrib wheel is the only real dependency, and numpy/torch are already there. Nothing here needs a downloaded model. There are ~470 auto-generated cv2.* wrappers in this pack plus curated high-level nodes; it's GPL-3.0, forked from geroldmeisinger/opencv-comfyui, written largely by LLMs, and the author states plainly it isn't production-ready and gets updates whenever they feel like it. That matters less for a constant node than for the rest of the pack, but you should know it.
Common issues
- The node is missing from your menu. The pack resolves every generated wrapper against your installed
cv2at import time and silently drops the ones your build doesn't expose. Since this one is core, a missing node usually means the pack didn't load at all - check the console for an import error, and confirm Python is 3.12+. - Your result is garbage. You left
channelson 0. Set it. - You're feeding this into a dropdown and ComfyUI rejects the link. Correct behaviour: combos take option labels, not numbers.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| channels | INT | 0-2147483648–2147483647 | - - - |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| int | INT | — |