Nodes/ComfyUI CV/CV Cast Array
ComfyUI Node

CV Cast Array

The cast you need before OpenCV will do arithmetic on your arrays

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Cast Array
  • nparray
  • nparray
◄dtypeuint8►

This is the least exciting node in the pack and one of the most used. It converts an ndarray to another element type, the way cv2.convertTo does - values are rounded and clipped to the target range rather than wrapping around.

You'll meet it within an hour of doing anything numeric here, because cv2 arithmetic refuses mixed types. Take connected-components: connectedComponents hands you int32 labels. You want to multiply or mask those against a uint8 image. OpenCV won't do it. It doesn't warn, it doesn't upcast - it errors. So you cast one side, and this is the node that casts.

The saturation behaviour is the important detail. Casting 500.0 to uint8 gives you 255, not 244. If it wrapped, an out-of-range score would come back as a small dark value and quietly destroy a threshold; clipping fails loudly-ish instead of silently. It also means the node is safe to sprinkle around after any math you don't fully trust.

Inputs

Two, and you'll set the second one every time:

  • nparray - the array. Values survive; only the element type changes.
  • dtype - the target: uint8, uint16, int16, int32, float32, float64. Integer targets round and clip; float targets convert as-is.

That's the whole node. One NPARRAY in, one NPARRAY out.

When you reach for it

  • Feeding a uint8 mask node an int32 label array from connected components.
  • Normalising precision after a chain of float math - this pack's scores and arrays are float32 by convention, and a consumer that wants float64 or uint8 needs an explicit cast.
  • Tidying up after transforms. Boxes come out of CV BBoxes To Array as float32; a consumer that wants int32 coordinates (pixel indices, canvas draws) needs them rounded, and rounding is what the integer targets do.
  • Crossing between the array world and the image world, where dtype is part of the contract.

Because NPARRAY is this pack's native socket, nearly every wrapper node accepts one - but wrappers validate types where cv2 would have segmented a fault or worse. Casting at the boundary is cheaper than debugging after it.

Install

Manager → ComfyUI CV, 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, recent ComfyUI on the V3 node API. Nothing to download.

Where people get burned

Casting too early. Convert to uint8 and you've thrown away everything above 255 and everything fractional. In a chain like normalise → multiply → threshold, the cast belongs at the end, and a mid-chain cast is the reason a threshold that "should work" doesn't.

Assuming wrap-around from other tools. If you've used numpy's astype() directly, that truncates toward zero and wraps on overflow in the same situation where this saturates and rounds. 2.7 → astype(int) = 2, this node's int target gives 3. Different answers, and both are correct for their own definition - just don't carry the assumption across.

Silent precision loss the other way. Casting float64 down to float32 halves your significant digits. Fine for pixel coordinates, occasionally not fine for accumulating a trajectory across hundreds of frames.

Categoryimage/CV/low-level

Inputs (2)

NameTypeDefaultDescription
nparrayNPARRAYArray to convert; values survive, only the element type changes.
dtypeCOMBOuint8Target element type. Integer targets round and clip (saturate); float targets convert values as-is.

Outputs (1)

NameTypeDescription
nparrayNPARRAY—