Nodes/ComfyUI CV/cv2.CV_16UC
ComfyUI Node

cv2.CV_16UC

The type code for depth maps and stereo disparity

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.CV_16UC
    • int
    ◄channels0►

    cv2.CV_16UC builds the OpenCV type code for an unsigned 16-bit array. In the ComfyUI CV pack it's the node cv2.CV_16UC: one INT input named channels, one INT output named int, wrapping the CV_16UC(channels) macro. No image goes in, no image comes out - it produces the single integer that other cv2 wrappers want when they ask for a dtype or ddepth.

    That sounds like trivia until you're in stereo or depth territory, where 16-bit unsigned is the storage convention. A stereo disparity map is classically written as CV_16U with the disparity scaled by 16 (or 256, in the newer half-pixel convention) so you keep fractional precision in an integer format. A depth map in millimetres is CV_16U too, because 0–65535 covers 65 metres at 1 mm resolution and the file is half the size of a float32 version - which is why 16-bit PNG depth maps are everywhere in the CV world, and why every depth pipeline in this ecosystem is full of nodes converting between a float tensor and a 16U file.

    How the code works

    The macro packs depth and channel count: CV_16U is depth 2, and every additional channel adds 8, so CV_16UC(1) is the plain 16-bit unsigned depth code and CV_16UC(3) gets you a three-channel version (a 16-bit-per-channel colour image, legal but rare - that's what a 16-bit-per-channel TIFF carries). You'll mostly pass 1.

    The channels widget defaults to 0, which is a trap: the macro computes channels − 1, so 0 yields a nonsense negative code that no cv2 function will accept. Set 1.

    The output is a plain INT. Since ComfyUI only lets you wire into inputs, the receiving node's widget has to be converted first - right-click it → Convert widget to input - and then the code can arrive over a link. This is also the point where these code-builder nodes are most honestly assessed: typing 2 into a ddepth field is easier than building it, and the pack's own philosophy admits it. The README states that the ~470 wrappers are auto-generated from cv2's type stubs and uncurated - every top-level function becomes a node, useful or not.

    Where 16U meets ComfyUI's data model

    Nowhere pleasant, and it's worth saying plainly. A ComfyUI IMAGE is a 3-channel float32 tensor in 0–1; a MASK is a single-channel float. A CV_16U array holding millimetres or scaled disparity fits neither, so it lives in NPARRAY space: produced by a cv2 wrapper, inspected with Inspect CV Data, manipulated with other cv2 nodes, and converted to something visible only at the end (CV Array → Image for a normalised preview, or the pack's depth-specific nodes if you're on the stereo path).

    One more pack-specific detail worth knowing before you plan a file-based round trip: cv2.imread and cv2.imwrite are deliberately hidden from this pack - the author blacklists every cv2 function that takes a host filesystem path, so images enter through Load Image and never through a node-supplied path. cv2.imdecode survives because it works on an in-memory buffer. So a 16U depth PNG can be loaded, but not by pointing a wrapper node at it.

    Installing it

    Manager → search the pack title (ComfyUI CV) → install → restart. Manual:

    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 ComfyUI with the V3 node API, and the contrib wheel. Note the headless part is not a limitation for this pack - no node in it uses a cv2 window - but a non-contrib wheel installed on top will strip the contrib submodules out of the shared site-packages/cv2 and take nodes with it (tools/repair_opencv_contrib.py --check/--apply).

    Common issues and troubleshooting

    Negative or absurd output value. channels is 0. The macro subtracts one from it internally; give it 1.

    The value won't connect to a widget. Convert the widget to an input first. A link dropped on a plain widget is ignored.

    Your 16U data looks black in a preview. 16-bit values only fill the top of the 8-bit display range once scaled - normalise before previewing rather than assuming the array is empty. Preview CV Array's normalize mode is there for exactly this.

    You wanted to save the 16-bit result to disk. The pack's path-taking functions are hidden on purpose. Route it through the array-to-image bridge and core Save Image, or add your own node - just don't expect to find cv2.imwrite in the node list.

    Categoryimage/CV/low-level/cv2 C

    Inputs (1)

    NameTypeDefaultDescription
    channelsINT0-2147483648–2147483647 - - -

    Outputs (1)

    NameTypeDescription
    intINT—