cv2.CV_16FC
Building the half-float type code OpenCV keeps asking for
- int
cv2.CV_16FC(channels) is not a converter, a viewer, or anything that touches an image. It's a type-code builder: give it a channel count, and it returns the single integer OpenCV uses to mean "16-bit float, this many channels". The ComfyUI CV node of the same name exposes that macro as a node - one INT in (channels), one INT out (int) - so you can wire the code into a socket instead of typing it.
That's the whole node, and the reason it's interesting is the reason it's confusing: OpenCV's type system packs depth and channel count into one number, computed as depth + ((channels − 1) << 3). CV_32F is depth 5; CV_32FC(3) is 21. The bare constants you've seen (cv2.CV_32F, cv2.CV_8U) are the depth-only half of that scheme; the C macros add the channel count. This pack's wrappers take that raw integer for every dtype / ddepth parameter, so something has to produce it.
Where 16-bit float actually shows up
Half precision is the DNN depth and the storage-format depth. It's what OpenCV's DNN module uses for reduced-precision blobs and what a lot of exported models carry their weights in, and it's the compact way to hold a float array when fp32 is overkill and int16's fixed point isn't what you want. In this pack that makes CV_16FC relevant when you're handing a dtype to an arithmetic or array-building wrapper, or setting an output type for a node whose tooltip says "see the combinations" - those parameters genuinely want a code, and 16F is a legal one.
Two practical cautions. First, 16F arrays are NPARRAY-only in ComfyUI: the IMAGE socket is a 3-channel float32 tensor, and the pack's bridges convert to that, so a half-float array has to stay in cv2 space. Second, half precision has ~3 decimal digits of mantissa - for anything you're going to threshold or accumulate, use CV_32FC and save yourself the debugging.
The inputs and outputs that matter
channels is an INT, and the widget default is 0 - which is not "one channel". Plug in 1, 3 or 4. The output socket is named int and carries the packed type code; to use it, right-click the receiving widget (Sobel's ddepth, cv2.add's dtype, and so on), choose Convert widget to input, and wire this node's output in. That's the standard ComfyUI mechanic for turning a value into a socket, and it's the only way a code-builder node earns its place in a graph.
Worth knowing: you can type the number directly if you know it, and most people do. These nodes exist because the pack aims to expose cv2 faithfully rather than to be convenient - the README says plainly that the ~470 raw wrappers are auto-generated from the type stubs and uncurated. cv2.CV_16FC is the illustration.
Don't confuse it with two neighbours in the same pack: CV DType (which reports an array's dtype name as a STRING) and CV Cast Array (which actually converts dtype, with or without scaling). This node builds a code; it changes nothing.
Installing it
Manager → search the pack title (ComfyUI CV) → install → restart. Or:
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 and a ComfyUI recent enough for the V3 node API. One detail specific to these constant nodes: the registry is generated from whatever cv2 the build exposes, and entries the build lacks are skipped. So if cv2.CV_16FC is missing from your node list, your OpenCV doesn't have it - reinstalling the pack won't help. And as always with this pack, don't let a non-contrib opencv-python wheel land on top of the contrib one; the shared site-packages/cv2 loses its contrib submodules and nodes vanish (tools/repair_opencv_contrib.py --check/--apply).
Common issues and troubleshooting
The output is a big negative number. You left channels at 0. The macro packs channels − 1 into the code, so 0 isn't a channel count at all - set 1, 3 or 4.
Nothing accepts the value. The receiving widget has to be an input first (right-click → Convert widget to input). Trying to drag a link onto a plain widget does nothing.
You expected a conversion. It's a code. Use CV Cast Array, or the wrapped arithmetic function's own dtype, to actually change an array's type.
The node isn't listed at all. Your installed cv2 doesn't expose this constant - check cv2.__version__ and whether you're on the contrib build.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| channels | INT | 0-2147483648–2147483647 | - - - |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| int | INT | — |