Nodes/ComfyUI CV/CV To Blob
ComfyUI Node

CV To Blob

The blob converter that doesn't flatten your float32 first

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV To Blob
  • nparray
  • blob
◄scale1.00►
◄target_width0►
◄target_height0►

An OpenCV DNN model almost never eats an image. It eats a blob: a 4-D (1, C, H, W) float32 tensor in NCHW order, scaled and mean-subtracted exactly the way the model was trained. CV To Blob is the node that makes that tensor from an NPARRAY in the pack, and the reason to pick it over the sibling CV DNN Blob From Image is a single word: float32.

Why there are two blob nodes

CV DNN Blob From Image starts from a ComfyUI IMAGE - pixels, 0-255 - and gives you the usual resize / mean subtraction / 1-255 scale / R-B swap switches. That's the right node when your model wants raw pixels normalized inside the blob.

CV To Blob starts from an array you have already prepared. No uint8 cast happens on the way in, so pre-normalized data survives. If you've run the image through ImageNet normalization, divided by 255 yourself, or fed it through a feature extractor's preprocessing chain, the other node quietly destroys that work. This one doesn't.

What it actually does

The mechanism is one call - cv2.dnn.blobFromImage - with the mean set to zero:

dsize = (target_width, target_height) if target_width and target_height else None
blob = cv2.dnn.blobFromImage(arr.astype(np.float32), scale, dsize, (0, 0, 0))

A 2-D grayscale array gets a trailing axis so it comes out (1, 1, H, W). Anything that isn't 2-D or 3-D raises instead of guessing.

The inputs and output that matter

Three of the four inputs you'll usually leave alone.

  • nparray - your (H, W, C) float32 array. This is the only required decision.
  • scale - a multiplier applied to every pixel. Leave it at 1.0 when your data is already in the model's input range, which is the whole point of the node. Set it to 0.00392-ish only if you're feeding raw 0-255 values.
  • target_width / target_height - resize on the way in. Both or neither: the code only builds a size when both are non-zero, so setting just the width silently keeps the original dimensions. That one bites people.
  • blob (output, NPARRAY) - the (1, C, H, W) float32 tensor. Wire it into cv2_dnn_setInput-style wrapper nodes, a cv2_dnn_Net forward pass, or any node in this pack that takes a blob. Going the other way afterwards, the pack has CV DNN Images From Blob when a network hands you a batch back.

Installing the pack

ComfyUI Manager is the fast route - search ComfyUI CV (the registry lists it as comfyui_cv from publisher bmad4ever). By hand:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv

Restart. The pack needs Python ≥ 3.12 and a reasonably current ComfyUI built on the V3 node API, and its one real dependency is opencv-contrib-python-headless~=5.0.0.93. Note contrib: if some other pack later installs plain opencv-python or opencv-python-headless over the top, the shared site-packages/cv2 gets replaced and contrib nodes vanish. The pack ships tools/repair_opencv_contrib.py --check / --apply for exactly that.

No models to download for this node. Nothing else in the pack matters here either.

Where people get burned

Channel order. There is no swap_rb switch on this node, and it passes no mean. OpenCV's own convention is BGR; a ComfyUI IMAGE is RGB. If your ONNX model was exported expecting one and you hand it the other, you get a subtly wrong answer rather than an error - colours are the tell. Fix it upstream with a cv2_cvtColor wrapper before the blob.

Half-configured resize. As above: one dimension set is the same as none. If a detection or classification result looks like it came from the wrong resolution, check both fields.

Aspect ratio. The resize does not letterbox. Squeezing 16:9 into a square makes your model work on stretched geometry - use CV DNN Letterbox for that job and keep this node for plain resizes.

Feeding it a batch. It wants one (H, W, C) image, not (N, H, W, C). If a DNN output gave you a batch, cut it apart first with CV Unstack Batch, process the frames, and blob them back.

The generic caveat of this whole pack applies: most of it is cv2.* wrapped as nodes, generated with heavy LLM assistance, and the author says outright that it isn't meant for production without reading the code first. For a 20-line blob wrapper that's a low-stakes warning - but it's why the node's own tooltips are worth trusting over your assumptions.

Categoryimage/CV/low-level

Inputs (4)

NameTypeDefaultDescription
nparrayNPARRAYHWC float32 array (H, W, C).
scaleFLOAT1.00Multiplier applied to each pixel. Use 1.0 for already-scaled or normalized data.
target_widthINT0Target width in pixels. 0 = keep input size.
target_heightINT0Target height in pixels. 0 = keep input size.

Outputs (1)

NameTypeDescription
blobNPARRAY4-D float32 blob shaped (1, C, H, W) ready for cv2.dnn.Net.setInput().